diff --git include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticParseKinds.td
index 3764a40..27b4f85 100644
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -487,6 +487,15 @@ def err_paren_sizeof_parameter_pack : Error<
 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_this_captured_by_reference : Error<
+  "'this' cannot be captured by reference">;
+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]]'">;
diff --git include/clang/Parse/Parser.h include/clang/Parse/Parser.h
index 5d9376c..cf89812 100644
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1183,6 +1183,17 @@ private:
                                       bool IsTypename = false);
 
   //===--------------------------------------------------------------------===//
+  // C++0x 5.1.2: Lambda expressions
+
+  // [...] () -> type {...}
+  ExprResult ParseCXX0XLambdaExpression();
+  ExprResult TryParseCXX0XLambdaExpression();
+  llvm::Optional<unsigned> ParseCXX0XLambdaIntroducer(CXX0XLambdaIntroducer &Intro);
+  bool TryParseCXX0XLambdaIntroducer(CXX0XLambdaIntroducer &Intro);
+  ExprResult ParseCXX0XLambdaExpressionAfterIntroducer(
+               CXX0XLambdaIntroducer &Intro);
+
+  //===--------------------------------------------------------------------===//
   // C++ 5.2p1: C++ Casts
   ExprResult ParseCXXCasts();
 
diff --git include/clang/Sema/DeclSpec.h include/clang/Sema/DeclSpec.h
index ad96c45..e306662 100644
--- include/clang/Sema/DeclSpec.h
+++ include/clang/Sema/DeclSpec.h
@@ -1828,6 +1828,56 @@ private:
   SourceLocation LastLocation;
 };
 
+/// 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.
+// FIXME: Try to nest CXX0XLambdaCaptureKind within CXX0XLambdaCapture within
+// CXX0XLambdaIntroducer? Will require a very long namespace qualifier to get to
+// these enums.
+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)
+  {}
+};
+
+/// CXX0XLambdaIntroducer - Represents a complete lambda introducer.
+struct CXX0XLambdaIntroducer {
+  SourceRange Range;
+  CXX0XLambdaCaptureDefault Default;
+  llvm::SmallVector<CXX0XLambdaCapture, 4> Captures;
+
+  CXX0XLambdaIntroducer()
+    : Default(LCD_None) {}
+
+  /// addCapture - Append a capture in a lambda introducer.
+  void addCapture(CXX0XLambdaCaptureKind Kind,
+                  SourceLocation Loc,
+                  IdentifierInfo* Id = 0) {
+    Captures.push_back(CXX0XLambdaCapture(Kind, Loc, Id));
+  }
+
+};
+
 } // end namespace clang
 
 #endif
diff --git lib/Parse/ParseExpr.cpp lib/Parse/ParseExpr.cpp
index fc64ae0..38d78de 100644
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1109,6 +1109,16 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
                                NotCastExpr, isTypeCast);
   }
   case tok::l_square:
+    if (getLang().CPlusPlus0x) {
+      if (getLang().ObjC1) {
+        Res = TryParseCXX0XLambdaExpression();
+        if (Res.isInvalid())
+          Res = ParseObjCMessageExpression();
+        break;
+      }
+      Res = ParseCXX0XLambdaExpression();
+      break;
+    }
     if (getLang().ObjC1) {
       Res = ParseObjCMessageExpression();
       break;
diff --git lib/Parse/ParseExprCXX.cpp lib/Parse/ParseExprCXX.cpp
index b32eeda..58fef80 100644
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -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,267 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
   
 }
 
+/// 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.
+  CXX0XLambdaIntroducer Intro;
+
+  llvm::Optional<unsigned> DiagID(ParseCXX0XLambdaIntroducer(Intro));
+  if (DiagID) {
+    Diag(Tok, DiagID.getValue());
+    SkipUntil(tok::r_square);
+  }
+
+  return ParseCXX0XLambdaExpressionAfterIntroducer(Intro);
+}
+
+/// 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();
+  }
+
+  CXX0XLambdaIntroducer Intro;
+  if (TryParseCXX0XLambdaIntroducer(Intro))
+    return ExprError();
+  return ParseCXX0XLambdaExpressionAfterIntroducer(Intro);
+}
+
+/// ParseCXX0XLambdaExpression - Parse a lambda introducer.
+///
+/// Returns a DiagnosticID if it hit something unexpected.
+llvm::Optional<unsigned> Parser::ParseCXX0XLambdaIntroducer(CXX0XLambdaIntroducer &Intro) {
+  typedef llvm::Optional<unsigned> DiagResult;
+
+  assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['.");
+  Intro.Range.setBegin(ConsumeBracket());
+
+  bool first = true;
+
+  // Parse capture-default.
+  if (Tok.is(tok::amp) &&
+      (NextToken().is(tok::comma) || NextToken().is(tok::r_square))) {
+    Intro.Default = LCD_ByRef;
+    ConsumeToken();
+    first = false;
+  } else if (Tok.is(tok::equal)) {
+    Intro.Default = LCD_ByCopy;
+    ConsumeToken();
+    first = false;
+  }
+
+  while (Tok.isNot(tok::r_square)) {
+    if (!first) {
+      if (Tok.isNot(tok::comma))
+        return DiagResult(diag::err_expected_comma_or_rsquare);
+      ConsumeToken();
+    }
+
+    first = false;
+
+    // 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 if (Tok.is(tok::kw_this)) {
+        // FIXME: If we want to suggest a fixit here, will need to return more
+        // than just DiagnosticID. Perhaps full DiagnosticBuilder that can be
+        // Clear()ed to prevent emission in case of tentative parsing?
+        return DiagResult(diag::err_this_captured_by_reference);
+      } else {
+        return DiagResult(diag::err_expected_capture);
+      }
+    }
+
+    Intro.addCapture(Kind, Loc, Id);
+  }
+
+  Intro.Range.setEnd(MatchRHSPunctuation(tok::r_square,
+                                         Intro.Range.getBegin()));
+
+  return DiagResult();
+}
+
+/// TryParseCXX0XLambdaExpression - Tentatively parse a lambda introducer.
+///
+/// Returns true if it hit something unexpected.
+bool Parser::TryParseCXX0XLambdaIntroducer(CXX0XLambdaIntroducer &Intro) {
+  TentativeParsingAction PA(*this);
+
+  llvm::Optional<unsigned> DiagID(ParseCXX0XLambdaIntroducer(Intro));
+
+  if (DiagID) {
+    PA.Revert();
+    return true;
+  }
+
+  PA.Commit();
+  return false;
+}
+
+/// ParseCXX0XLambdaExpressionAfterIntroducer - Parse the rest of a lambda
+/// expression.
+ExprResult Parser::ParseCXX0XLambdaExpressionAfterIntroducer(
+                     CXX0XLambdaIntroducer &Intro) {
+  // Parse lambda-declarator[opt].
+  DeclSpec DS(AttrFactory);
+  Declarator D(DS, Declarator::PrototypeContext);
+
+  if (Tok.is(tok::l_paren)) {
+    ParseScope PrototypeScope(this,
+                              Scope::FunctionPrototypeScope |
+                              Scope::DeclScope);
+
+    SourceLocation DeclLoc = ConsumeParen(), DeclEndLoc;
+
+    // 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);
+
+    DeclEndLoc = MatchRHSPunctuation(tok::r_paren, DeclLoc);
+
+    // Parse 'mutable'[opt].
+    SourceLocation MutableLoc;
+    if (Tok.is(tok::kw_mutable)) {
+      MutableLoc = ConsumeToken();
+      DeclEndLoc = MutableLoc;
+    }
+
+    // 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);
+
+    if (ESpecType != EST_None)
+      DeclEndLoc = ESpecRange.getEnd();
+
+    // Parse attribute-specifier[opt].
+    // FIXME: The endLoc parameter of MaybeParseCXX0XAttribtues is undocumented
+    // (and unused it seems), but I presume it is an output parameter.
+    MaybeParseCXX0XAttributes(Attr, &DeclEndLoc);
+
+    // Parse trailing-return-type[opt].
+    ParsedType TrailingReturnType;
+    if (Tok.is(tok::arrow)) {
+      // FIXME: No way to get end location of trailing return type?
+      DeclEndLoc = Tok.getLocation();
+      TrailingReturnType = ParseTrailingReturnType().get();
+    }
+
+    PrototypeScope.Exit();
+
+    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.
 ///
diff --git test/Parser/cxx0x-attributes.cpp test/Parser/cxx0x-attributes.cpp
index f65e290..0285ee1 100644
--- test/Parser/cxx0x-attributes.cpp
+++ test/Parser/cxx0x-attributes.cpp
@@ -17,7 +17,7 @@ int comma_attr [[,]]; // expected-error {{expected identifier}}
 int scope_attr [[foo::]]; // expected-error {{expected identifier}}
 int & [[]] ref_attr = after_attr; // expected-error {{an attribute list cannot appear here}}
 class foo {
-  void after_const_attr () const [[]]; // expected-error {{expected expression}}
+  void after_const_attr () const [[]]; // expected-error {{expected body of lambda expression}} expected-error {{array has incomplete element type 'void'}}
 };
 extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
 [[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}
diff --git test/Parser/cxx0x-lambda-expressions.cpp test/Parser/cxx0x-lambda-expressions.cpp
new file mode 100644
index 0000000..cf09684
--- /dev/null
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+class C {
+
+  void f() {
+    int foo, bar;
+
+    []; // expected-error {{expected body of lambda expression}}
+    [+] {}; // expected-error {{expected variable name or 'this' in lambda capture list}}
+    [foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
+    [foo,&this] {}; // expected-error {{'this' cannot be captured by reference}}
+    [&this] {}; // expected-error {{'this' cannot be captured by reference}}
+    [&,] {}; // expected-error {{ expected variable name or 'this' in lambda capture list}}
+    [=,] {}; // expected-error {{ expected variable name or 'this' in lambda capture list}}
+    [] {};
+    [=] (int i) {};
+    [&] (int) mutable -> void {};
+    // FIXME: this error occurs because we do not yet handle lambda scopes
+    // properly. I did not anticipate it because I thought it was a semantic (not
+    // syntactic) check.
+    [foo,bar] () { return 3; }; // expected-error {{void function 'f' should not return a value}}
+    [=,&foo] () {};
+    [&,foo] () {};
+    [this] () {};
+  }
+
+};
+
diff --git test/Parser/objc-messaging-neg-1.m test/Parser/objc-messaging-neg-1.m
index 4ddadb8..bb496e9 100644
--- test/Parser/objc-messaging-neg-1.m
+++ test/Parser/objc-messaging-neg-1.m
@@ -9,4 +9,5 @@ int main() {
   [a bla:0 6:7]; // expected-error {{expected ']'}}
   [A foo bar]; // expected-error {{expected ':'}}
   [A foo bar bar1]; // expected-error {{expected ':'}}
+  [] {}; // expected-error {{expected expression}}
 }
diff --git test/Parser/objcxx-lambda-expressions-neg.mm test/Parser/objcxx-lambda-expressions-neg.mm
new file mode 100644
index 0000000..864cc6b
--- /dev/null
+++ test/Parser/objcxx-lambda-expressions-neg.mm
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int main() {
+  []{}; // expected-error {{expected expression}}
+}
diff --git test/Parser/objcxx0x-lambda-expressions.mm test/Parser/objcxx0x-lambda-expressions.mm
new file mode 100644
index 0000000..d100e2e
--- /dev/null
+++ test/Parser/objcxx0x-lambda-expressions.mm
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+class C {
+
+  void f() {
+    int foo, bar;
+
+    // fail to parse as a lambda introducer, so we get objc message parsing errors instead
+    [foo,+] {}; // expected-error {{expected expression}}
+
+    []; // expected-error {{expected body of lambda expression}}
+    [=,foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
+    [&this] {}; // expected-error {{address expression must be an lvalue}}
+    [] {};
+    [=] (int i) {};
+    [&] (int) mutable -> void {};
+    // FIXME: this error occurs because we do not yet handle lambda scopes
+    // properly. I did not anticipate it because I thought it was a semantic (not
+    // syntactic) check.
+    [foo,bar] () { return 3; }; // expected-error {{void function 'f' should not return a value}}
+    [=,&foo] () {};
+    [this] () {};
+  }
+
+};
+
