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:
John McCall 2015-09-29 23:55:17 +00:00
parent c1db67e218
commit 53dcf94d05
2 changed files with 32 additions and 2 deletions

View File

@ -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>();

View File

@ -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 }