Basic IRGen for LambdaExprs with captures.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150141 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 49d85f7..e309571 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2361,12 +2361,55 @@
   return MakeAddrLValue(Slot.getAddr(), E->getType());
 }
 
+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());
+    }
+  };
+}
+
 LValue
 CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
-  if (E->capture_begin() != E->capture_end())
-    return EmitUnsupportedLValue(E, "lambda expression");
-
   AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
+
+  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);
+
   return MakeAddrLValue(Slot.getAddr(), E->getType());
 }