Index: test/Parser/objcxx0x-lambda-expressions.mm
===================================================================
--- test/Parser/objcxx0x-lambda-expressions.mm	(revision 140596)
+++ test/Parser/objcxx0x-lambda-expressions.mm	(working copy)
@@ -9,7 +9,7 @@
     [foo,+] {}; // expected-error {{expected expression}}
 
     []; // expected-error {{expected body of lambda expression}}
-    [=,foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
+    [=,&foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
     [&this] {}; // expected-error {{address expression must be an lvalue}}
     [] {};
     [=] (int i) {};
Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td	(revision 140596)
+++ include/clang/Basic/StmtNodes.td	(working copy)
@@ -123,6 +123,7 @@
 def SubstNonTypeTemplateParmExpr : DStmt<Expr>;
 def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
 def MaterializeTemporaryExpr : DStmt<Expr>;
+def LambdaExpr : DStmt<Expr>;
 
 // Obj-C Expressions.
 def ObjCStringLiteral : DStmt<Expr>;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 140596)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -1186,6 +1186,24 @@
 def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
 def err_constexpr_no_declarators : Error<
   "constexpr can only be used in variable and function declarations">;
+
+// C++0x lambda expressions
+def err_capture_more_than_once : Error<
+  "%0 can appear only once in a capture list">;
+def err_reference_capture_with_reference_default : Error<
+  "'&' cannot precede a capture when the capture default is '&'">;
+def err_this_capture_with_copy_default : Error<
+  "'this' cannot appear in a capture list when the capture default is '='">;
+def err_copy_capture_with_copy_default : Error<
+  "'&' must precede a capture when the capture default is '='">;
+def err_capture_non_automatic_variable : Error<
+  "%0 cannot be captured because it does not have automatic storage duration">;
+def err_capture_this : Error<
+  "cannot capture 'this' outside of a non-static member function">;
+def err_capture_not_local_variable : Error<
+  "lambda capture %0 does not refer to a local variable">;
+def note_capture_found : Note<
+  "capture refers to declaration here">;
   
 // Objective-C++
 def err_objc_decls_may_only_appear_in_global_scope : Error<
Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h	(revision 140596)
+++ include/clang/Sema/DeclSpec.h	(working copy)
@@ -1876,7 +1876,6 @@
                   IdentifierInfo* Id = 0) {
     Captures.push_back(LambdaCapture(Kind, Loc, Id));
   }
-
 };
 
 } // end namespace clang
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 140596)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -100,6 +100,7 @@
   class InitializedEntity;
   class IntegerLiteral;
   class LabelStmt;
+  class LambdaExpr;
   class LangOptions;
   class LocalInstantiationScope;
   class LookupResult;
@@ -160,6 +161,7 @@
 namespace sema {
   class AccessedEntity;
   class BlockScopeInfo;
+  class LambdaScopeInfo;
   class DelayedDiagnostic;
   class FunctionScopeInfo;
   class TemplateDeductionInfo;
@@ -750,9 +752,11 @@
 
   void PushFunctionScope();
   void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
-  void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0,
-                               const Decl *D = 0, const BlockExpr *blkExpr = 0);
-
+  sema::LambdaScopeInfo *PushLambdaScope(CXXRecordDecl *Lambda);
+  void PopFunctionOrClosureScope(
+         const sema::AnalysisBasedWarnings::Policy *WP =0,
+         const Decl *D = 0, const BlockExpr *blkExpr = 0);
+  
   sema::FunctionScopeInfo *getCurFunction() const {
     return FunctionScopes.back();
   }
@@ -2980,9 +2984,12 @@
   //// ActOnCXXThis -  Parse 'this' pointer.
   ExprResult ActOnCXXThis(SourceLocation loc);
 
-  /// getAndCaptureCurrentThisType - Try to capture a 'this' pointer.  Returns
-  /// the type of the 'this' pointer, or a null type if this is not possible.
-  QualType getAndCaptureCurrentThisType();
+  /// \brief Try to retrieve the type of the current 'this' pointer, or NULL
+  /// if this is not possible.
+  ///
+  /// \param Capture When true (the default), captures the 'this' pointer for
+  /// use in the current block or lambda.
+  QualType getCurrentThisType(bool Capture = true);
 
   /// ActOnCXXBoolLiteral - Parse {true,false} literals.
   ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@@ -5034,6 +5041,15 @@
   DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
                           const MultiLevelTemplateArgumentList &TemplateArgs);
 
+  //===--------------------------------------------------------------------===//
+  // C++ Lambda Expressions (C++0x [expr.prim.lambda])
+
+  DeclResult ActOnLambdaIntroducer(Scope *S, const LambdaIntroducer &Intro);
+  void ActOnLambdaDeclarator(Scope *S, Decl *Lambda, Declarator &D);
+  ExprResult ActOnLambdaBody(Scope *S, Decl *Lambda, Stmt *Body);
+  ExprResult ActOnLambdaError(Decl *Lambda);
+                        
+  //===--------------------------------------------------------------------===//
   // Objective-C declarations.
   Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
                                  IdentifierInfo *ClassName,
Index: include/clang/Sema/ScopeInfo.h
===================================================================
--- include/clang/Sema/ScopeInfo.h	(revision 140596)
+++ include/clang/Sema/ScopeInfo.h	(working copy)
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
 #define LLVM_CLANG_SEMA_SCOPE_INFO_H
 
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "llvm/ADT/DenseMap.h"
@@ -45,12 +46,18 @@
 /// \brief Retains information about a function, method, or block that is
 /// currently being parsed.
 class FunctionScopeInfo {
+protected:
+  enum ScopeKind {
+    SK_Function,
+    SK_Block,
+    SK_Lambda
+  };
+  
 public:
+  /// \brief What kind of scope we are describing.
+  ///
+  ScopeKind Kind;
 
-  /// \brief Whether this scope information structure defined information for
-  /// a block.
-  bool IsBlockInfo;
-
   /// \brief Whether this function contains a VLA, @try, try, C++
   /// initializer, or anything else that can't be jumped past.
   bool HasBranchProtectedScope;
@@ -96,7 +103,7 @@
   }
   
   FunctionScopeInfo(DiagnosticsEngine &Diag)
-    : IsBlockInfo(false),
+    : Kind(SK_Function),
       HasBranchProtectedScope(false),
       HasBranchIntoScope(false),
       HasIndirectGoto(false),
@@ -141,15 +148,53 @@
     : FunctionScopeInfo(Diag), TheDecl(Block), TheScope(BlockScope),
       CapturesCXXThis(false)
   {
-    IsBlockInfo = true;
+    Kind = SK_Block;
   }
 
   virtual ~BlockScopeInfo();
 
-  static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
+  static bool classof(const FunctionScopeInfo *FSI) { 
+    return FSI->Kind == SK_Block; 
+  }
   static bool classof(const BlockScopeInfo *BSI) { return true; }
 };
 
+class LambdaScopeInfo : public FunctionScopeInfo {
+public:
+  /// \brief The class that describes the lambda.
+  CXXRecordDecl *Lambda;
+  
+  /// \brief A mapping from the set of captured variables to the 
+  /// fields (within the lambda class) that represent the captured variables.
+  llvm::DenseMap<VarDecl *, FieldDecl *> CapturedVariables;
+  
+  /// \brief The list of captured variables, starting with the explicit 
+  /// captures and then finishing with any implicit captures.
+  llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
+  
+  /// \brief The number of captures in the \c Captures list that are 
+  /// explicit captures.
+  unsigned NumExplicitCaptures;
+  
+  /// \brief The field associated with the captured 'this' pointer.
+  FieldDecl *ThisCapture;
+
+  LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda) 
+    : FunctionScopeInfo(Diag), Lambda(Lambda), 
+      NumExplicitCaptures(0), ThisCapture(0) 
+  {
+    Kind = SK_Lambda;
+  }
+    
+  virtual ~LambdaScopeInfo();
+  
+  static bool classof(const FunctionScopeInfo *FSI) { 
+    return FSI->Kind == SK_Lambda; 
+  }
+  static bool classof(const LambdaScopeInfo *BSI) { return true; }
+
+};
+  
 }
 }
 
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h	(revision 140596)
+++ include/clang/AST/RecursiveASTVisitor.h	(working copy)
@@ -1901,6 +1901,12 @@
 DEF_TRAVERSE_STMT(CallExpr, { })
 DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
 
+// FIXME: Implement.
+// Traverse captures, parameters, return type, body, etc.
+DEF_TRAVERSE_STMT(LambdaExpr, {
+  llvm_unreachable("unimplemented");
+})
+
 // These exprs (most of them), do not need any action except iterating
 // over the children.
 DEF_TRAVERSE_STMT(AddrLabelExpr, { })
Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h	(revision 140596)
+++ include/clang/AST/DeclCXX.h	(working copy)
@@ -476,6 +476,9 @@
     /// declared but would have been deleted.
     bool FailedImplicitMoveAssignment : 1;
 
+    /// \brief Whether this class describes a C++ lambda.
+    bool IsLambda : 1;
+    
     /// NumBases - The number of base class specifiers in Bases.
     unsigned NumBases;
     
@@ -882,6 +885,12 @@
   /// This value is used for lazy creation of destructors.
   bool hasDeclaredDestructor() const { return data().DeclaredDestructor; }
 
+  /// \brief Determine whether this class describes a lambda function object.
+  ///
+  bool isLambda() const { return data().IsLambda; }
+  
+  void setLambda(bool Lambda = true) { data().IsLambda = Lambda; }
+  
   /// getConversions - Retrieve the overload set containing all of the
   /// conversion functions in this class.
   UnresolvedSetImpl *getConversionFunctions() {
Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h	(revision 140596)
+++ include/clang/AST/ExprCXX.h	(working copy)
@@ -3123,7 +3123,129 @@
   // Iterators
   child_range children() { return child_range(&Temporary, &Temporary + 1); }
 };
+
+/// LambdaExpr - Represents a C++0x lambda expression, e.g.,
+/// @c [&sum] (int x) -> void { sum += x; }
+/// Holds related declarations, including the captures and closure type.
+class LambdaExpr : public CXXConstructExpr {
+public:
+  /// \brief Describes the capture of either a variable or 'this'.
+  class Capture {
+    enum Kind {
+      CaptureThis,
+      CaptureByCopy,
+      CaptureByRef
+    };
+
+    /// \brief The variable we're capturing (if any) along with the kind of
+    /// capture.
+    llvm::PointerIntPair<VarDecl *, 2, Kind> VarAndKind;
+    
+    /// \brief The source location at which the capture occurred.
+    SourceLocation Loc;
   
+  public:
+    Capture(SourceLocation Loc)
+      : VarAndKind(0, CaptureThis), Loc(Loc) {}
+
+    Capture(VarDecl *Var, SourceLocation Loc, bool ByRef)
+      : VarAndKind(Var, ByRef ? CaptureByRef : CaptureByCopy), Loc(Loc) {}
+
+    bool isThisCapture() const { return VarAndKind.getInt() == CaptureThis; }
+    bool isVariableCapture() const { return !isThisCapture(); }
+    
+    bool isCopyCapture() const { return VarAndKind.getInt() == CaptureByCopy; }
+    bool isReferenceCapture() const {
+      return VarAndKind.getInt() == CaptureByRef;
+    }
+
+    /// Convenience function for variable captures.
+    VarDecl *getVar() const {
+      assert(!isVariableCapture() && "Not a variable capture");
+      return VarAndKind.getPointer();
+    }
+
+    SourceLocation getLoc() const { return Loc; }
+  };
+
+private:
+  /// \brief The number of captures, total.
+  ///
+  unsigned NumCaptures;
+  
+  /// \brief The number of explicit captures.
+  ///
+  /// Any remaining captures are implicit.
+  unsigned NumExplicitCaptures;
+
+protected:
+  LambdaExpr(ASTContext &C, QualType T, ArrayRef<Capture> Captures,
+             unsigned NumExplicitCaptures,
+             SourceLocation Loc,
+             CXXConstructorDecl *Constructor,
+             ArrayRef<Expr *> ConstructorArgs);
+  
+  explicit LambdaExpr(EmptyShell Empty) 
+    : CXXConstructExpr(LambdaExprClass, Empty) {}
+
+public:
+  static LambdaExpr *Create(ASTContext &C, CXXRecordDecl *ClosureType,
+                            ArrayRef<Capture> Captures,
+                            unsigned NumExplicitCaptures,
+                            CXXConstructorDecl *Constructor,
+                            ArrayRef<Expr *> ConstructorArgs);
+
+  unsigned getNumExplicitCaptures() const { return NumExplicitCaptures; }
+
+  typedef const Capture *capture_iterator;
+  typedef const Capture *capture_const_iterator;
+
+  capture_iterator explicits_begin() { 
+    return capture_begin();
+  }
+  
+  capture_iterator explicits_end() { 
+    return capture_begin() + NumExplicitCaptures;
+  }
+
+  capture_const_iterator explicits_begin() const { 
+    return capture_begin();
+  }
+  
+  capture_const_iterator explicits_end() const { 
+    return capture_begin() + NumExplicitCaptures;
+  }
+
+  capture_iterator capture_begin() {
+    return reinterpret_cast<Capture *>(this + 1);
+  }
+
+  capture_iterator capture_end() {
+    return capture_begin() + NumCaptures;
+  }
+
+  capture_const_iterator capture_begin() const {
+    return reinterpret_cast<const Capture *>(this + 1);
+  }
+  
+  capture_const_iterator capture_end() const {
+    return capture_begin() + NumCaptures;
+  }
+
+  /// \brief Retrieve the declaration of the generated closure type.
+  CXXRecordDecl *getClosureType() const;
+
+  SourceRange getSourceRange() const;
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == LambdaExprClass;
+  }
+  static bool classof(const LambdaExpr *) { return true; }
+
+  // Required to pass implementation check.
+  child_range children() { return child_range(); }
+};
+
 }  // end namespace clang
 
 #endif
Index: include/clang/AST/TypeLoc.h
===================================================================
--- include/clang/AST/TypeLoc.h	(revision 140596)
+++ include/clang/AST/TypeLoc.h	(working copy)
@@ -1077,6 +1077,10 @@
     getLocalData()->TrailingReturn = Trailing;
   }
 
+  ArrayRef<ParmVarDecl *> getParams() const {
+    return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs());
+  }
+                                                 
   // ParmVarDecls* are stored after Info, one for each argument.
   ParmVarDecl **getParmArray() const {
     return (ParmVarDecl**) getExtraLocalData();
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h	(revision 140596)
+++ include/clang/Serialization/ASTBitCodes.h	(working copy)
@@ -1075,6 +1075,9 @@
       EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
       EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
       
+      /// \brief LambdaExpr
+      EXPR_LAMBDA,
+
       // CUDA
       EXPR_CUDA_KERNEL_CALL,       // CUDAKernelCallExpr      
 
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp	(revision 140596)
+++ lib/Sema/SemaDeclCXX.cpp	(working copy)
@@ -6455,7 +6455,7 @@
     
     ~ImplicitlyDefinedFunctionScope() {
       S.PopExpressionEvaluationContext();
-      S.PopFunctionOrBlockScope();
+      S.PopFunctionOrClosureScope();
     }
   };
 }
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h	(revision 140596)
+++ lib/Sema/TreeTransform.h	(working copy)
@@ -7926,8 +7926,16 @@
                                                E->getRParenLoc());
 }
 
+// FIXME: Implement.
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
+  llvm_unreachable("unimplemented");
+  return ExprEmpty();
+}
+
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
   BlockDecl *oldBlock = E->getBlockDecl();
   
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 140596)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -630,20 +630,26 @@
   return Owned(E);
 }
 
-QualType Sema::getAndCaptureCurrentThisType() {
+QualType Sema::getCurrentThisType(bool Capture) {
   // Ignore block scopes: we can capture through them.
   // Ignore nested enum scopes: we'll diagnose non-constant expressions
   // where they're invalid, and other uses are legitimate.
   // Don't ignore nested class scopes: you can't use 'this' in a local class.
   DeclContext *DC = CurContext;
-  unsigned NumBlocks = 0;
+  unsigned NumClosures = 0;
   while (true) {
     if (isa<BlockDecl>(DC)) {
       DC = cast<BlockDecl>(DC)->getDeclContext();
-      ++NumBlocks;
-    } else if (isa<EnumDecl>(DC))
+      ++NumClosures;
+    } else if (isa<CXXMethodDecl>(DC) &&
+               cast<CXXRecordDecl>(DC->getParent())->isLambda()) {
+      DC = DC->getParent()->getParent();
+      ++NumClosures;
+    } else if (isa<EnumDecl>(DC)) {
       DC = cast<EnumDecl>(DC)->getDeclContext();
-    else break;
+    }
+    else 
+      break;
   }
 
   QualType ThisTy;
@@ -661,10 +667,16 @@
   }
 
   // Mark that we're closing on 'this' in all the block scopes we ignored.
-  if (!ThisTy.isNull())
+  if (Capture && !ThisTy.isNull()) {
     for (unsigned idx = FunctionScopes.size() - 1;
-         NumBlocks; --idx, --NumBlocks)
-      cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
+         NumClosures; --idx, --NumClosures) {
+      if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(FunctionScopes[idx]))
+        BSI->CapturesCXXThis = true;
+      else {
+        // FIXME: Lambdas need to capture 'this' here.
+      }
+    }
+  }
 
   return ThisTy;
 }
@@ -674,7 +686,7 @@
   /// is a non-lvalue expression whose value is the address of the object for
   /// which the function is called.
 
-  QualType ThisTy = getAndCaptureCurrentThisType();
+  QualType ThisTy = getCurrentThisType();
   if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
 
   return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
@@ -4661,3 +4673,445 @@
   LookupParsedName(R, getCurScope(), &SS);
   return !R.empty(); 
 }
+
+/// \brief Capture the given local variable into the active lambda.
+static FieldDecl *captureVariableInLambda(Sema &S, VarDecl *Var, 
+                                          SourceLocation Loc, bool ByRef) {
+  LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(S.FunctionScopes.back());
+  
+  FieldDecl *&Field = LSI->CapturedVariables[Var];
+  if (Field)
+    return Field;
+  
+  // C++11 [expr.prim.lambda]:
+  //   For each entity captured by copy, an unnamed non- static data member is
+  //   declared in the closure type. The declaration order of these members is
+  //   unspecified. The type of such a data member is the type of the 
+  //   corresponding captured entity if the entity is not a reference to an 
+  //   object, or the referenced type otherwise. [Note: If the captured entity
+  //   is a reference to a function, the corresponding data member is also a 
+  //   reference to a function. - end note ]
+  QualType FieldType = Var->getType();
+  if (const ReferenceType *RefType = FieldType->getAs<ReferenceType>()) {
+    if (!RefType->getPointeeType()->isFunctionType())
+      FieldType = RefType->getPointeeType();
+  }
+  
+  // C++11 [expr.prim.lambda]p15:
+  //   An entity is captured by reference if it is implicitly or explicitly 
+  //   captured but not captured by copy. It is unspecified whether additional
+  //   unnamed non-static data members are declared in the closure type for 
+  //   entities captured by reference.
+  //
+  // We just create a non-static data member that is a reference.
+  if (ByRef && !FieldType->isReferenceType())
+    FieldType = S.Context.getLValueReferenceType(FieldType);
+
+  // Construct a field to to store the captured variable.
+  Field = FieldDecl::Create(S.Context, LSI->Lambda, Loc, SourceLocation(), 0, 
+                            FieldType,
+                            S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
+                            0, false, false);
+  Field->setAccess(AS_public);
+  LSI->Lambda->addDecl(Field);
+  
+  // Record the capture.
+  LSI->Captures.push_back(LambdaExpr::Capture(Var, Loc, ByRef));
+  
+  return Field;
+}
+
+/// \brief Capture 'this' into the active lambda.
+static FieldDecl *captureThisInLambda(Sema &S, SourceLocation Loc) {
+  // FIXME: Check whether we're even allowed to capture 'this', based on the
+  // default capture.
+  QualType ThisTy = S.getCurrentThisType(/*Capture=*/false);
+  if (ThisTy.isNull()) {
+    S.Diag(Loc, diag::err_capture_this);
+    return 0;
+  }
+  
+  LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(S.FunctionScopes.back());
+  if (LSI->ThisCapture)
+    return LSI->ThisCapture;
+  
+  // Construct a field to capture 'this'.
+  LSI->ThisCapture = FieldDecl::Create(S.Context, LSI->Lambda, Loc,
+                       SourceLocation(), 0, ThisTy,
+                       S.Context.getTrivialTypeSourceInfo(ThisTy, Loc),
+                       0, false, false);
+  LSI->ThisCapture->setAccess(AS_public);
+  LSI->Lambda->addDecl(LSI->ThisCapture);
+  
+  // Record the capture.
+  LSI->Captures.push_back(LambdaExpr::Capture(Loc));
+  
+  return LSI->ThisCapture;
+}
+
+// FIXME: Several areas in the below ActOnLambda* functions may benefit from
+// calling existing Sema functions, or from factoring out some essential bits to
+// share. These are marked with FIXMEs that begin "Compare with ...".
+//
+// Additionally, there are a few checks sprinkled throughout these actions
+// merely to ensure their correct implementation. I did not think it worth
+// wrapping them in separate functions just so they can be asserted. They should
+// be removed after code review for performance reasons. They are marked with
+// FIXMEs stating "Remove this check later.".
+DeclResult Sema::ActOnLambdaIntroducer(Scope *S, const LambdaIntroducer &Intro){
+  // Find the nearest block, class, or namespace scope.
+  DeclContext *DC = CurContext;
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isNamespace()))
+    DC = DC->getParent();
+
+  // Start constructing the lambda class.
+  CXXRecordDecl *Class = CXXRecordDecl::Create(Context,
+                                               TTK_Class,
+                                               DC,
+                                               Intro.Range.getBegin(),
+                                               /*IdLoc=*/SourceLocation(),
+                                               /*Id=*/0);
+  Class->startDefinition();
+  Class->setLambda();
+  
+  // Introduce the lambda scope.
+  LambdaScopeInfo *LSI = PushLambdaScope(Class);
+
+  // Diagnose and build the explicit capture list. Erroneous captures are
+  // skipped as if they did not exist.
+  SourceLocation CapturesThis;
+  llvm::DenseMap<const IdentifierInfo*, SourceLocation> CapturesSoFar;
+
+  for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
+       C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E; ++C) {
+    if (C->Kind == LCK_This) {
+      if (CapturesThis.isValid()) {
+        Diag(C->Loc, diag::err_capture_more_than_once) << "'this'"
+          << CapturesThis;
+        continue;
+      }
+
+      if (Intro.Default == LCD_ByCopy) {
+        Diag(C->Loc, diag::err_this_capture_with_copy_default);
+        continue;
+      }
+      
+      captureThisInLambda(*this, C->Loc);
+      continue;
+    }
+
+    assert(C->Id && "missing identifier for capture");
+
+    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
+      Diag(C->Loc, diag::err_reference_capture_with_reference_default);
+      continue;
+    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
+      Diag(C->Loc, diag::err_copy_capture_with_copy_default);
+      continue;
+    }
+
+    llvm::DenseMap<const IdentifierInfo*, SourceLocation>::iterator Appearance;
+    bool IsFirstAppearance;
+    llvm::tie(Appearance, IsFirstAppearance)
+      = CapturesSoFar.insert(std::make_pair(C->Id, C->Loc));
+
+    if (!IsFirstAppearance) {
+      Diag(C->Loc, diag::err_capture_more_than_once) << C->Id
+        << Appearance->second;
+      continue;
+    }
+
+    // Look up the named capture.
+    LookupResult Result(*this, C->Id, C->Loc, LookupOrdinaryName);
+    LookupName(Result, S);
+
+    VarDecl *Var = 0;
+    switch (Result.getResultKind()) {
+    case LookupResult::Found:
+      Var = Result.getAsSingle<VarDecl>();
+      if (Var)
+        break;
+        
+      // Fall through
+
+    case LookupResult::FoundOverloaded:
+    case LookupResult::FoundUnresolvedValue:
+      Diag(C->Loc, diag::err_capture_not_local_variable)
+        << C->Id;
+      Diag((*Result.begin())->getLocation(), diag::note_capture_found);
+      break;
+      
+    case LookupResult::NotFound:
+    case LookupResult::NotFoundInCurrentInstantiation:
+      Diag(C->Loc, diag::err_capture_not_local_variable)
+        << C->Id;
+      break;
+      
+    case LookupResult::Ambiguous:
+      break;
+    }
+    
+    if (!Var)
+      continue;
+
+    // Only local variables with automatic storage duration can be captured.
+    if (!Var->hasLocalStorage() || Var->getStorageClass() == SC_Register) {
+      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
+      continue;
+    }
+
+    captureVariableInLambda(*this, Var, C->Loc, C->Kind == LCK_ByRef);
+  }
+  LSI->NumExplicitCaptures = LSI->Captures.size();
+  
+  Class->setRBraceLoc(Intro.Range.getEnd());
+  return Class;
+}
+
+void Sema::ActOnLambdaDeclarator(Scope *S, Decl *Lambda, Declarator &D) {
+  CXXRecordDecl *Class = cast<CXXRecordDecl>(Lambda);
+  Class->setRBraceLoc(D.getSourceRange().getEnd());
+
+  QualType MethodTy;
+  TypeSourceInfo *MethodTyInfo;
+  if (D.getNumTypeObjects() == 0) {
+    MethodTy = Context.getFunctionType(Context.VoidTy,
+                                       /*Args=*/0,
+                                       /*NumArgs=*/0,
+                                       FunctionProtoType::ExtProtoInfo());
+    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+  } else {
+    assert(D.isFunctionDeclarator() && "non-function lambda-declarator!");
+    DeclaratorChunk::FunctionTypeInfo &Fun = D.getFunctionTypeInfo();
+    if (!Fun.TrailingReturnType) {
+      Fun.TrailingReturnType = Context.VoidTy.getAsOpaquePtr();
+    }
+    // FIXME: The scope is unused?
+    MethodTyInfo = GetTypeForDeclarator(D, S);
+    // FIXME: Unsure of how to deal with this error. Any problems building the
+    // DeclaratorChunk should have been dealt with earlier, correct? I expect
+    // that we would have a void() function type at worst.
+    // If we can fail here, then probably need to return true to indicate
+    // failure, and have the caller in Parser skip over the rest of the
+    // expression and return ExprError.
+    assert(MethodTyInfo && "no type from lambda-declarator!");
+    MethodTy = MethodTyInfo->getType();
+  }
+
+  assert(MethodTy->isFunctionType() &&
+         "no function type from lambda-declarator!");
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context,
+                            Class,
+                            D.getSourceRange().getBegin(),
+                            DeclarationNameInfo(MethodName,
+                                                /*NameLoc=*/SourceLocation()),
+                            MethodTy,
+                            MethodTyInfo,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            D.getSourceRange().getEnd());
+  Method->setAccess(AS_public);
+  Class->addDecl(Method);
+
+  assert(isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc()) &&
+         "no function type from lambda-declarator!");
+  FunctionProtoTypeLoc MethodTypeLoc
+    = cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
+  Method->setParams(MethodTypeLoc.getParams());
+
+  // FIXME: Remove this check later.
+  bool Redeclaration = false;
+  LookupResult Previous(*this,
+                        MethodName,
+                        SourceLocation(),
+                        LookupOrdinaryName,
+                        ForRedeclaration);
+  CheckFunctionDeclaration(S, Method, Previous,
+                           /*IsExplicitSpecialization=*/false,
+                           Redeclaration);
+  assert(!Method->isInvalidDecl() && "bad lambda constructor");
+  
+  PushDeclContext(S, Method);
+}
+
+ExprResult Sema::ActOnLambdaBody(Scope *S, Decl *Lambda, Stmt *Body) {
+  CXXRecordDecl *Class = cast<CXXRecordDecl>(Lambda);
+  Class->setRBraceLoc(Body->getLocEnd());
+
+  CanQualType ClassType
+    = Context.getCanonicalType(Context.getRecordType(Class));
+
+  // Exit the scope of the lambda.
+  PopDeclContext();
+  
+  // Find the function call operator, to which we attach the body of the lambda.
+  CXXMethodDecl *Method 
+    = cast<CXXMethodDecl>(
+        *Class->lookup(
+          Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
+  Method->setBody(Body);
+
+  // Build the constructor.
+  DeclarationName CtorName
+    = Context.DeclarationNames.getCXXConstructorName(ClassType);
+  CXXConstructorDecl *Ctor
+    = CXXConstructorDecl::Create(Context,
+                                 Class,
+                                 /*StartLoc=*/SourceLocation(),
+                                 DeclarationNameInfo(CtorName,
+                                                  /*NameLoc=*/SourceLocation()),
+                                 // Chicken and egg problem: we need the Ctor to
+                                 // build the CtorParams and the CtorParams to
+                                 // build the Ctor. Favor one call on the Ctor
+                                 // to set its type after construction instead
+                                 // of one call on each CtorParam to set their
+                                 // DeclContext.
+                                 QualType(),
+                                 /*TInfo=*/0,
+                                 /*isExplicit=*/true,
+                                 /*isInline=*/true,
+                                 /*isImplicitlyDeclared=*/true,
+                                 /*isConstExpr=*/false);
+
+  // FIXME: When we support implicit captures later, this number will need to be
+  // updated.
+  unsigned NumCaptures = 0; // Lambda->getNumExplicits();
+
+  llvm::SmallVector<QualType, 4> CtorParamTys;
+  CtorParamTys.reserve(NumCaptures);
+  llvm::SmallVector<ParmVarDecl*, 4> CtorParams;
+  CtorParams.reserve(NumCaptures);
+  CXXCtorInitializer **CtorInits
+    = new (Context) CXXCtorInitializer*[NumCaptures];
+  llvm::SmallVector<Expr*, 4> CtorArgs;
+  CtorArgs.reserve(NumCaptures);
+
+FIXME: Need to rewrite all of this
+  
+  CXXCtorInitializer **CtorInit = CtorInits;
+#if 0
+  for (LambdaExpr::capture_const_iterator C = Lambda->explicits_begin(),
+       E = Lambda->explicits_end(); C != E; ++C) {
+
+    Expr *Init = C->getInit();
+
+    IdentifierInfo *Id;
+    if (C->isThisCapture()) {
+      Id = PP.getIdentifierInfo("__this");
+    } else {
+      Id = cast<DeclRefExpr>(Init)->getDecl()->getIdentifier();
+    }
+
+    SourceLocation CaptureLoc = C->getLoc();
+    DeclarationName CaptureName
+      = Context.DeclarationNames.getIdentifier(Id);
+
+    // FIXME: Find the correct type. There are capture type transformations
+    // remaining to be implemented. What is the difference between CanQualType
+    // and QualType? How is template instantiation handled? If some of these
+    // have dependent type, how is that treated?
+    QualType CaptureType = Init->getType();
+    if (C->isReferenceCapture()) {
+      // FIXME: Compare with Sema::BuildReferenceType.
+      CaptureType = Context.getLValueReferenceType(CaptureType,
+                                                   /*SpelledAsLValue=*/true);
+    }
+
+    // FIXME: Compare with Sema::CheckParameter.
+    ParmVarDecl *CtorParam = ParmVarDecl::Create(Context,
+                                                 Ctor,
+                                                 CaptureLoc,
+                                                 CaptureLoc,
+                                                 Id,
+                                  Context.getAdjustedParameterType(CaptureType),
+                                                 /*TInfo=*/0,
+                                                 SC_None,
+                                                 SC_None,
+                                                 /*DefArg=*/0);
+
+    CtorParamTys.push_back(CaptureType);
+    CtorParams.push_back(CtorParam);
+
+    {
+      // FIXME: Have to use Expr* instead of DeclRefExpr* because we cannot
+      // convert from DeclRefExpr** to Expr**. Why?
+      Expr *CtorInitArg
+        = DeclRefExpr::Create(Context,
+                              /*QualifierLoc=*/NestedNameSpecifierLoc(),
+                              CtorParam,
+                              CaptureLoc,
+                              CaptureType.getNonReferenceType(),
+                              VK_LValue);
+
+      MemInitResult Res = BuildMemberInitializer(Field,
+                                                 &CtorInitArg,
+                                                 /*NumArgs=*/1u,
+                                                 CaptureLoc,
+                                                 /*L=*/SourceLocation(),
+                                                 /*R=*/SourceLocation());
+
+      // FIXME: If there was an error, it is probably a bug, right?
+      assert(Res.isUsable() && "bad member initializer!");
+      *CtorInit = Res.take();
+      ++CtorInit;
+    }
+
+    CtorArgs.push_back(Init);
+  }
+#endif
+  
+  assert(CtorParamTys.size() == NumCaptures &&
+         "missed a constructor parameter type!");
+  assert(CtorParams.size() == NumCaptures && "missed a constructor parameter!");
+  assert(CtorArgs.size() == NumCaptures && "missed a constructor argument!");
+
+  // FIXME: Compare with Sema::BuildFunctionType.
+  QualType CtorType = Context.getFunctionType(Context.VoidTy,
+                                              CtorParamTys.data(),
+                                              CtorParamTys.size(),
+                                              FunctionProtoType::ExtProtoInfo());
+
+  Ctor->setAccess(AS_public);
+  Ctor->setImplicit();
+  Ctor->setType(CtorType);
+  // FIXME: Compare with Sema::CheckParmsForFunctionDef.
+  Ctor->setParams(CtorParams);
+  // FIXME: Compare with Sema::ActOnMemInitializers.
+  // FIXME: Compare with Sema::SetCtorInitializers.
+  Ctor->setNumCtorInitializers(NumCaptures);
+  Ctor->setCtorInitializers(CtorInits);
+
+  // FIXME: Remove this check later.
+  bool Redeclaration = false;
+  LookupResult Previous(*this,
+                        CtorName,
+                        SourceLocation(),
+                        LookupOrdinaryName,
+                        ForRedeclaration);
+  CheckFunctionDeclaration(S, Ctor, Previous,
+                           /*IsExplicitSpecialization=*/false,
+                           Redeclaration);
+  assert(!Ctor->isInvalidDecl() && "bad lambda constructor");
+
+  Class->addDecl(Ctor);
+
+  Class->completeDefinition();
+  
+  // FIXME: Remove this check later.
+  CheckCompletedCXXClass(Class);
+
+  LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(FunctionScopes.back());
+  
+  LambdaExpr *LambdaObj
+    = LambdaExpr::Create(Context, Class, LSI->Captures, 
+                         LSI->NumExplicitCaptures, Ctor, CtorArgs);
+  ExprResult Result = MaybeBindToTemporary(LambdaObj);  
+  PopFunctionOrClosureScope();
+  return Result;
+}
+
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 140596)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -6932,7 +6932,7 @@
   if (!IsInstantiation)
     PopDeclContext();
 
-  PopFunctionOrBlockScope(ActivePolicy, dcl);
+  PopFunctionOrClosureScope(ActivePolicy, dcl);
   
   // If any errors have occurred, clear out any temporaries that may have
   // been leftover. This ensures that these temporaries won't be picked up for
Index: lib/Sema/SemaExprMember.cpp
===================================================================
--- lib/Sema/SemaExprMember.cpp	(revision 140596)
+++ lib/Sema/SemaExprMember.cpp	(working copy)
@@ -697,7 +697,7 @@
     // We've found a member of an anonymous struct/union that is
     // inside a non-anonymous struct/union, so in a well-formed
     // program our base object expression is "this".
-    QualType ThisTy = getAndCaptureCurrentThisType();
+    QualType ThisTy = getCurrentThisType();
     if (ThisTy.isNull()) {
       Diag(loc, diag::err_invalid_member_use_in_static_method)
         << indirectField->getDeclName();
@@ -1579,7 +1579,7 @@
   // If this is known to be an instance access, go ahead and build an
   // implicit 'this' expression now.
   // 'this' expression now.
-  QualType ThisTy = getAndCaptureCurrentThisType();
+  QualType ThisTy = getCurrentThisType();
   assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
   
   Expr *baseExpr = 0; // null signifies implicit access
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 140596)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -8782,7 +8782,7 @@
 void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
   // Pop off CurBlock, handle nested blocks.
   PopDeclContext();
-  PopFunctionOrBlockScope();
+  PopFunctionOrClosureScope();
 }
 
 /// ActOnBlockStmtExpr - This is called when the body of a block statement
@@ -8870,7 +8870,7 @@
   
   BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
   const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
-  PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
+  PopFunctionOrClosureScope(&WP, Result->getBlockDecl(), Result);
 
   return Owned(Result);
 }
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 140596)
+++ lib/Sema/Sema.cpp	(working copy)
@@ -54,6 +54,7 @@
 }
 
 BlockScopeInfo::~BlockScopeInfo() { }
+LambdaScopeInfo::~LambdaScopeInfo() { }
 
 void Sema::ActOnTranslationUnitScope(Scope *S) {
   TUScope = S;
@@ -783,8 +784,14 @@
                                               BlockScope, Block));
 }
 
-void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP,
-                                   const Decl *D, const BlockExpr *blkExpr) {
+LambdaScopeInfo *Sema::PushLambdaScope(CXXRecordDecl *Lambda) {
+  LambdaScopeInfo *Result = new LambdaScopeInfo(getDiagnostics(), Lambda);
+  FunctionScopes.push_back(Result);
+  return Result;
+}
+
+void Sema::PopFunctionOrClosureScope(const AnalysisBasedWarnings::Policy *WP,
+                                     const Decl *D, const BlockExpr *blkExpr) {
   FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();  
   assert(!FunctionScopes.empty() && "mismatched push/pop!");
   
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp	(revision 140596)
+++ lib/AST/ExprCXX.cpp	(working copy)
@@ -1012,4 +1012,38 @@
   return TemplateArgument(Arguments, NumArguments);
 }
 
+CXXRecordDecl *LambdaExpr::getClosureType() const {
+  return getType()->getAsCXXRecordDecl();
+}
 
+LambdaExpr::LambdaExpr(ASTContext &C, QualType T, ArrayRef<Capture> Captures,
+                       unsigned NumExplicitCaptures,
+                       SourceLocation Loc,
+                       CXXConstructorDecl *Constructor,
+                       ArrayRef<Expr *> ConstructorArgs)
+  : CXXConstructExpr(C, LambdaExprClass, T, Loc, Constructor, 
+                     /*elidable=*/false, 
+                     (Expr **)ConstructorArgs.data(), ConstructorArgs.size()),
+    NumCaptures(Captures.size()), NumExplicitCaptures(NumExplicitCaptures)
+{
+  memcpy(reinterpret_cast<Capture *>(this + 1), Captures.data(),
+         sizeof(Capture) * NumExplicitCaptures);
+}
+
+LambdaExpr *LambdaExpr::Create(ASTContext &C, CXXRecordDecl *ClosureType,
+                               ArrayRef<Capture> Captures,
+                               unsigned NumExplicitCaptures,
+                               CXXConstructorDecl *Constructor,
+                               ArrayRef<Expr *> ConstructorArgs) {
+  void *Mem = C.Allocate(sizeof(LambdaExpr) + sizeof(Capture)*Captures.size());
+  return new (Mem) LambdaExpr(C, C.getTypeDeclType(ClosureType), Captures,
+                              NumExplicitCaptures, 
+                              ClosureType->getLocation(),
+                              Constructor, 
+                              ConstructorArgs);
+}
+
+SourceRange LambdaExpr::getSourceRange() const {
+  return getClosureType()->getSourceRange();
+}
+
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 140596)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -1503,6 +1503,11 @@
   PrintExpr(E->getSubExpr());
 }
 
+// FIXME: Implement.
+void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
+  llvm_unreachable("unimplemented");
+}
+
 void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
   BlockDecl *BD = Node->getBlockDecl();
   OS << "^";
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp	(revision 140596)
+++ lib/AST/StmtProfile.cpp	(working copy)
@@ -449,6 +449,11 @@
   VisitDecl(S->getBlockDecl());
 }
 
+// FIXME: Implement.
+void StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
+  llvm_unreachable("unimplemented");
+}
+
 void StmtProfiler::VisitBlockDeclRefExpr(const BlockDeclRefExpr *S) {
   VisitExpr(S);
   VisitDecl(S->getDecl());
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp	(revision 140596)
+++ lib/AST/DeclCXX.cpp	(working copy)
@@ -43,8 +43,10 @@
     DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
     DeclaredCopyAssignment(false), DeclaredMoveAssignment(false),
     DeclaredDestructor(false), FailedImplicitMoveConstructor(false),
-    FailedImplicitMoveAssignment(false), NumBases(0), NumVBases(0), Bases(),
-    VBases(), Definition(D), FirstFriend(0) {
+    FailedImplicitMoveAssignment(false), IsLambda(false), 
+    NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D), 
+    FirstFriend(0) 
+{
 }
 
 CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 140596)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -587,7 +587,7 @@
   return ParseLambdaExpressionAfterIntroducer(Intro);
 }
 
-/// ParseLambdaExpression - Parse a lambda introducer.
+/// ParseLambdaIntroducer - Parse a lambda introducer.
 ///
 /// Returns a DiagnosticID if it hit something unexpected.
 llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) {
@@ -655,7 +655,7 @@
   return DiagResult();
 }
 
-/// TryParseLambdaExpression - Tentatively parse a lambda introducer.
+/// TryParseLambdaIntroducer - Tentatively parse a lambda introducer.
 ///
 /// Returns true if it hit something unexpected.
 bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) {
@@ -676,8 +676,20 @@
 /// expression.
 ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
                      LambdaIntroducer &Intro) {
+  DeclResult MaybeLambda = Actions.ActOnLambdaIntroducer(getCurScope(), Intro);
+  if (!MaybeLambda.isUsable())
+    return ExprError();
+
+  Decl *Lambda = MaybeLambda.get();
+
   // Parse lambda-declarator[opt].
   DeclSpec DS(AttrFactory);
+  {
+    const char *PrevSpec = 0;
+    unsigned DiagID = 0;
+    bool HasPrevSpec = DS.SetTypeSpecType(TST_auto, /*Loc=*/SourceLocation(), PrevSpec, DiagID);
+    assert(!HasPrevSpec && !PrevSpec && "unexpected default type specifier!");
+  }
   Declarator D(DS, Declarator::PrototypeContext);
 
   if (Tok.is(tok::l_paren)) {
@@ -751,6 +763,8 @@
                   Attr, DeclEndLoc);
   }
 
+  Actions.ActOnLambdaDeclarator(getCurScope(), Lambda, D);
+
   // Parse compound-statement.
   if (Tok.is(tok::l_brace)) {
     // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
@@ -762,11 +776,14 @@
     StmtResult Stmt(ParseCompoundStatementBody());
 
     BodyScope.Exit();
+
+    if (!Stmt.isInvalid())
+      return Actions.ActOnLambdaBody(getCurScope(), Lambda, Stmt.take());
   } else {
     Diag(Tok, diag::err_expected_lambda_body);
   }
 
-  return ExprEmpty();
+  return Actions.ActOnLambdaError(Lambda);
 }
 
 /// ParseCXXCasts - This handles the various ways to cast expressions to another
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp	(revision 140596)
+++ lib/Serialization/ASTReaderDecl.cpp	(working copy)
@@ -893,6 +893,7 @@
   Data.DeclaredDestructor = Record[Idx++];
   Data.FailedImplicitMoveConstructor = Record[Idx++];
   Data.FailedImplicitMoveAssignment = Record[Idx++];
+  Data.IsLambda = Record[Idx++];
 
   Data.NumBases = Record[Idx++];
   if (Data.NumBases)
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp	(revision 140596)
+++ lib/Serialization/ASTReaderStmt.cpp	(working copy)
@@ -741,6 +741,11 @@
   E->setRParenLoc(ReadSourceLocation(Record, Idx));
 }
 
+// FIXME: Implement.
+void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) {
+  llvm_unreachable("unimplemented");
+}
+
 void ASTStmtReader::VisitBlockExpr(BlockExpr *E) {
   VisitExpr(E);
   E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx));
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp	(revision 140596)
+++ lib/Serialization/ASTWriter.cpp	(working copy)
@@ -3830,6 +3830,7 @@
   Record.push_back(Data.DeclaredDestructor);
   Record.push_back(Data.FailedImplicitMoveConstructor);
   Record.push_back(Data.FailedImplicitMoveAssignment);
+  Record.push_back(Data.IsLambda);
 
   Record.push_back(Data.NumBases);
   if (Data.NumBases > 0)
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp	(revision 140596)
+++ lib/Serialization/ASTWriterStmt.cpp	(working copy)
@@ -701,6 +701,11 @@
   Code = serialization::EXPR_SHUFFLE_VECTOR;
 }
 
+// FIXME: Implement.
+void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) {
+  llvm_unreachable("unimplemented");
+}
+
 void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) {
   VisitExpr(E);
   Writer.AddDeclRef(E->getBlockDecl(), Record);
