]> granicus.if.org Git - clang/commitdiff
Don't crash when a reserved global placement operator new is paired
authorJohn McCall <rjmccall@apple.com>
Tue, 29 Sep 2015 23:55:17 +0000 (23:55 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 29 Sep 2015 23:55:17 +0000 (23:55 +0000)
with a non-reserved operator delete in a new-expression.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@248862 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprCXX.cpp
test/CodeGenCXX/exceptions.cpp

index 7e0a6abc23b96350a9ee29a42b11a66655908bdf..599dc9a8dbc3d211f2f50d07a6c746d54a352b18 100644 (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>();
index d6b5942dd23d29ce207c56d37bb5ee652bedd1e4..ff76b11350db76f6b49eb935918401f09cd61725 100644 (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 }