Fix a lot of problems with the partial destruction of arrays:
- an off-by-one error in emission of irregular array limits for
InitListExprs
- use an EH partial-destruction cleanup within the normal
array-destruction cleanup
- get the branch destinations right for the empty check
Also some refactoring which unfortunately obscures these changes.
llvm-svn: 134890
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 1d473f6..062e13d 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -689,8 +689,8 @@
endOfInit = CGF.CreateTempAlloca(begin->getType(),
"arrayinit.endOfInit");
Builder.CreateStore(begin, endOfInit);
- CGF.pushPartialArrayCleanup(begin, elementType,
- CGF.getDestroyer(dtorKind), endOfInit);
+ CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType,
+ CGF.getDestroyer(dtorKind));
cleanup = CGF.EHStack.stable_begin();
// Otherwise, remember that we didn't need a cleanup.
@@ -710,16 +710,17 @@
// Emit the explicit initializers.
for (uint64_t i = 0; i != NumInitElements; ++i) {
// Advance to the next element.
- if (i > 0)
+ if (i > 0) {
element = Builder.CreateInBoundsGEP(element, one, "arrayinit.element");
+ // Tell the cleanup that it needs to destroy up to this
+ // element. TODO: some of these stores can be trivially
+ // observed to be unnecessary.
+ if (endOfInit) Builder.CreateStore(element, endOfInit);
+ }
+
LValue elementLV = CGF.MakeAddrLValue(element, elementType);
EmitInitializationToLValue(E->getInit(i), elementLV);
-
- // Tell the cleanup that it needs to destroy this element.
- // TODO: some of these stores can be trivially observed to be
- // unnecessary.
- if (endOfInit) Builder.CreateStore(element, endOfInit);
}
// Check whether there's a non-trivial array-fill expression.
@@ -743,8 +744,10 @@
// do { *array++ = filler; } while (array != end);
// Advance to the start of the rest of the array.
- if (NumInitElements)
+ if (NumInitElements) {
element = Builder.CreateInBoundsGEP(element, one, "arrayinit.start");
+ if (endOfInit) Builder.CreateStore(element, endOfInit);
+ }
// Compute the end of the array.
llvm::Value *end = Builder.CreateInBoundsGEP(begin,
@@ -767,13 +770,13 @@
else
EmitNullInitializationToLValue(elementLV);
- // Tell the EH cleanup that we finished with that element.
- if (endOfInit) Builder.CreateStore(element, endOfInit);
-
// Move on to the next element.
llvm::Value *nextElement =
Builder.CreateInBoundsGEP(currentElement, one, "arrayinit.next");
+ // Tell the EH cleanup that we finished with the last element.
+ if (endOfInit) Builder.CreateStore(nextElement, endOfInit);
+
// Leave the loop if we're done.
llvm::Value *done = Builder.CreateICmpEQ(nextElement, end,
"arrayinit.done");