diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-17 22:05:50 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-17 22:05:50 +0000 |
| commit | 0444006fff93b24852328c4f0d32f37ba00b3c34 (patch) | |
| tree | d6d5936ab53e43a6012888948edb957b3cdeaf18 /clang/lib | |
| parent | 1ef3866a644757f0c8c04f62db6784210bf5ed6e (diff) | |
| download | bcm5719-llvm-0444006fff93b24852328c4f0d32f37ba00b3c34.tar.gz bcm5719-llvm-0444006fff93b24852328c4f0d32f37ba00b3c34.zip | |
Fix cleanup registration for lambda captures.
Lambda captures should be destroyed if an exception is thrown only if
the construction of the complete lambda-expression has not completed.
(If the lambda-expression has been fully constructed, any exception will
invoke its destructor, which will destroy the captures.)
This is directly modeled after how we handle the equivalent situation in
InitListExprs.
Note that EmitLambdaLValue was unreachable because in C++11 onwards the
frontend never creates the awkward situation where a prvalue expression
(such as a lambda) is used in an lvalue context (such as the left-hand
side of a class member access).
llvm-svn: 351487
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 47 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 6 |
4 files changed, 49 insertions, 31 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 34a921e2dc0..f986bc4c4cf 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1287,8 +1287,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E)); case Expr::CXXUuidofExprClass: return EmitCXXUuidofLValue(cast<CXXUuidofExpr>(E)); - case Expr::LambdaExprClass: - return EmitLambdaLValue(cast<LambdaExpr>(E)); case Expr::ExprWithCleanupsClass: { const auto *cleanups = cast<ExprWithCleanups>(E); @@ -4548,13 +4546,6 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) { return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); } -LValue -CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) { - AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue"); - EmitLambdaExpr(E, Slot); - return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); -} - LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { RValue RV = EmitObjCMessageExpr(E); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index db49b3f28a5..be6e938c308 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1264,7 +1264,52 @@ void AggExprEmitter::VisitCXXInheritedCtorInitExpr( void AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) { AggValueSlot Slot = EnsureSlot(E->getType()); - CGF.EmitLambdaExpr(E, Slot); + LValue SlotLV = CGF.MakeAddrLValue(Slot.getAddress(), E->getType()); + + // We'll need to enter cleanup scopes in case any of the element + // initializers throws an exception. + SmallVector<EHScopeStack::stable_iterator, 16> Cleanups; + llvm::Instruction *CleanupDominator = nullptr; + + CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin(); + for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(), + e = E->capture_init_end(); + i != e; ++i, ++CurField) { + // Emit initialization + LValue LV = CGF.EmitLValueForFieldInitialization(SlotLV, *CurField); + if (CurField->hasCapturedVLAType()) { + CGF.EmitLambdaVLACapture(CurField->getCapturedVLAType(), LV); + continue; + } + + EmitInitializationToLValue(*i, LV); + + // Push a destructor if necessary. + if (QualType::DestructionKind DtorKind = + CurField->getType().isDestructedType()) { + assert(LV.isSimple()); + if (CGF.needsEHCleanup(DtorKind)) { + if (!CleanupDominator) + CleanupDominator = CGF.Builder.CreateAlignedLoad( + CGF.Int8Ty, + llvm::Constant::getNullValue(CGF.Int8PtrTy), + CharUnits::One()); // placeholder + + CGF.pushDestroy(EHCleanup, LV.getAddress(), CurField->getType(), + CGF.getDestroyer(DtorKind), false); + Cleanups.push_back(CGF.EHStack.stable_begin()); + } + } + } + + // Deactivate all the partial cleanups in reverse order, which + // generally means popping them. + for (unsigned i = Cleanups.size(); i != 0; --i) + CGF.DeactivateCleanupBlock(Cleanups[i-1], CleanupDominator); + + // Destroy the placeholder if we made one. + if (CleanupDominator) + CleanupDominator->eraseFromParent(); } void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) { diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 884ce96859c..98ef25bb192 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2253,21 +2253,3 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, return Value; } - -void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) { - LValue SlotLV = MakeAddrLValue(Slot.getAddress(), E->getType()); - - CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin(); - for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(), - e = E->capture_init_end(); - i != e; ++i, ++CurField) { - // Emit initialization - LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField); - if (CurField->hasCapturedVLAType()) { - auto VAT = CurField->getCapturedVLAType(); - EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); - } else { - EmitInitializerForField(*CurField, LV, *i); - } - } -} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 89cb850ab1b..005337a56b9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1836,6 +1836,9 @@ public: void EmitLambdaBlockInvokeBody(); void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD); void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD); + void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) { + EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); + } void EmitAsanPrologueOrEpilogue(bool Prologue); /// Emit the unified return block, trying to avoid its emission when @@ -3560,7 +3563,6 @@ public: LValue EmitCXXConstructLValue(const CXXConstructExpr *E); LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E); - LValue EmitLambdaLValue(const LambdaExpr *E); LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E); LValue EmitCXXUuidofLValue(const CXXUuidofExpr *E); @@ -3982,8 +3984,6 @@ public: void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true); - void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest); - RValue EmitAtomicExpr(AtomicExpr *E); //===--------------------------------------------------------------------===// |

