Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 134493)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1183,6 +1183,53 @@
                                       bool IsTypename = false);
 
   //===--------------------------------------------------------------------===//
+  // C++0x 5.1.2: Lambda expressions
+
+  enum CXX0XLambdaCaptureDefault {
+    DEFAULT_CAPTURE_NONE,
+    DEFAULT_CAPTURE_BY_COPY,
+    DEFAULT_CAPTURE_BY_REF
+  };
+
+  enum CXX0XLambdaCaptureKind {
+    CAPTURE_BY_COPY,
+    CAPTURE_BY_REF
+  };
+
+  struct CXX0XLambdaCapture {
+    SourceLocation Loc;
+    CXX0XLambdaCaptureKind Kind;
+    IdentifierInfo* Id;
+
+    CXX0XLambdaCapture(SourceLocation Loc,
+                       CXX0XLambdaCaptureKind Kind,
+                       IdentifierInfo* Id)
+      : Loc(Loc), Kind(Kind), Id(Id)
+    {}
+  };
+
+  // FIXME: This struct is unnecessary at the moment, but if lambda parsing is
+  // divided among several functions, it raises a couple of questions: Should
+  // these be grouped in a struct, or passed as separate parameters? What is the
+  // policy on defining structs just to hold argument packs?
+  struct CXX0XLambdaCaptureList {
+    llvm::SmallVector<CXX0XLambdaCapture, 4> Captures;
+    SourceLocation ThisLoc;
+    CXX0XLambdaCaptureDefault Default;
+
+    CXX0XLambdaCaptureList()
+      : Default(DEFAULT_CAPTURE_NONE) {}
+  };
+
+  bool isCXX0XLambdaExpression();
+
+  // FIXME: Almost none of the diagnostics used in the ParseCXX0X* functions are
+  // suitable. Create new ones.
+
+  // [...] () -> type {...}
+  ExprResult ParseCXX0XLambdaExpression();
+
+  //===--------------------------------------------------------------------===//
   // C++ 5.2p1: C++ Casts
   ExprResult ParseCXXCasts();
 
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 134493)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -459,6 +459,7 @@
 ///       primary-expression: [C99 6.5.1]
 /// [C99]   identifier
 /// [C++]   id-expression
+/// [C++0x] lambda-expression
 ///         constant
 ///         string-literal
 /// [C++]   boolean-literal  [C++ 2.13.5]
@@ -1099,18 +1100,27 @@
     SourceLocation AtLoc = ConsumeToken();
     return ParseObjCAtExpression(AtLoc);
   }
-  case tok::caret:
-    return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
-  case tok::code_completion:
+  case tok::caret: {
+    Res = ParseBlockLiteralExpression();
+    break;
+  }
+  case tok::code_completion: {
     Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
     ConsumeCodeCompletionToken();
     return ParseCastExpression(isUnaryExpression, isAddressOfOperand, 
                                NotCastExpr, isTypeCast);
-  case tok::l_square:
+  }
+  case tok::l_square: {
     // These can be followed by postfix-expr pieces.
-    if (getLang().ObjC1)
-      return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
+    if (getLang().CPlusPlus0x && isCXX0XLambdaExpression()) {
+      Res = ParseCXX0XLambdaExpression();
+      break;
+    } else if (getLang().ObjC1) {
+      Res = ParseObjCMessageExpression();
+      break;
+    }
     // FALL THROUGH.      
+  }
   default:
     NotCastExpr = true;
     return ExprError();
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 134493)
+++ 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,222 @@
   
 }
 
+/// isCXX0XLambdaExpression - Make sure we are looking at a C++ lambda
+/// expression and not a (possibly nested) Objective-C++ message expression.
+bool Parser::isCXX0XLambdaExpression() {
+  assert(getLang().CPlusPlus0x
+         && Tok.is(tok::l_square)
+         && "why would you call me?");
+  // FIXME: Is there a smaller set of conditions we can check?
+  return !getLang().ObjC1
+         || NextToken().is(tok::r_square)
+         || NextToken().is(tok::equal)
+         || NextToken().is(tok::amp)
+         || (NextToken().is(tok::identifier)
+             && (GetLookAheadToken(2).is(tok::comma)
+                 || GetLookAheadToken(2).is(tok::r_square)));
+  // FIXME: An isObjCMessageExression check might look like the following.
+  // Should we use it instead?
+  //return NextToken().is(tok::l_square) // nested expression
+         //|| (NextToken().is(tok::identifier) && GetLookAheadToken(2).is(tok::identifier));
+}
+
+/// ParseCXX0XLambdaExpression - Handle a C++0x lambda expression.
+///
+/// FIXME: Split this into functions for introducer, declarator, and whole
+/// 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.
+  assert(Tok.is(tok::l_square) && "lambda expressions begin with '['");
+  SourceLocation IntroLoc = ConsumeBracket();
+
+  CXX0XLambdaCaptureList List;
+
+  bool first = true;
+  while (Tok.isNot(tok::r_square)) {
+    if (first) {
+      first = false;
+
+      // Parse capture-default.
+      if (Tok.is(tok::amp) && NextToken().isNot(tok::identifier)) {
+        List.Default = DEFAULT_CAPTURE_BY_REF;
+      } else if (Tok.is(tok::equal)) {
+        List.Default = DEFAULT_CAPTURE_BY_COPY;
+      }
+
+      if (List.Default != DEFAULT_CAPTURE_NONE) {
+        // Consume '&' or '='.
+        ConsumeToken();
+        continue;
+      }
+    } else {
+      if (ExpectAndConsume(tok::comma,
+                           diag::err_expected_comma,
+                           "",
+                           tok::r_square)) {
+        // FIXME: We could also expect end of capture list. Should the
+        // diagnostic indicate this?
+        return ExprError();
+      }
+    }
+
+    // Parse capture.
+    CXX0XLambdaCaptureKind Kind = CAPTURE_BY_COPY;
+    if (Tok.is(tok::amp)) {
+      Kind = CAPTURE_BY_REF;
+      ConsumeToken();
+    }
+
+    if (Tok.is(tok::kw_this)) {
+      if (Kind == CAPTURE_BY_REF) {
+        // FIXME: Need proper diagnostic.
+        //fprintf(stderr, "error: 'this' is always captured by copy'");
+      } 
+      if (List.ThisLoc.isValid()) {
+        // FIXME: Need proper diagnostic.
+        //fprintf(stderr,
+                //"error: 'this' may appear only once in a capture list");
+      }
+      List.ThisLoc = Tok.getLocation();
+      ConsumeToken();
+    } else if (Tok.is(tok::identifier)) {
+      List.Captures.push_back(CXX0XLambdaCapture(Tok.getLocation(),
+                                                 Kind,
+                                                 Tok.getIdentifierInfo()));
+      ConsumeToken();
+    } else {
+      // FIXME: Need proper diagnostic.
+      //fprintf(stderr, "error: expected capture in capture list\n");
+      SkipUntil(tok::r_square);
+      return ExprError();
+    }
+  }
+
+  MatchRHSPunctuation(tok::r_square, IntroLoc);
+
+  // Parse lambda-declarator[opt].
+  // FIXME: Should we default the type quals, or store mutability in this?
+  DeclSpec DS(AttrFactory);
+  // FIXME: Need a LambdaExpressionContext
+  Declarator D(DS, Declarator::BlockLiteralContext);
+
+  if (Tok.is(tok::l_paren)) {
+    // FIXME: Should we have separate or same scopes for the declarator and
+    // body?
+    ParseScope PrototypeScope(this,
+                              Scope::FunctionPrototypeScope |
+                              Scope::DeclScope);
+
+    SourceLocation DBeginLoc = ConsumeParen();
+
+    // Parse parameter-declaration-clause.
+    // FIXME: Is "Attr" the correct naming convention for ParsedAttributes?
+    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, DBeginLoc);
+
+    // Parse 'mutable'[opt].
+    if (Tok.is(tok::kw_mutable)) {
+      // FIXME: How should we add this to the declarator? Should we instead
+      // add const-ness if we do not see 'mutable'?
+      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 DEndLoc;
+    D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
+                                           /*isVariadic=*/EllipsisLoc.isValid(),
+                                           EllipsisLoc,
+                                           ParamInfo.data(), ParamInfo.size(),
+                                           DS.getTypeQualifiers(),
+                                           /*RefQualifierIsLValueRef=*/true,
+                                           /*RefQualifierLoc=*/SourceLocation(),
+                                           ESpecType, ESpecRange.getBegin(),
+                                           DynamicExceptions.data(),
+                                           DynamicExceptionRanges.data(),
+                                           DynamicExceptions.size(),
+                                           NoexceptExpr.isUsable() ?
+                                             NoexceptExpr.get() : 0,
+                                           DBeginLoc, DEndLoc, D,
+                                           TrailingReturnType),
+                  Attr, DEndLoc);
+  }
+
+  // Parse compound-statement.
+  if (Tok.is(tok::l_brace)) {
+    // FIXME: Do we need a separate scope type for lambdas, or can we reuse
+    // BlockScope?
+    ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+                               Scope::BreakScope | Scope::ContinueScope |
+                               Scope::DeclScope);
+
+    StmtResult Stmt(ParseCompoundStatementBody());
+
+    BodyScope.Exit();
+  } else {
+    Diag(Tok, diag::err_expected_fn_body);
+  }
+
+  return ExprResult(true);
+}
+
 /// ParseCXXCasts - This handles the various ways to cast expressions to another
 /// type.
 ///
