diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-02-09 03:32:31 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-02-09 03:32:31 +0000 |
commit | 4c5d8afd100189b6cce4fd89bfb8aec5700acb50 (patch) | |
tree | 82fefe6b9b44cfee1a74e99e7267dfd598c4f5eb /lib/CodeGen/CGExprCXX.cpp | |
parent | b4e5e286a5cd156247720b1eb204abaa8e09568d (diff) |
Refactor lambda IRGen so AggExprEmitter::VisitLambdaExpr does the right thing.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150146 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index aa3b3a8a83..b049e02403 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -1764,3 +1764,50 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value, return Value; } + +namespace { + struct CallLambdaMemberDtor : EHScopeStack::Cleanup { + FieldDecl *Field; + CXXDestructorDecl *Dtor; + llvm::Value *Lambda; + + CallLambdaMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor, + llvm::Value *Lambda) + : Field(Field), Dtor(Dtor), Lambda(Lambda) {} + + void Emit(CodeGenFunction &CGF, Flags flags) { + LValue LHS = CGF.EmitLValueForField(Lambda, Field, 0); + CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, + LHS.getAddress()); + } + }; +} + +void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) { + EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin(); + CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin(); + for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(), + e = E->capture_init_end(); + i != e; ++i, ++CurField) { + // FIXME: Add array handling + // FIXME: Try to refactor with CodeGenFunction::EmitCtorPrologue + + // Emit initialization + LValue LV = EmitLValueForFieldInitialization(Slot.getAddr(), *CurField, 0); + EmitExprAsInit(*i, *CurField, LV, false); + + // Add temporary cleanup to handle the case where a later initialization + // throws. + if (!CGM.getLangOptions().Exceptions) + continue; + const RecordType *RT = CurField->getType()->getAs<RecordType>(); + if (!RT) + continue; + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (!RD->hasTrivialDestructor()) + EHStack.pushCleanup<CallLambdaMemberDtor>(EHCleanup, *CurField, + RD->getDestructor(), + Slot.getAddr()); + } + PopCleanupBlocks(CleanupDepth); +} |