]> granicus.if.org Git - clang/commitdiff
Code gen for arrady delete operator. Fixes pr5472.
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 13 Nov 2009 19:27:47 +0000 (19:27 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 13 Nov 2009 19:27:47 +0000 (19:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88680 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CGCXXExpr.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/array-operator-delete-call.cpp [new file with mode: 0644]

index 9b83f00173510d3646a08fc808732fb9d9c0ce9b..c23ad597649184e8bdbb77686b65508edc4ede9a 100644 (file)
@@ -521,16 +521,25 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
                                            llvm::Value *This) {
   const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
   assert(CA && "Do we support VLA for destruction ?");
+  uint64_t ElementCount = getContext().getConstantArrayElementCount(CA);
+  llvm::Value* ElementCountPtr =
+    llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount);
+  EmitCXXAggrDestructorCall(D, ElementCountPtr, This);
+}
+
+/// EmitCXXAggrDestructorCall - calls the default destructor on array
+/// elements in reverse order of construction.
+void
+CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+                                           llvm::Value *UpperCount,
+                                           llvm::Value *This) {
   llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
                                             1);
-  uint64_t ElementCount = getContext().getConstantArrayElementCount(CA);
   // Create a temporary for the loop index and initialize it with count of
   // array elements.
   llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
                                            "loop.index");
   // Index = ElementCount;
-  llvm::Value* UpperCount =
-    llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount);
   Builder.CreateStore(UpperCount, IndexPtr, false);
 
   // Start the loop with a block that tests the condition.
@@ -574,7 +583,7 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
   EmitBlock(AfterFor, true);
 }
 
-/// EmitCXXAggrDestructorCall - Generates a helper function which when invoked,
+/// GenerateCXXAggrDestructorHelper - Generates a helper function which when invoked,
 /// calls the default destructor on array elements in reverse order of 
 /// construction.
 llvm::Constant * 
index a21149973dae01895edff967c85a771527faf23a..d9275fc0a76fcf2ef7970c411c62fb4075318c87 100644 (file)
@@ -235,11 +235,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
 }
 
 void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
-  if (E->isArrayForm()) {
-    ErrorUnsupported(E, "delete[] expression");
-    return;
-  };
-
+  
   // Get at the argument before we performed the implicit conversion
   // to void*.
   const Expr *Arg = E->getArgument();
@@ -273,7 +269,33 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
     if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
       if (!RD->hasTrivialDestructor()) {
         const CXXDestructorDecl *Dtor = RD->getDestructor(getContext());
-        if (Dtor->isVirtual()) {
+        if (E->isArrayForm()) {
+          QualType SizeTy = getContext().getSizeType();
+          uint64_t CookiePadding = std::max(getContext().getTypeSize(SizeTy),
+                static_cast<uint64_t>(getContext().getTypeAlign(DeleteTy))) / 8;
+          if (CookiePadding) {
+            llvm::Type *Ptr8Ty = 
+              llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
+            uint64_t CookieOffset =
+              CookiePadding - getContext().getTypeSize(SizeTy) / 8;
+            llvm::Value *AllocatedObjectPtr = 
+              Builder.CreateConstInBoundsGEP1_64(
+                            Builder.CreateBitCast(Ptr, Ptr8Ty), -CookiePadding);
+            llvm::Value *NumElementsPtr =
+              Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr, 
+                                                 CookieOffset);
+            
+            NumElementsPtr =
+              Builder.CreateBitCast(NumElementsPtr,
+                            llvm::Type::getInt64Ty(VMContext)->getPointerTo());
+            llvm::Value *NumElements = 
+              Builder.CreateLoad(NumElementsPtr);
+            assert (!Dtor->isVirtual() && "delete [] with virtual dtors NYI");
+            EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
+            Ptr = AllocatedObjectPtr;
+          }
+        }
+        else if (Dtor->isVirtual()) {
           const llvm::Type *Ty =
             CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
                                            /*isVariadic=*/false);
index c69dcb505ac9c471a548715a580792c6ca1cade1..5f8a1969f91ea8caf3f370ec0ff3407b838fff8b 100644 (file)
@@ -646,6 +646,10 @@ public:
                                  const ArrayType *Array,
                                  llvm::Value *This);
 
+  void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+                                 llvm::Value *NumElements,
+                                 llvm::Value *This);
+
   llvm::Constant * GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
                                                 const ArrayType *Array,
                                                 llvm::Value *This);
diff --git a/test/CodeGenCXX/array-operator-delete-call.cpp b/test/CodeGenCXX/array-operator-delete-call.cpp
new file mode 100644 (file)
index 0000000..d394aa1
--- /dev/null
@@ -0,0 +1,52 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+
+extern "C" int printf(...);
+
+int count;
+
+struct S {
+  S() : iS (++count) { printf("S::S(%d)\n", iS); }
+  ~S() { printf("S::~S(%d)\n", iS); }
+  int iS;
+};
+
+struct COST
+{
+  S *cost;
+  unsigned *cost_val;
+
+  ~COST();
+  COST();
+};
+
+
+COST::COST()
+{
+  cost = new S[3];
+  cost_val = new unsigned[10];
+}
+
+COST::~COST()
+{
+  if (cost) {
+   delete [] cost;
+  }
+  if (cost_val)
+    delete [] cost_val;
+}
+
+COST c1;
+
+int main()
+{
+  COST c3;
+}
+COST c2;
+
+// CHECK-LP64: call     __ZdaPv
+
+// CHECK-LP32: call     L__ZdaPv
+