[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/

David Blaikie dblaikie at gmail.com
Tue Feb 7 08:59:41 PST 2012


On Tue, Feb 7, 2012 at 2:09 AM, Douglas Gregor <dgregor at apple.com> wrote:
> 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).

This parenthetical seems out of place (copy-pasted from the 'begin'
version, presumably) - "which initializes the last capture field"
would be ambiguous at best (if it refer to the "last initialization
argument") and probably reads incorrectly (as referring to "one past
the last initialization argument") so I'm not sure what wording you
might want there instead.

> +  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;
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list