summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-08-20 23:02:58 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-08-20 23:02:58 +0000
commit1c536bf6bbb0cdc039cff754825b36f9abfe0629 (patch)
treef4adc662ec282cfe7e928ce7d5a8f291b8819921
parent37b372b76a3fafe77186d7e6079e5642e2017478 (diff)
Patch to ir-gen destruction of array member elements in revers order
of their construction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79571 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGCXX.cpp60
-rw-r--r--test/CodeGenCXX/constructor-for-array-members.cpp2
2 files changed, 61 insertions, 1 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 72aa9fc090..8b1f2fc1fe 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -412,10 +412,70 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
EmitBlock(AfterFor, true);
}
+/// EmitCXXAggrDestructorCall - calls the default destructor on array
+/// elements in reverse order of construction.
void
CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
const ArrayType *Array,
llvm::Value *This) {
+ const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
+ assert(CA && "Do we support VLA for destruction ?");
+ llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ 1);
+ uint64_t ElementCount = 1;
+ const ConstantArrayType *CAW = CA;
+ do {
+ ElementCount *= CAW->getSize().getZExtValue();
+ CAW = dyn_cast<ConstantArrayType>(CAW->getElementType());
+ } while (CAW);
+ // 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.
+ llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
+ llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
+
+ EmitBlock(CondBlock);
+
+ llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+
+ // Generate: if (loop-index != 0 fall to the loop body,
+ // otherwise, go to the block after the for-loop.
+ llvm::Value* zeroConstant =
+ llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext));
+ llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
+ llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant,
+ "isne");
+ // If the condition is true, execute the body.
+ Builder.CreateCondBr(IsNE, ForBody, AfterFor);
+
+ EmitBlock(ForBody);
+
+ llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
+ // Inside the loop body, emit the constructor call on the array element.
+ Counter = Builder.CreateLoad(IndexPtr);
+ Counter = Builder.CreateSub(Counter, One);
+ llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
+ EmitCXXDestructorCall(D, Dtor_Complete, Address);
+
+ EmitBlock(ContinueBlock);
+
+ // Emit the decrement of the loop counter.
+ Counter = Builder.CreateLoad(IndexPtr);
+ Counter = Builder.CreateSub(Counter, One, "dec");
+ Builder.CreateStore(Counter, IndexPtr, false);
+
+ // Finally, branch back up to the condition for the next iteration.
+ EmitBranch(CondBlock);
+
+ // Emit the fall-through block.
+ EmitBlock(AfterFor, true);
}
void
diff --git a/test/CodeGenCXX/constructor-for-array-members.cpp b/test/CodeGenCXX/constructor-for-array-members.cpp
index f0f7f51ac0..9d9e2c8290 100644
--- a/test/CodeGenCXX/constructor-for-array-members.cpp
+++ b/test/CodeGenCXX/constructor-for-array-members.cpp
@@ -11,7 +11,7 @@ float vf = 1.00;
struct S {
S() : iS(i++), f1(vf++) {printf("S::S()\n");}
-// ~S(){printf("S::~S()\n"); }
+ ~S(){printf("S::~S(iS = %d f1 = %f)\n", iS, f1); }
int iS;
float f1;
};