[cfe-commits] r135021 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/delete.cpp

Douglas Gregor dgregor at apple.com
Tue Jul 12 17:54:47 PDT 2011


Author: dgregor
Date: Tue Jul 12 19:54:47 2011
New Revision: 135021

URL: http://llvm.org/viewvc/llvm-project?rev=135021&view=rev
Log:
When compiling ::delete for a class with a virtual destructor, call
the complete destructor and then invoke the global delete
operator. Previously, we would invoke the deleting destructor, which
calls the wrong delete operator. Fixes PR10341.

Modified:
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/delete.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=135021&r1=135020&r2=135021&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Tue Jul 12 19:54:47 2011
@@ -1211,7 +1211,8 @@
 static void EmitObjectDelete(CodeGenFunction &CGF,
                              const FunctionDecl *OperatorDelete,
                              llvm::Value *Ptr,
-                             QualType ElementType) {
+                             QualType ElementType,
+                             bool UseGlobalDelete) {
   // Find the destructor for the type, if applicable.  If the
   // destructor is virtual, we'll just emit the vcall and return.
   const CXXDestructorDecl *Dtor = 0;
@@ -1221,17 +1222,30 @@
       Dtor = RD->getDestructor();
 
       if (Dtor->isVirtual()) {
+        if (UseGlobalDelete) {
+          // If we're supposed to call the global delete, make sure we do so
+          // even if the destructor throws.
+          CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
+                                                    Ptr, OperatorDelete, 
+                                                    ElementType);
+        }
+        
         const llvm::Type *Ty =
           CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,
                                                                Dtor_Complete),
                                          /*isVariadic=*/false);
           
         llvm::Value *Callee
-          = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
+          = CGF.BuildVirtualCall(Dtor, 
+                                 UseGlobalDelete? Dtor_Complete : Dtor_Deleting,
+                                 Ptr, Ty);
         CGF.EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,
                               0, 0);
 
-        // The dtor took care of deleting the object.
+        if (UseGlobalDelete) {
+          CGF.PopCleanupBlock();
+        }
+        
         return;
       }
     }
@@ -1477,7 +1491,8 @@
   if (E->isArrayForm()) {
     EmitArrayDelete(*this, E, Ptr, DeleteTy);
   } else {
-    EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy);
+    EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy,
+                     E->isGlobalDelete());
   }
 
   EmitBlock(DeleteEnd);

Modified: cfe/trunk/test/CodeGenCXX/delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/delete.cpp?rev=135021&r1=135020&r2=135021&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/delete.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/delete.cpp Tue Jul 12 19:54:47 2011
@@ -112,3 +112,22 @@
     delete a;
   }
 }
+
+namespace test4 {
+  // PR10341: ::delete with a virtual destructor
+  struct X {
+    virtual ~X();
+    void operator delete (void *);
+  };
+
+  // CHECK: define void @_ZN5test421global_delete_virtualEPNS_1XE
+  void global_delete_virtual(X *xp) {
+    // CHECK: [[VTABLE:%.*]] = load void ([[X:%.*]])***
+    // CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds void ([[X]])** [[VTABLE]], i64 0
+    // CHECK-NEXT: [[VFNPTR:%.*]] = load void ([[X]])** [[VFN]]
+    // CHECK-NEXT: call void [[VFNPTR]]([[X]] [[OBJ:%.*]])
+    // CHECK-NEXT: [[OBJVOID:%.*]] = bitcast [[X]] [[OBJ]] to i8*
+    // CHECK-NEXT: call void @_ZdlPv(i8* [[OBJVOID]]) nounwind
+    ::delete xp;
+  }
+}





More information about the cfe-commits mailing list