[cfe-commits] r149977 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/CXX/expr/expr.prim/expr.prim.lambda/ tools/libclang/

Douglas Gregor dgregor at apple.com
Tue Feb 7 02:09:13 PST 2012


Author: dgregor
Date: Tue Feb  7 04:09:13 2012
New Revision: 149977

URL: http://llvm.org/viewvc/llvm-project?rev=149977&view=rev
Log:
Introduce basic ASTs for lambda expressions. This covers:
  - Capturing variables by-reference and by-copy within a lambda
  - The representation of lambda captures
  - The creation of the non-static data members in the lambda class
  that store the captured variables
  - The initialization of the non-static data members from the
  captured variables
  - Pretty-printing lambda expressions

There are a number of FIXMEs, both explicit and implied, including:
  - Creating a field for a capture of 'this'
  - Improved diagnostics for initialization failures when capturing
  variables by copy
  - Dealing with temporaries created during said initialization
  - Template instantiation
  - AST (de-)serialization
  - Binding and returning the lambda expression; turning it into a
  proper temporary
  - Lots and lots of semantic constraints
  - Parameter pack captures

Added:
    cfe/trunk/include/clang/Basic/Lambda.h   (with props)
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp   (with props)
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/ExprClassification.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Feb  7 04:09:13 2012
@@ -14,11 +14,12 @@
 #ifndef LLVM_CLANG_AST_EXPRCXX_H
 #define LLVM_CLANG_AST_EXPRCXX_H
 
-#include "clang/Basic/TypeTraits.h"
-#include "clang/Basic/ExpressionTraits.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/AST/TemplateBase.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/TypeTraits.h"
 
 namespace clang {
 
@@ -1007,6 +1008,274 @@
   friend class ASTStmtReader;
 };
 
+/// \brief A C++ lambda expression, which produces a function object
+/// (of unspecified type) that can be invoked later.
+///
+/// Example:
+/// \code
+/// void low_pass_filter(std::vector<double> &values, double cutoff) {
+///   values.erase(std::remove_if(values.begin(), values.end(),
+//                                [=](double value) { return value > cutoff; });
+/// }
+/// \endcode
+///
+/// Lambda expressions can capture local variables, either by copying
+/// the values of those local variables at the time the function
+/// object is constructed (not when it is called!) or by holding a
+/// reference to the local variable. These captures can occur either
+/// implicitly or can be written explicitly between the square
+/// brackets ([...]) that start the lambda expression.
+class LambdaExpr : public Expr {
+  enum {
+    /// \brief Flag used by the Capture class to indicate that the given
+    /// capture was implicit.
+    Capture_Implicit = 0x01,
+
+    /// \brief Flag used by the Capture class to indciate that the
+    /// given capture was by-copy.
+    Capture_ByCopy = 0x02
+  };
+
+  /// \brief The source range that covers the lambda introducer ([...]).
+  SourceRange IntroducerRange;
+
+  /// \brief The number of captures in this lambda.
+  unsigned NumCaptures : 16;
+
+  /// \brief The number of explicit captures in this lambda.
+  unsigned NumExplicitCaptures : 13;
+
+  /// \brief The default capture kind, which is a value of type
+  /// LambdaCaptureDefault.
+  unsigned CaptureDefault : 2;
+
+  /// \brief Whether this lambda had an explicit parameter list vs. an
+  /// implicit (and empty) parameter list.
+  unsigned ExplicitParams : 1;
+
+  /// \brief The location of the closing brace ('}') that completes
+  /// the lambda.
+  /// 
+  /// The location of the brace is also available by looking up the
+  /// function call operator in the lambda class. However, it is
+  /// stored here to improve the performance of getSourceRange(), and
+  /// to avoid having to deserialize the function call operator from a
+  /// module file just to determine the source range.
+  SourceLocation ClosingBrace;
+
+  // Note: The Create method allocates storage after the LambdaExpr
+  // object, which contains the captures, followed by the capture
+  // initializers, and finally the body of the lambda. The capture
+  // initializers and lambda body are placed next to each other so
+  // that the children() function can visit all of them easily.
+
+public:
+  /// \brief Describes the capture of either a variable or 'this'.
+  class Capture {
+    llvm::PointerIntPair<VarDecl *, 2> VarAndBits;
+    SourceLocation Loc;
+    SourceLocation EllipsisLoc;
+
+    friend class ASTStmtReader;
+    friend class ASTStmtWriter;
+
+  public:
+    /// \brief Create a new capture.
+    ///
+    /// \param Loc The source location associated with this capture.
+    ///
+    /// \param Kind The kind of capture (this, byref, bycopy).
+    ///
+    /// \param Implicit Whether the capture was implicit or explicit.
+    ///
+    /// \param Var The local variable being captured, or null if capturing this.
+    ///
+    /// \param EllipsisLoc The location of the ellipsis (...) for a
+    /// capture that is a pack expansion, or an invalid source
+    /// location to indicate that this is not a pack expansion.
+    Capture(SourceLocation Loc, bool Implicit,
+            LambdaCaptureKind Kind, VarDecl *Var = 0,
+            SourceLocation EllipsisLoc = SourceLocation());
+
+    /// \brief Determine the kind of capture.
+    LambdaCaptureKind getCaptureKind() const;
+
+    /// \brief Determine whether this capture handles the C++ 'this'
+    /// pointer.
+    bool capturesThis() const { return VarAndBits.getPointer() == 0; }
+
+    /// \brief Determine whether this capture handles a variable.
+    bool capturesVariable() const { return VarAndBits.getPointer() != 0; }
+
+    /// \brief Retrieve the declaration of the local variable being
+    /// captured.
+    ///
+    /// This operation is only valid if this capture does not capture
+    /// 'this'.
+    VarDecl *getCapturedVar() const { 
+      assert(!capturesThis() && "No variable available for 'this' capture");
+      return VarAndBits.getPointer();
+    }
+
+    /// \brief Determine whether this was an implicit capture (not
+    /// written between the square brackets introducing the lambda).
+    bool isImplicit() const { return VarAndBits.getInt() & Capture_Implicit; }
+
+    /// \brief Determine whether this was an explicit capture, written
+    /// between the square brackets introducing the lambda.
+    bool isExplicit() const { return !isImplicit(); }
+
+    /// \brief Retrieve the source location of the capture.
+    ///
+    /// For an explicit capture, this returns the location of the
+    /// explicit capture in the source. For an implicit capture, this
+    /// returns the location at which the variable or 'this' was first
+    /// used.
+    SourceLocation getLocation() const { return Loc; }
+
+    /// \brief Determine whether this capture is a pack expansion,
+    /// which captures a function parameter pack.
+    bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+
+    /// \brief Retrieve the location of the ellipsis for a capture
+    /// that is a pack expansion.
+    SourceLocation getEllipsisLoc() const {
+      assert(isPackExpansion() && "No ellipsis location for a non-expansion");
+      return EllipsisLoc;
+    }
+  };
+
+private:
+  /// \brief Construct a lambda expression.
+  LambdaExpr(QualType T, SourceRange IntroducerRange,
+             LambdaCaptureDefault CaptureDefault,
+             ArrayRef<Capture> Captures,
+             bool ExplicitParams,
+             ArrayRef<Expr *> CaptureInits,
+             SourceLocation ClosingBrace);
+
+  Stmt **getStoredStmts() const {
+    LambdaExpr *This = const_cast<LambdaExpr *>(this);
+    return reinterpret_cast<Stmt **>(reinterpret_cast<Capture *>(This + 1)
+                                     + NumCaptures);
+  }
+
+public:
+  /// \brief Construct a new lambda expression.
+  static LambdaExpr *Create(ASTContext &C, 
+                            CXXRecordDecl *Class,
+                            SourceRange IntroducerRange,
+                            LambdaCaptureDefault CaptureDefault,
+                            ArrayRef<Capture> Captures,
+                            bool ExplicitParams,
+                            ArrayRef<Expr *> CaptureInits,
+                            SourceLocation ClosingBrace);
+
+  /// \brief Determine the default capture kind for this lambda.
+  LambdaCaptureDefault getCaptureDefault() const {
+    return static_cast<LambdaCaptureDefault>(CaptureDefault);
+  }
+
+  /// \brief An iterator that walks over the captures of the lambda,
+  /// both implicit and explicit.
+  typedef const Capture *capture_iterator;
+
+  /// \brief Retrieve an iterator pointing to the first lambda capture.
+  capture_iterator capture_begin() const {
+    return reinterpret_cast<const Capture *>(this + 1);
+  }
+
+  /// \brief Retrieve an iterator pointing past the end of the
+  /// sequence of lambda captures.
+  capture_iterator capture_end() const {
+    return capture_begin() + NumCaptures;
+  }
+
+  /// \brief Retrieve an iterator pointing to the first explicit
+  /// lambda capture.
+  capture_iterator explicit_capture_begin() const {
+    return capture_begin();
+  }
+
+  /// \brief Retrieve an iterator pointing past the end of the sequence of
+  /// explicit lambda captures.
+  capture_iterator explicit_capture_end() const {
+    return capture_begin() + NumExplicitCaptures;
+  }
+
+  /// \brief Retrieve an iterator pointing to the first implicit
+  /// lambda capture.
+  capture_iterator implicit_capture_begin() const {
+    return explicit_capture_end();
+  }
+
+  /// \brief Retrieve an iterator pointing past the end of the sequence of
+  /// implicit lambda captures.
+  capture_iterator implicit_capture_end() const {
+    return capture_end();
+  }
+
+  /// \brief Iterator that walks over the capture initialization
+  /// arguments.
+  typedef Expr **capture_init_iterator;
+
+  /// \brief Retrieve the first initialization argument for this
+  /// lambda expression (which initializes the first capture field).
+  capture_init_iterator capture_init_begin() const {
+    return reinterpret_cast<Expr **>(getStoredStmts() + 1);
+  }
+
+  /// \brief Retrieve the iterator pointing one past the last
+  /// initialization argument for this lambda expression (which
+  /// initializes the first capture field).
+  capture_init_iterator capture_init_end() const {
+    return capture_init_begin() + NumCaptures;
+  }
+
+  /// \brief Retrieve the source range covering the lambda introducer,
+  /// which contains the explicit capture list surrounded by square
+  /// brackets ([...]).
+  SourceRange getIntroducerRange() const { return IntroducerRange; }
+
+  /// \brief Retrieve the class that corresponds to the lambda, which
+  /// stores the captures in its fields and provides the various
+  /// operations permitted on a lambda (copying, calling).
+  CXXRecordDecl *getLambdaClass() const;
+
+  /// \brief Retrieve the function call operator associated with this
+  /// lambda expression. 
+  CXXMethodDecl *getCallOperator() const;
+
+  /// \brief Retrieve the body of the lambda.
+  CompoundStmt *getBody() const {
+    return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
+  }
+
+  /// \brief Determine whether the lambda is mutable, meaning that any
+  /// captures values can be modified.
+  bool isMutable() const;
+
+  /// \brief Determine whether this lambda has an explicit parameter
+  /// list vs. an implicit (empty) parameter list.
+  bool hasExplicitParameters() const { return ExplicitParams; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == LambdaExprClass;
+  }
+  static bool classof(const LambdaExpr *) { return true; }
+
+  SourceRange getSourceRange() const {
+    return SourceRange(IntroducerRange.getBegin(), ClosingBrace);
+  }
+
+  child_range children() { 
+    return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
+  }
+
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+};
+
 /// CXXScalarValueInitExpr - [C++ 5.2.3p2]
 /// Expression "T()" which creates a value-initialized rvalue of type
 /// T, which is a non-class type.

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Feb  7 04:09:13 2012
@@ -1953,6 +1953,10 @@
     TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
   })
 
+DEF_TRAVERSE_STMT(LambdaExpr, {
+    TRY_TO(TraverseStmt(S->getBody()));
+  })
+
 DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
     // This is called for code like 'T()', where T is a template argument.
     TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Feb  7 04:09:13 2012
@@ -2857,6 +2857,9 @@
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
+  void printExceptionSpecification(std::string &S, 
+                                   PrintingPolicy Policy) const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionProto;
   }

Added: cfe/trunk/include/clang/Basic/Lambda.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Lambda.h?rev=149977&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/Lambda.h (added)
+++ cfe/trunk/include/clang/Basic/Lambda.h Tue Feb  7 04:09:13 2012
@@ -0,0 +1,38 @@
+//===--- Lambda.h - Types for C++ Lambdas -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several types used to describe C++ lambda
+// expressions that are shared between the parser and AST.
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_BASIC_LAMBDA_H
+#define LLVM_CLANG_BASIC_LAMBDA_H
+
+namespace clang {
+
+/// LambdaCaptureDefault - The default, if any, capture method for a
+/// lambda expression.
+enum LambdaCaptureDefault {
+  LCD_None,
+  LCD_ByCopy,
+  LCD_ByRef
+};
+
+/// LambdaCaptureKind - The different capture forms in a lambda
+/// introducer: 'this' or a copied or referenced variable.
+enum LambdaCaptureKind {
+  LCK_This,
+  LCK_ByCopy,
+  LCK_ByRef
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_LAMBDA_H

Propchange: cfe/trunk/include/clang/Basic/Lambda.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/include/clang/Basic/Lambda.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/include/clang/Basic/Lambda.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Feb  7 04:09:13 2012
@@ -127,6 +127,7 @@
 def SubstNonTypeTemplateParmExpr : DStmt<Expr>;
 def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
 def MaterializeTemporaryExpr : DStmt<Expr>;
+def LambdaExpr : DStmt<Expr>;
 
 // Obj-C Expressions.
 def ObjCStringLiteral : DStmt<Expr>;

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Tue Feb  7 04:09:13 2012
@@ -25,6 +25,7 @@
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/Lex/Token.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/Lambda.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/SmallVector.h"
@@ -1917,31 +1918,14 @@
   SourceLocation LastLocation;
 };
 
-/// LambdaCaptureDefault - The default, if any, capture method for a
-/// lambda expression.
-enum LambdaCaptureDefault {
-  LCD_None,
-  LCD_ByCopy,
-  LCD_ByRef
-};
-
-/// LambdaCaptureKind - The different capture forms in a lambda
-/// introducer: 'this' or a copied or referenced variable.
-enum LambdaCaptureKind {
-  LCK_This,
-  LCK_ByCopy,
-  LCK_ByRef
-};
-
 /// LambdaCapture - An individual capture in a lambda introducer.
 struct LambdaCapture {
   LambdaCaptureKind Kind;
   SourceLocation Loc;
   IdentifierInfo* Id;
 
-  LambdaCapture(LambdaCaptureKind Kind,
-                     SourceLocation Loc,
-                     IdentifierInfo* Id = 0)
+  LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
+                IdentifierInfo* Id = 0)
     : Kind(Kind), Loc(Loc), Id(Id)
   {}
 };

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Tue Feb  7 04:09:13 2012
@@ -279,12 +279,18 @@
 public:
   /// \brief The class that describes the lambda.
   CXXRecordDecl *Lambda;
-  
+
+  /// \brief Source range covering the lambda introducer [...].
+  SourceRange IntroducerRange;
+
   /// \brief The number of captures in the \c Captures list that are 
   /// explicit captures.
   unsigned NumExplicitCaptures;
 
   bool Mutable;
+  
+  /// \brief Whether the (empty) parameter list is explicit.
+  bool ExplicitParams;
 
   LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda)
     : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Feb  7 04:09:13 2012
@@ -2019,6 +2019,16 @@
     return MergeCanThrow(CT, CanSubExprsThrow(C, this));
   }
 
+  case LambdaExprClass: {
+    const LambdaExpr *Lambda = cast<LambdaExpr>(this);
+    CanThrowResult CT = Expr::CT_Cannot;
+    for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
+                                        CapEnd = Lambda->capture_init_end();
+         Cap != CapEnd; ++Cap)
+      CT = MergeCanThrow(CT, (*Cap)->CanThrow(C));
+    return CT;
+  }
+
   case CXXNewExprClass: {
     CanThrowResult CT;
     if (isTypeDependent())

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Feb  7 04:09:13 2012
@@ -712,6 +712,113 @@
   }
 }
 
+LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit,
+                             LambdaCaptureKind Kind, VarDecl *Var,
+                             SourceLocation EllipsisLoc)
+  : VarAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
+{
+  unsigned Bits = 0;
+  if (Implicit)
+    Bits |= Capture_Implicit;
+  
+  switch (Kind) {
+  case LCK_This: 
+    assert(Var == 0 && "'this' capture cannot have a variable!");
+    break;
+
+  case LCK_ByCopy:
+    Bits |= Capture_ByCopy;
+    // Fall through 
+  case LCK_ByRef:
+    assert(Var && "capture must have a variable!");
+    break;
+  }
+  VarAndBits.setInt(Bits);
+}
+
+LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const {
+  if (capturesThis())
+    return LCK_This;
+
+  return (VarAndBits.getInt() & Capture_ByCopy)? LCK_ByCopy : LCK_ByRef;
+}
+
+LambdaExpr::LambdaExpr(QualType T, 
+                       SourceRange IntroducerRange,
+                       LambdaCaptureDefault CaptureDefault,
+                       ArrayRef<Capture> Captures, 
+                       bool ExplicitParams,
+                       ArrayRef<Expr *> CaptureInits,
+                       SourceLocation ClosingBrace)
+  : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
+         T->isDependentType(), T->isDependentType(), T->isDependentType(),
+         /*ContainsUnexpandedParameterPack=*/false),
+    IntroducerRange(IntroducerRange),
+    NumCaptures(Captures.size()),
+    NumExplicitCaptures(0),
+    CaptureDefault(CaptureDefault),
+    ExplicitParams(ExplicitParams),
+    ClosingBrace(ClosingBrace)
+{
+  assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
+
+  // Copy captures.
+  // FIXME: Do we need to update "contains unexpanded parameter pack" here?
+  Capture *ToCapture = reinterpret_cast<Capture *>(this + 1);
+  for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
+    if (Captures[I].isExplicit())
+      ++NumExplicitCaptures;
+    *ToCapture++ = Captures[I];
+  }
+
+  // Copy initialization expressions for the non-static data members.
+  Stmt **Stored = getStoredStmts();
+  for (unsigned I = 0, N = CaptureInits.size(); I != N; ++I)
+    *Stored++ = CaptureInits[I];
+
+  // Copy the body of the lambda.
+  *Stored++ = getCallOperator()->getBody();
+}
+
+LambdaExpr *LambdaExpr::Create(ASTContext &Context, 
+                               CXXRecordDecl *Class,
+                               SourceRange IntroducerRange,
+                               LambdaCaptureDefault CaptureDefault,
+                               ArrayRef<Capture> Captures, 
+                               bool ExplicitParams,
+                               ArrayRef<Expr *> CaptureInits,
+                               SourceLocation ClosingBrace) {
+  // Determine the type of the expression (i.e., the type of the
+  // function object we're creating).
+  QualType T = Context.getTypeDeclType(Class);
+  size_t Size = sizeof(LambdaExpr) + sizeof(Capture) * Captures.size()
+              + sizeof(Stmt *) * (Captures.size() + 1);
+
+  void *Mem = Context.Allocate(Size, llvm::alignOf<LambdaExpr>());
+  return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, 
+                              Captures, ExplicitParams, CaptureInits,
+                              ClosingBrace);
+}
+
+CXXRecordDecl *LambdaExpr::getLambdaClass() const {
+  return getType()->getAsCXXRecordDecl();
+}
+
+CXXMethodDecl *LambdaExpr::getCallOperator() const {
+  CXXRecordDecl *Record = getLambdaClass();
+  DeclarationName Name
+    = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclContext::lookup_result Calls = Record->lookup(Name);
+  assert(Calls.first != Calls.second && "Missing lambda call operator!");
+  CXXMethodDecl *Result = cast<CXXMethodDecl>(*Calls.first++);
+  assert(Calls.first == Calls.second && "More than lambda one call operator?");
+  return Result;
+}
+
+bool LambdaExpr::isMutable() const {
+  return (getCallOperator()->getTypeQualifiers() & Qualifiers::Const) == 0;
+}
+
 ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
                                    ArrayRef<CleanupObject> objects)
   : Expr(ExprWithCleanupsClass, subexpr->getType(),

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Feb  7 04:09:13 2012
@@ -330,6 +330,7 @@
     // Some C++ expressions are always class temporaries.
   case Expr::CXXConstructExprClass:
   case Expr::CXXTemporaryObjectExprClass:
+  case Expr::LambdaExprClass:
     return Cl::CL_ClassTemporary;
 
   case Expr::VAArgExprClass:

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Feb  7 04:09:13 2012
@@ -6086,6 +6086,7 @@
   case Expr::PseudoObjectExprClass:
   case Expr::AtomicExprClass:
   case Expr::InitListExprClass:
+  case Expr::LambdaExprClass:
     return ICEDiag(2, E->getLocStart());
 
   case Expr::SizeOfPackExprClass:

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Feb  7 04:09:13 2012
@@ -2247,6 +2247,7 @@
   case Expr::ImplicitValueInitExprClass:
   case Expr::InitListExprClass:
   case Expr::ParenListExprClass:
+  case Expr::LambdaExprClass:
     llvm_unreachable("unexpected statement kind");
 
   // FIXME: invent manglings for all these.

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Feb  7 04:09:13 2012
@@ -1263,6 +1263,98 @@
   OS << ")";
 }
 
+void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
+  OS << '[';
+  bool NeedComma = false;
+  switch (Node->getCaptureDefault()) {
+  case LCD_None:
+    break;
+
+  case LCD_ByCopy:
+    OS << '=';
+    NeedComma = true;
+    break;
+
+  case LCD_ByRef:
+    OS << '&';
+    NeedComma = true;
+    break;
+  }
+  for (LambdaExpr::capture_iterator C = Node->explicit_capture_begin(),
+                                 CEnd = Node->explicit_capture_end();
+       C != CEnd;
+       ++C) {
+    if (NeedComma)
+      OS << ", ";
+    NeedComma = true;
+
+    switch (C->getCaptureKind()) {
+    case LCK_This:
+      OS << "this";
+      break;
+
+    case LCK_ByRef:
+      if (Node->getCaptureDefault() != LCD_ByRef)
+        OS << '&';
+      OS << C->getCapturedVar()->getName();
+      break;
+
+    case LCK_ByCopy:
+      if (Node->getCaptureDefault() != LCD_ByCopy)
+        OS << '=';
+      OS << C->getCapturedVar()->getName();
+      break;
+    }
+  }
+  OS << ']';
+
+  if (Node->hasExplicitParameters()) {
+    OS << " (";
+    CXXMethodDecl *Method = Node->getCallOperator();
+    NeedComma = false;
+    for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+                                    PEnd = Method->param_end();
+         P != PEnd; ++P) {
+      if (NeedComma) {
+        OS << ", ";
+      } else {
+        NeedComma = true;
+      }
+      std::string ParamStr = (*P)->getNameAsString();
+      (*P)->getOriginalType().getAsStringInternal(ParamStr, Policy);
+      OS << ParamStr;
+    }
+    if (Method->isVariadic()) {
+      if (NeedComma)
+        OS << ", ";
+      OS << "...";
+    }
+    OS << ')';
+
+    if (Node->isMutable())
+      OS << " mutable";
+
+    const FunctionProtoType *Proto
+      = Method->getType()->getAs<FunctionProtoType>();
+    {
+      std::string ExceptionSpec;
+      Proto->printExceptionSpecification(ExceptionSpec, Policy);
+      OS << ExceptionSpec;
+    }
+
+    // FIXME: Attributes
+
+    // FIXME: Suppress trailing return type if it wasn't specified in
+    // the source.
+    OS << " -> " << Proto->getResultType().getAsString(Policy);
+  }
+
+  // Print the body.
+  CompoundStmt *Body = Node->getBody();
+  OS << ' ';
+  PrintStmt(Body);
+}
+
 void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
   if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo())
     OS << TSInfo->getType().getAsString(Policy) << "()";

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Feb  7 04:09:13 2012
@@ -790,6 +790,24 @@
 }
 
 void
+StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
+  VisitExpr(S);
+  for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
+                                 CEnd = S->explicit_capture_end();
+       C != CEnd; ++C) {
+    ID.AddInteger(C->getCaptureKind());
+    if (C->capturesVariable()) {
+      VisitDecl(C->getCapturedVar());
+      ID.AddBoolean(C->isPackExpansion());
+    }
+  }
+  // Note: If we actually needed to be able to match lambda
+  // expressions, we would have to consider parameters and return type
+  // here, among other things.
+  VisitStmt(S->getBody());
+}
+
+void
 StmtProfiler::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *S) {
   VisitExpr(S);
 }

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Tue Feb  7 04:09:13 2012
@@ -397,6 +397,35 @@
   print(T->getElementType(), S);
 }
 
+void 
+FunctionProtoType::printExceptionSpecification(std::string &S, 
+                                               PrintingPolicy Policy) const {
+  
+  if (hasDynamicExceptionSpec()) {
+    S += " throw(";
+    if (getExceptionSpecType() == EST_MSAny)
+      S += "...";
+    else
+      for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
+        if (I)
+          S += ", ";
+        
+        S += getExceptionType(I).getAsString(Policy);
+      }
+    S += ")";
+  } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
+    S += " noexcept";
+    if (getExceptionSpecType() == EST_ComputedNoexcept) {
+      S += "(";
+      llvm::raw_string_ostream EOut(S);
+      getNoexceptExpr()->printPretty(EOut, 0, Policy);
+      EOut.flush();
+      S += EOut.str();
+      S += ")";
+    }
+  }
+}
+
 void TypePrinter::printFunctionProto(const FunctionProtoType *T, 
                                      std::string &S) { 
   // If needed for precedence reasons, wrap the inner part in grouping parens.
@@ -470,33 +499,7 @@
     S += " &&";
     break;
   }
-
-  if (T->hasDynamicExceptionSpec()) {
-    S += " throw(";
-    if (T->getExceptionSpecType() == EST_MSAny)
-      S += "...";
-    else
-      for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
-        if (I)
-          S += ", ";
-
-        std::string ExceptionType;
-        print(T->getExceptionType(I), ExceptionType);
-        S += ExceptionType;
-      }
-    S += ")";
-  } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) {
-    S += " noexcept";
-    if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
-      S += "(";
-      llvm::raw_string_ostream EOut(S);
-      T->getNoexceptExpr()->printPretty(EOut, 0, Policy);
-      EOut.flush();
-      S += EOut.str();
-      S += ")";
-    }
-  }
-
+  T->printExceptionSpecification(S, Policy);
   print(T->getResultType(), S);
 }
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb  7 04:09:13 2012
@@ -9637,11 +9637,77 @@
       byRef = hasBlocksAttr || type->isReferenceType();
     }
 
-    // Build a copy expression if we are capturing by copy and the copy
-    // might be non-trivial.
+    // Build a copy expression if we are capturing by copy into a
+    // block and the copy might be non-trivial.
     Expr *copyExpr = 0;
     const RecordType *rtype;
-    if (!byRef && getLangOptions().CPlusPlus &&
+    if (isLambda) {
+      CXXRecordDecl *Lambda = cast<LambdaScopeInfo>(CSI)->Lambda;
+      QualType FieldType;
+      if (byRef) {
+        // 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.
+        FieldType = Context.getLValueReferenceType(type.getNonReferenceType());
+      } else {
+        // C++11 [expr.prim.lambda]p14:
+        // 
+        //   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 ]
+        if (const ReferenceType *RefType
+                                      = type->getAs<ReferenceType>()) {
+          if (!RefType->getPointeeType()->isFunctionType())
+            FieldType = RefType->getPointeeType();
+          else
+            FieldType = type;
+        } else {
+          FieldType = type;
+        }
+      }
+
+      // Build the non-static data member.
+      FieldDecl *Field
+        = FieldDecl::Create(Context, Lambda, loc, loc, 0, FieldType,
+                            Context.getTrivialTypeSourceInfo(FieldType, loc),
+                            0, false, false);
+      Field->setImplicit(true);
+      Field->setAccess(AS_private);
+
+      // C++11 [expr.prim.lambda]p21:
+      //   When the lambda-expression is evaluated, the entities that
+      //   are captured by copy are used to direct-initialize each
+      //   corresponding non-static data member of the resulting closure
+      //   object. (For array members, the array elements are
+      //   direct-initialized in increasing subscript order.) These
+      //   initializations are performed in the (unspecified) order in
+      //   which the non-static data members are declared.
+      //
+      // FIXME: Introduce an initialization entity for lambda captures.
+      // FIXME: Totally broken for arrays.
+      Expr *Ref = new (Context) DeclRefExpr(var, type.getNonReferenceType(),
+                                            VK_LValue, loc);
+      InitializedEntity InitEntity
+        = InitializedEntity::InitializeMember(Field, /*Parent=*/0);
+      InitializationKind InitKind
+        = InitializationKind::CreateDirect(loc, loc, loc);
+      InitializationSequence Init(*this, InitEntity, InitKind, &Ref, 1);
+      if (!Init.Diagnose(*this, InitEntity, InitKind, &Ref, 1)) {
+        ExprResult Result = Init.Perform(*this, InitEntity, InitKind, 
+                                         MultiExprArg(*this, &Ref, 1));
+        if (!Result.isInvalid())
+          copyExpr = Result.take();
+      }
+    } else if (!byRef && getLangOptions().CPlusPlus &&
         (rtype = type.getNonReferenceType()->getAs<RecordType>())) {
       // The capture logic needs the destructor, so make sure we mark it.
       // Usually this is unnecessary because most local variables have
@@ -9654,10 +9720,10 @@
       // According to the blocks spec, the capture of a variable from
       // the stack requires a const copy constructor.  This is not true
       // of the copy/move done to move a __block variable to the heap.
-      // There is no equivalent language in the C++11 specification of lambdas.
-      if (isBlock)
-        type.addConst();
+      type.addConst();
 
+      // FIXME: Add an initialized entity for lambda capture.
+      // FIXME: Won't work for arrays, although we do need this behavior.
       Expr *declRef = new (Context) DeclRefExpr(var, type, VK_LValue, loc);
       ExprResult result =
         PerformCopyInitialization(

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Feb  7 04:09:13 2012
@@ -4895,6 +4895,7 @@
   // at this point, but we need something to attach child declarations to.
   QualType MethodTy;
   TypeSourceInfo *MethodTyInfo;
+  bool ExplicitParams = true;
   if (ParamInfo.getNumTypeObjects() == 0) {
     // C++11 [expr.prim.lambda]p4:
     //   If a lambda-expression does not include a lambda-declarator, it is as 
@@ -4904,6 +4905,7 @@
     MethodTy = Context.getFunctionType(Context.DependentTy,
                                        /*Args=*/0, /*NumArgs=*/0, EPI);
     MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+    ExplicitParams = false;
   } else {
     assert(ParamInfo.isFunctionDeclarator() &&
            "lambda-declarator is a function");
@@ -4967,9 +4969,10 @@
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
   else if (Intro.Default == LCD_ByRef)
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
-
+  LSI->IntroducerRange = Intro.Range;
+  LSI->ExplicitParams = ExplicitParams;
   LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0;
-
+ 
   // Handle explicit captures.
   for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
          C = Intro.Captures.begin(), 
@@ -5116,8 +5119,78 @@
 
 ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
                                  Stmt *Body, Scope *CurScope) {
-  // FIXME: Implement
+  // Leave the expression-evaluation context.
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
+  // Leave the context of the lambda.
+  PopDeclContext();
+
+  // FIXME: End-of-lambda checking
+
+  // Collect information from the lambda scope.
+  llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
+  llvm::SmallVector<Expr *, 4> CaptureInits;
+  LambdaCaptureDefault CaptureDefault;
+  CXXRecordDecl *Class;
+  SourceRange IntroducerRange;
+  bool ExplicitParams;
+  {
+    LambdaScopeInfo *LSI = getCurLambda();
+    Class = LSI->Lambda;
+    IntroducerRange = LSI->IntroducerRange;
+    ExplicitParams = LSI->ExplicitParams;
+
+    // Translate captures.
+    for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
+      LambdaScopeInfo::Capture From = LSI->Captures[I];
+      assert(!From.isBlockCapture() && "Cannot capture __block variables");
+      bool IsImplicit = I >= LSI->NumExplicitCaptures;
+
+      // Handle 'this' capture.
+      if (From.isThisCapture()) {
+        Captures.push_back(LambdaExpr::Capture(From.getLocation(),
+                                               IsImplicit,
+                                               LCK_This));
+        CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
+                                                         getCurrentThisType(),
+                                                         /*isImplicit=*/true));
+        continue;
+      }
+
+      VarDecl *Var = From.getVariable();
+      // FIXME: Handle pack expansions.
+      LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
+      Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, 
+                                             Kind, Var));
+      CaptureInits.push_back(From.getCopyExpr());
+    }
+
+    switch (LSI->ImpCaptureStyle) {
+    case CapturingScopeInfo::ImpCap_None:
+      CaptureDefault = LCD_None;
+      break;
+
+    case CapturingScopeInfo::ImpCap_LambdaByval:
+      CaptureDefault = LCD_ByCopy;
+      break;
+
+    case CapturingScopeInfo::ImpCap_LambdaByref:
+      CaptureDefault = LCD_ByRef;
+      break;
+
+    case CapturingScopeInfo::ImpCap_Block:
+      llvm_unreachable("block capture in lambda");
+      break;
+    }
+
+    PopFunctionScopeInfo();
+  }
+
+  Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
+                                    CaptureDefault, Captures, ExplicitParams, 
+                                    CaptureInits, Body->getLocEnd());
+  (void)Lambda;
   Diag(StartLoc, diag::err_lambda_unsupported);
-  ActOnLambdaError(StartLoc, CurScope);
   return ExprError();
 }

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Feb  7 04:09:13 2012
@@ -7620,6 +7620,13 @@
 
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
+  assert(false && "Lambda expressions cannot be instantiated (yet)");
+  return ExprError();
+}
+
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
                                                   CXXUnresolvedConstructExpr *E) {
   TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Feb  7 04:09:13 2012
@@ -1048,6 +1048,11 @@
   E->Type = GetTypeSourceInfo(Record, Idx);
 }
 
+void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) {
+  VisitExpr(E);
+  assert(false && "Cannot deserialize lambda expressions yet");
+}
+
 void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
   VisitExplicitCastExpr(E);
   SourceRange R = ReadSourceRange(Record, Idx);

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Feb  7 04:09:13 2012
@@ -1022,6 +1022,11 @@
   Code = serialization::EXPR_CXX_TEMPORARY_OBJECT;
 }
 
+void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) {
+  VisitExpr(E);
+  assert(false && "Cannot serialize lambda expressions yet");
+}
+
 void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
   VisitExplicitCastExpr(E);
   Writer.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc()),

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Feb  7 04:09:13 2012
@@ -486,6 +486,7 @@
     case Stmt::SubstNonTypeTemplateParmPackExprClass:
     case Stmt::SEHTryStmtClass:
     case Stmt::SEHExceptStmtClass:
+    case Stmt::LambdaExprClass:
     case Stmt::SEHFinallyStmtClass: {
       const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState());
       Engine.addAbortedBlock(node, currentBuilderContext->getBlock());

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp?rev=149977&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp Tue Feb  7 04:09:13 2012
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+class NonCopyable {
+  NonCopyable(const NonCopyable&); // expected-note 2 {{implicitly declared private here}}
+};
+
+void capture_by_copy(NonCopyable nc, NonCopyable &ncr) {
+  // FIXME: error messages should talk about capture
+  [nc] { }; // expected-error{{field of type 'NonCopyable' has private copy constructor}} \
+             // expected-error{{lambda expressions are not supported yet}}
+  [ncr] { }; // expected-error{{field of type 'NonCopyable' has private copy constructor}} \
+             // expected-error{{lambda expressions are not supported yet}}
+}
+
+// FIXME: arrays!

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp?rev=149977&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp Tue Feb  7 04:09:13 2012
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+class NonCopyable {
+  NonCopyable(const NonCopyable&);
+};
+
+void capture_by_ref(NonCopyable nc, NonCopyable &ncr) {
+  [&nc] {}; // expected-error{{lambda expressions are not supported yet}}
+  [&ncr] {}; // expected-error{{lambda expressions are not supported yet}}
+}

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=149977&r1=149976&r2=149977&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Feb  7 04:09:13 2012
@@ -226,6 +226,7 @@
   case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::UnaryTypeTraitExprClass:
   case Stmt::VAArgExprClass:
+  case Stmt::LambdaExprClass:
     K = CXCursor_UnexposedExpr;
     break;
 





More information about the cfe-commits mailing list