diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-22 17:37:59 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-22 17:37:59 +0000 |
commit | 674c77e5552ebb1bd3ae9ceaa3c6fd5e248ffea9 (patch) | |
tree | 3c05ad9f2e3069ba81781385763122670872e644 /clang/lib/CodeGen/CGExprCXX.cpp | |
parent | f862eb6a9ffc9e9c0d40182d1f18439998c97abc (diff) | |
download | bcm5719-llvm-674c77e5552ebb1bd3ae9ceaa3c6fd5e248ffea9.tar.gz bcm5719-llvm-674c77e5552ebb1bd3ae9ceaa3c6fd5e248ffea9.zip |
Unwind path cleanup for array new list initializers.
llvm-svn: 151172
Diffstat (limited to 'clang/lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index af9c7662386..00fbe9bfb0a 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -804,12 +804,32 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E, unsigned initializerElements = 0; const Expr *Init = E->getInitializer(); + llvm::AllocaInst *endOfInit = 0; + QualType::DestructionKind dtorKind = elementType.isDestructedType(); + EHScopeStack::stable_iterator cleanup; + llvm::Instruction *cleanupDominator = 0; // If the initializer is an initializer list, first do the explicit elements. if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { initializerElements = ILE->getNumInits(); - QualType elementType = E->getAllocatedType(); - // FIXME: exception-safety for the explicit initializers + + // Enter a partial-destruction cleanup if necessary. + if (needsEHCleanup(dtorKind)) { + // In principle we could tell the cleanup where we are more + // directly, but the control flow can get so varied here that it + // would actually be quite complex. Therefore we go through an + // alloca. + endOfInit = CreateTempAlloca(beginPtr->getType(), "array.endOfInit"); + cleanupDominator = Builder.CreateStore(beginPtr, endOfInit); + pushIrregularPartialArrayCleanup(beginPtr, endOfInit, elementType, + getDestroyer(dtorKind)); + cleanup = EHStack.stable_begin(); + } + for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) { + // 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(explicitPtr, endOfInit); StoreAnyExprIntoOneUnit(*this, ILE->getInit(i), elementType, explicitPtr); explicitPtr =Builder.CreateConstGEP1_32(explicitPtr, 1, "array.exp.next"); } @@ -825,7 +845,12 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E, // anything left to initialize. if (llvm::ConstantInt *constNum = dyn_cast<llvm::ConstantInt>(numElements)) { // If all elements have already been initialized, skip the whole loop. - if (constNum->getZExtValue() <= initializerElements) return; + if (constNum->getZExtValue() <= initializerElements) { + // If there was a cleanup, deactivate it. + if (cleanupDominator) + DeactivateCleanupBlock(cleanup, cleanupDominator);; + return; + } } else { llvm::BasicBlock *nonEmptyBB = createBasicBlock("new.loop.nonempty"); llvm::Value *isEmpty = Builder.CreateICmpEQ(explicitPtr, endPtr, @@ -845,11 +870,11 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E, Builder.CreatePHI(explicitPtr->getType(), 2, "array.cur"); curPtr->addIncoming(explicitPtr, entryBB); + // Store the new cleanup position for irregular cleanups. + if (endOfInit) Builder.CreateStore(curPtr, endOfInit); + // Enter a partial-destruction cleanup if necessary. - QualType::DestructionKind dtorKind = elementType.isDestructedType(); - EHScopeStack::stable_iterator cleanup; - llvm::Instruction *cleanupDominator = 0; - if (needsEHCleanup(dtorKind)) { + if (!cleanupDominator && needsEHCleanup(dtorKind)) { pushRegularPartialArrayCleanup(beginPtr, curPtr, elementType, getDestroyer(dtorKind)); cleanup = EHStack.stable_begin(); |