Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td	(revision 135121)
+++ include/clang/Basic/DiagnosticParseKinds.td	(working copy)
@@ -487,6 +487,13 @@
 def err_sizeof_parameter_pack : Error<
   "expected parenthesized parameter pack name in 'sizeof...' expression">;
 
+// C++0x lambda expressions
+def err_expected_comma_or_rsquare : Error<
+  "expected ',' or ']' in lambda capture list">;
+def err_expected_capture : Error<
+  "expected variable name or 'this' in lambda capture list">;
+def err_expected_lambda_body : Error<"expected body of lambda expression">;
+
 // Availability attribute
 def err_expected_version : Error<
   "expected a version of the form 'major[.minor[.subminor]]'">;
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 135121)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1183,6 +1183,57 @@
                                       bool IsTypename = false);
 
   //===--------------------------------------------------------------------===//
+  // C++0x 5.1.2: Lambda expressions
+
+  /// CXX0XLambdaCaptureDefault - The default, if any, capture method for a
+  /// lambda expression.
+  enum CXX0XLambdaCaptureDefault {
+    LCD_None,
+    LCD_ByCopy,
+    LCD_ByRef
+  };
+
+  /// CXX0XLambdaCaptureKind - The different capture forms in a lambda
+  /// introducer: 'this' or a copied or referenced variable.
+  enum CXX0XLambdaCaptureKind {
+    LCK_This,
+    LCK_ByCopy,
+    LCK_ByRef
+  };
+
+  /// CXX0XLambdaCapture - An individual capture in a lambda introducer.
+  struct CXX0XLambdaCapture {
+    CXX0XLambdaCaptureKind Kind;
+    SourceLocation Loc;
+    IdentifierInfo* Id;
+
+    CXX0XLambdaCapture(CXX0XLambdaCaptureKind Kind,
+                       SourceLocation Loc,
+                       IdentifierInfo* Id = 0)
+      : Kind(Kind), Loc(Loc), Id(Id)
+    {}
+  };
+
+  /// CXX0XLambdaCaptureList - Represents a complete lambda introducer.
+  /// FIXME: Rename to CXX0XLambdaIntroducer? 
+  struct CXX0XLambdaCaptureList {
+    SourceRange Range;
+    CXX0XLambdaCaptureDefault Default;
+    llvm::SmallVector<CXX0XLambdaCapture, 4> Captures;
+
+    CXX0XLambdaCaptureList()
+      : Default(LCD_None) {}
+  };
+
+  // [...] () -> type {...}
+  ExprResult ParseCXX0XLambdaExpression();
+  ExprResult TryParseCXX0XLambdaExpression();
+  llvm::Optional<unsigned> ParseCXX0XLambdaIntroducer(CXX0XLambdaCaptureList &List);
+  bool TryParseCXX0XLambdaIntroducer(CXX0XLambdaCaptureList &List);
+  ExprResult ParseCXX0XLambdaExpressionAfterIntroducer(
+               CXX0XLambdaCaptureList &List);
+
+  //===--------------------------------------------------------------------===//
   // C++ 5.2p1: C++ Casts
   ExprResult ParseCXXCasts();
 
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 135121)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -15,6 +15,7 @@
 #include "clang/Parse/Parser.h"
 #include "RAIIObjectsForParser.h"
 #include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -504,6 +505,262 @@
   
 }
 
+/// ParseCXX0XLambdaExpression - Parse a C++0x lambda expression.
+///
+///       lambda-expression:
+///         lambda-introducer lambda-declarator[opt] compound-statement
+///
+///       lambda-introducer:
+///         '[' lambda-capture[opt] ']'
+///
+///       lambda-capture:
+///         capture-default
+///         capture-list
+///         capture-default ',' capture-list
+///
+///       capture-default:
+///         '&'
+///         '='
+///
+///       capture-list:
+///         capture
+///         capture-list ',' capture
+///
+///       capture:
+///         identifier
+///         '&' identifier
+///         'this'
+///
+///       lambda-declarator:
+///         '(' parameter-declaration-clause ')' attribute-specifier[opt]
+///           'mutable'[opt] exception-specification[opt]
+///           trailing-return-type[opt]
+///
+ExprResult Parser::ParseCXX0XLambdaExpression() {
+  // Parse lambda-introducer.
+  CXX0XLambdaCaptureList List;
+
+  llvm::Optional<unsigned> DiagID(ParseCXX0XLambdaIntroducer(List));
+  if (DiagID) {
+    Diag(Tok, DiagID.getValue());
+    SkipUntil(tok::r_square);
+  }
+
+  return ParseCXX0XLambdaExpressionAfterIntroducer(List);
+}
+
+/// TryParseCXX0XLambdaExpression - Use lookahead and potentially tentative
+/// parsing to determine if we are looking at a C++0x lambda expression, and parse
+/// it if we are.
+///
+/// If we are not looking at a lambda expression, returns ExprError().
+ExprResult Parser::TryParseCXX0XLambdaExpression() {
+  assert(getLang().CPlusPlus0x
+         && Tok.is(tok::l_square)
+         && "Not at the start of a possible lambda expression.");
+
+  const Token &Next = NextToken(), &After = GetLookAheadToken(2);
+
+  // If lookahead indicates this is a lambda...
+  if (Next.is(tok::r_square) ||     // []
+      Next.is(tok::equal) ||        // [=
+      (Next.is(tok::amp) &&         // [&] or [&,
+       (After.is(tok::r_square) ||
+        After.is(tok::comma))) ||
+      (Next.is(tok::identifier) &&  // [identifier]
+       After.is(tok::r_square))) {
+    return ParseCXX0XLambdaExpression();
+  }
+
+  // If lookahead indicates this is an Objective-C message...
+  if (Next.is(tok::identifier) && After.is(tok::identifier)) {
+    return ExprError();
+  }
+
+  CXX0XLambdaCaptureList List;
+  if (TryParseCXX0XLambdaIntroducer(List))
+    return ParseCXX0XLambdaExpressionAfterIntroducer(List);
+
+  return ExprError();
+}
+
+/// ParseCXX0XLambdaExpression - Parse a lambda introducer.
+///
+/// Returns a DiagnosticID if it hit something unexpected.
+llvm::Optional<unsigned> Parser::ParseCXX0XLambdaIntroducer(CXX0XLambdaCaptureList &List) {
+  typedef llvm::Optional<unsigned> DiagResult;
+
+  assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['.");
+  List.Range.setBegin(ConsumeBracket());
+
+  bool first = true;
+  while (1) {
+    if (Tok.is(tok::r_square)) {
+      List.Range.setEnd(MatchRHSPunctuation(tok::r_square,
+                                            List.Range.getBegin()));
+      break;
+    }
+
+    if (first) {
+      first = false;
+
+      // Parse capture-default.
+      if (Tok.is(tok::amp) && NextToken().isNot(tok::identifier)) {
+        List.Default = LCD_ByRef;
+        // Consume '&'.
+        ConsumeToken();
+        continue;
+      } else if (Tok.is(tok::equal)) {
+        List.Default = LCD_ByCopy;
+        // Consume '='.
+        ConsumeToken();
+        continue;
+      }
+    } else {
+      if (Tok.isNot(tok::comma))
+        return DiagResult(diag::err_expected_comma_or_rsquare);
+    }
+
+    // Parse capture.
+    CXX0XLambdaCaptureKind Kind = LCK_ByCopy;
+    SourceLocation Loc;
+    IdentifierInfo* Id = 0;
+
+    if (Tok.is(tok::kw_this)) {
+      Kind = LCK_This;
+      Loc = ConsumeToken();
+    } else {
+      if (Tok.is(tok::amp)) {
+        Kind = LCK_ByRef;
+        ConsumeToken();
+      }
+
+      if (Tok.is(tok::identifier)) {
+        Id = Tok.getIdentifierInfo();
+        Loc = ConsumeToken();
+      } else {
+        return DiagResult(diag::err_expected_capture);
+      }
+    }
+
+    List.Captures.push_back(CXX0XLambdaCapture(Kind, Loc, Id));
+  }
+
+  return DiagResult();
+}
+
+/// TryParseCXX0XLambdaExpression - Tentatively parse a lambda introducer.
+///
+/// Returns true if it hit something unexpected.
+bool Parser::TryParseCXX0XLambdaIntroducer(CXX0XLambdaCaptureList &List) {
+  TentativeParsingAction PA(*this);
+
+  llvm::Optional<unsigned> DiagID(ParseCXX0XLambdaIntroducer(List));
+
+  if (DiagID) {
+    PA.Revert();
+    return true;
+  }
+
+  PA.Commit();
+  return false;
+}
+
+/// ParseCXX0XLambdaExpressionAfterIntroducer - Parse the rest of a lambda
+/// expression.
+///
+/// Returns a valid, but possibly unusable, ExprResult.
+ExprResult Parser::ParseCXX0XLambdaExpressionAfterIntroducer(
+                     CXX0XLambdaCaptureList &List) {
+  // Parse lambda-declarator[opt].
+  DeclSpec DS(AttrFactory);
+  // FIXME: Need a LambdaExpressionContext
+  Declarator D(DS, Declarator::BlockLiteralContext);
+
+  if (Tok.is(tok::l_paren)) {
+    ParseScope PrototypeScope(this,
+                              Scope::FunctionPrototypeScope |
+                              Scope::DeclScope);
+
+    SourceLocation DeclLoc = ConsumeParen();
+
+    // Parse parameter-declaration-clause.
+    ParsedAttributes Attr(AttrFactory);
+    llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+    SourceLocation EllipsisLoc;
+
+    if (Tok.isNot(tok::r_paren))
+      ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
+
+    MatchRHSPunctuation(tok::r_paren, DeclLoc);
+
+    // Parse 'mutable'[opt].
+    SourceLocation MutableLoc;
+    if (Tok.is(tok::kw_mutable)) {
+      MutableLoc = ConsumeToken();
+    }
+
+    // Parse exception-specification[opt].
+    ExceptionSpecificationType ESpecType = EST_None;
+    SourceRange ESpecRange;
+    llvm::SmallVector<ParsedType, 2> DynamicExceptions;
+    llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges;
+    ExprResult NoexceptExpr;
+    ESpecType = MaybeParseExceptionSpecification(ESpecRange,
+                                                 DynamicExceptions,
+                                                 DynamicExceptionRanges,
+                                                 NoexceptExpr);
+
+    // Parse attribute-specifier[opt].
+    MaybeParseCXX0XAttributes(Attr);
+
+    // Parse trailing-return-type[opt].
+    ParsedType TrailingReturnType;
+    if (Tok.is(tok::arrow)) {
+      TrailingReturnType = ParseTrailingReturnType().get();
+    }
+
+    PrototypeScope.Exit();
+
+    // FIXME: Have to set this at the end of each thing parsed above.
+    SourceLocation DeclEndLoc;
+    D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
+                                           /*isVariadic=*/EllipsisLoc.isValid(),
+                                           EllipsisLoc,
+                                           ParamInfo.data(), ParamInfo.size(),
+                                           DS.getTypeQualifiers(),
+                                           /*RefQualifierIsLValueRef=*/true,
+                                           /*RefQualifierLoc=*/SourceLocation(),
+                                           MutableLoc,
+                                           ESpecType, ESpecRange.getBegin(),
+                                           DynamicExceptions.data(),
+                                           DynamicExceptionRanges.data(),
+                                           DynamicExceptions.size(),
+                                           NoexceptExpr.isUsable() ?
+                                             NoexceptExpr.get() : 0,
+                                           DeclLoc, DeclEndLoc, D,
+                                           TrailingReturnType),
+                  Attr, DeclEndLoc);
+  }
+
+  // Parse compound-statement.
+  if (Tok.is(tok::l_brace)) {
+    // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
+    // it.
+    ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+                               Scope::BreakScope | Scope::ContinueScope |
+                               Scope::DeclScope);
+
+    StmtResult Stmt(ParseCompoundStatementBody());
+
+    BodyScope.Exit();
+  } else {
+    Diag(Tok, diag::err_expected_lambda_body);
+  }
+
+  return ExprEmpty();
+}
+
 /// ParseCXXCasts - This handles the various ways to cast expressions to another
 /// type.
 ///
