forked from OSchip/llvm-project
Don't crash when a reserved global placement operator new is paired
with a non-reserved operator delete in a new-expression. llvm-svn: 248862
This commit is contained in:
parent
c1db67e218
commit
53dcf94d05
|
@ -1289,9 +1289,11 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
|||
Address allocation = Address::invalid();
|
||||
CallArgList allocatorArgs;
|
||||
if (allocator->isReservedGlobalPlacementOperator()) {
|
||||
assert(E->getNumPlacementArgs() == 1);
|
||||
const Expr *arg = *E->placement_arguments().begin();
|
||||
|
||||
AlignmentSource alignSource;
|
||||
allocation = EmitPointerWithAlignment(*E->placement_arguments().begin(),
|
||||
&alignSource);
|
||||
allocation = EmitPointerWithAlignment(arg, &alignSource);
|
||||
|
||||
// The pointer expression will, in many cases, be an opaque void*.
|
||||
// In these cases, discard the computed alignment and use the
|
||||
|
@ -1301,6 +1303,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
|||
getContext().getTypeAlignInChars(allocType));
|
||||
}
|
||||
|
||||
// Set up allocatorArgs for the call to operator delete if it's not
|
||||
// the reserved global operator.
|
||||
if (E->getOperatorDelete() &&
|
||||
!E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
|
||||
allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType());
|
||||
allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType());
|
||||
}
|
||||
|
||||
} else {
|
||||
const FunctionProtoType *allocatorType =
|
||||
allocator->getType()->castAs<FunctionProtoType>();
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
typedef __typeof(sizeof(0)) size_t;
|
||||
|
||||
// Declare the reserved global placement new.
|
||||
void *operator new(size_t, void*);
|
||||
|
||||
// This just shouldn't crash.
|
||||
namespace test0 {
|
||||
struct allocator {
|
||||
|
@ -526,4 +529,21 @@ namespace test11 {
|
|||
// (After this is a terminate landingpad.)
|
||||
}
|
||||
|
||||
namespace test12 {
|
||||
struct A {
|
||||
void operator delete(void *, void *);
|
||||
A();
|
||||
};
|
||||
|
||||
A *test(void *ptr) {
|
||||
return new (ptr) A();
|
||||
}
|
||||
// CHECK-LABEL: define {{.*}} @_ZN6test124testEPv(
|
||||
// CHECK: [[PTR:%.*]] = load i8*, i8*
|
||||
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[PTR]] to [[A:%.*]]*
|
||||
// CHECK-NEXT: invoke void @_ZN6test121AC1Ev([[A]]* [[CAST]])
|
||||
// CHECK: ret [[A]]* [[CAST]]
|
||||
// CHECK: invoke void @_ZN6test121AdlEPvS1_(i8* [[PTR]], i8* [[PTR]])
|
||||
}
|
||||
|
||||
// CHECK: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind }
|
||||
|
|
Loading…
Reference in New Issue