[cfe-commits] r150393 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h lib/AST/DeclCXX.cpp lib/AST/ExprCXX.cpp lib/Sema/SemaLambda.cpp

Douglas Gregor dgregor at apple.com
Mon Feb 13 07:44:47 PST 2012


Author: dgregor
Date: Mon Feb 13 09:44:47 2012
New Revision: 150393

URL: http://llvm.org/viewvc/llvm-project?rev=150393&view=rev
Log:
Move the storage of lambda captures and capture initializers from
LambdaExpr over to the CXXRecordDecl. This allows us to eliminate the
back-link from the closure type to the LambdaExpr, which will simplify
and lazify AST deserialization.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 13 09:44:47 2012
@@ -59,7 +59,6 @@
   class CXXRecordDecl;
   class Decl;
   class FieldDecl;
-  class LambdaExpr;
   class MangleContext;
   class ObjCIvarDecl;
   class ObjCIvarRefExpr;
@@ -164,10 +163,6 @@
   llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
     ClassScopeSpecializationPattern;
 
-  /// \brief Mapping from closure types to the lambda expressions that
-  /// create instances of them.
-  llvm::DenseMap<const CXXRecordDecl *, LambdaExpr *> Lambdas;
-
   /// \brief Representation of a "canonical" template template parameter that
   /// is used in canonical template names.
   class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Feb 13 09:44:47 2012
@@ -2387,9 +2387,11 @@
   /// a definition until the definition has been fully processed.
   bool IsCompleteDefinition : 1;
 
+protected:
   /// IsBeingDefined - True if this is currently being defined.
   bool IsBeingDefined : 1;
 
+private:
   /// IsEmbeddedInDeclarator - True if this tag declaration is
   /// "embedded" (i.e., defined or declared for the very first time)
   /// in the syntax of a declarator.

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Feb 13 09:44:47 2012
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_AST_DECLCXX_H
 
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/UnresolvedSet.h"
@@ -555,6 +556,40 @@
     }
   } *DefinitionData;
 
+  /// \brief Describes a C++ closure type (generated by a lambda expression).
+  struct LambdaDefinitionData : public DefinitionData {
+    typedef LambdaExpr::Capture Capture;
+    
+    LambdaDefinitionData(CXXRecordDecl *D) 
+      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), Extra(0) { 
+      IsLambda = true;
+    }
+
+    /// \brief The number of captures in this lambda.
+    unsigned NumCaptures : 16;
+
+    /// \brief The number of explicit captures in this lambda.
+    unsigned NumExplicitCaptures : 16;
+
+    /// \brief The "extra" data associated with the lambda, including
+    /// captures, capture initializers, and the body of the lambda.
+    void *Extra;
+    
+    /// \brief Allocate the "extra" data associated with a lambda definition.
+    void allocateExtra(ArrayRef<Capture> Captures,
+                       ArrayRef<Expr *> CaptureInits,
+                       Stmt *Body);
+    
+    /// \brief Retrieve the set of captures.
+    Capture *getCaptures() const { return reinterpret_cast<Capture *>(Extra); }
+    
+    /// \brief Retrieve the set of stored statements, which contains the capture
+    /// initializers followed by the body of the lambda.
+    Stmt **getStoredStmts() const {
+      return reinterpret_cast<Stmt **>(getCaptures() + NumCaptures);
+    }
+  };
+
   struct DefinitionData &data() {
     assert(DefinitionData && "queried property of class with no definition");
     return *DefinitionData;
@@ -565,6 +600,13 @@
     return *DefinitionData;
   }
 
+  struct LambdaDefinitionData &getLambdaData() const {
+    assert(DefinitionData && "queried property of lambda with no definition");
+    assert(DefinitionData->IsLambda && 
+           "queried lambda property of non-lambda class");
+    return static_cast<LambdaDefinitionData &>(*DefinitionData);
+  }
+
   /// \brief The template or declaration that this declaration
   /// describes or was instantiated from, respectively.
   ///
@@ -578,6 +620,7 @@
     TemplateOrInstantiation;
 
   friend class DeclContext;
+  friend class LambdaExpr;
 
   /// \brief Notify the class that member has been added.
   ///
@@ -647,6 +690,8 @@
                                SourceLocation StartLoc, SourceLocation IdLoc,
                                IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0,
                                bool DelayTypeCreation = false);
+  static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
+                                     SourceLocation Loc);
   static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
 
   bool isDynamicClass() const {
@@ -928,12 +973,6 @@
   /// \brief Determine whether this class describes a lambda function object.
   bool isLambda() const { return hasDefinition() && data().IsLambda; }
   
-  /// \brief Mark this as a closure type from a lambda expression.
-  void makeLambda() { data().IsLambda = true; }
-
-  /// \brief Set the lambda expression associated with this closure type.
-  void setLambda(LambdaExpr *Lambda);
-
   /// \brief For a closure type, retrieve the mapping from captured
   /// variables and this to the non-static data members that store the
   /// values or references of the captures.

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Feb 13 09:44:47 2012
@@ -1048,12 +1048,6 @@
   /// \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;
@@ -1163,12 +1157,6 @@
              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, 
@@ -1190,39 +1178,27 @@
   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);
-  }
+  capture_iterator capture_begin() const;
 
   /// \brief Retrieve an iterator pointing past the end of the
   /// sequence of lambda captures.
-  capture_iterator capture_end() const {
-    return capture_begin() + NumCaptures;
-  }
+  capture_iterator capture_end() const;
 
   /// \brief Retrieve an iterator pointing to the first explicit
   /// lambda capture.
-  capture_iterator explicit_capture_begin() const {
-    return capture_begin();
-  }
+  capture_iterator explicit_capture_begin() const;
 
   /// \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;
-  }
+  capture_iterator explicit_capture_end() const;
 
   /// \brief Retrieve an iterator pointing to the first implicit
   /// lambda capture.
-  capture_iterator implicit_capture_begin() const {
-    return explicit_capture_end();
-  }
+  capture_iterator implicit_capture_begin() const;
 
   /// \brief Retrieve an iterator pointing past the end of the sequence of
   /// implicit lambda captures.
-  capture_iterator implicit_capture_end() const {
-    return capture_end();
-  }
+  capture_iterator implicit_capture_end() const;
 
   /// \brief Iterator that walks over the capture initialization
   /// arguments.
@@ -1230,15 +1206,11 @@
 
   /// \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());
-  }
+  capture_init_iterator capture_init_begin() const;
 
   /// \brief Retrieve the iterator pointing one past the last
   /// initialization argument for this lambda expression.
-  capture_init_iterator capture_init_end() const {
-    return capture_init_begin() + NumCaptures;
-  }
+  capture_init_iterator capture_init_end() const;
 
   /// \brief Retrieve the source range covering the lambda introducer,
   /// which contains the explicit capture list surrounded by square
@@ -1255,9 +1227,7 @@
   CXXMethodDecl *getCallOperator() const;
 
   /// \brief Retrieve the body of the lambda.
-  CompoundStmt *getBody() const {
-    return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
-  }
+  CompoundStmt *getBody() const;
 
   /// \brief Determine whether the lambda is mutable, meaning that any
   /// captures values can be modified.
@@ -1276,9 +1246,7 @@
     return SourceRange(IntroducerRange.getBegin(), ClosingBrace);
   }
 
-  child_range children() { 
-    return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
-  }
+  child_range children();
 
   friend class ASTStmtReader;
   friend class ASTStmtWriter;

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Feb 13 09:44:47 2012
@@ -35,6 +35,35 @@
   return new (Mem) AccessSpecDecl(EmptyShell());
 }
 
+void CXXRecordDecl::LambdaDefinitionData::allocateExtra(
+       ArrayRef<LambdaExpr::Capture> Captures,
+       ArrayRef<Expr *> CaptureInits,
+       Stmt *Body) {
+  NumCaptures = Captures.size();
+  NumExplicitCaptures = 0;
+  
+  ASTContext &Context = Definition->getASTContext();
+  this->Extra = Context.Allocate(sizeof(Capture) * Captures.size() +
+                                 sizeof(Stmt*) * (Captures.size() + 1));
+  
+  // Copy captures.
+  Capture *ToCapture = getCaptures();
+  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++ = Body;
+}
+
 
 CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
   : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
@@ -83,6 +112,16 @@
   return R;
 }
 
+CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
+                                           SourceLocation Loc) {
+  CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc,
+                                           0, 0);
+  R->IsBeingDefined = true;
+  R->DefinitionData = new (C) struct LambdaDefinitionData(R);
+  C.getTypeDeclType(R, /*PrevDecl=*/0);
+  return R;
+}
+
 CXXRecordDecl *
 CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl));
@@ -969,24 +1008,16 @@
   return isPOD() && data().HasOnlyCMembers;
 }
 
-void CXXRecordDecl::setLambda(LambdaExpr *Lambda) {
-  if (!Lambda)
-    return;
-
-  data().IsLambda = true;
-  getASTContext().Lambdas[this] = Lambda;
-}
-
 void CXXRecordDecl::getCaptureFields(
        llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
        FieldDecl *&ThisCapture) const {
   Captures.clear();
   ThisCapture = 0;
 
-  LambdaExpr *Lambda = getASTContext().Lambdas[this];
+  LambdaDefinitionData &Lambda = getLambdaData();
   RecordDecl::field_iterator Field = field_begin();
-  for (LambdaExpr::capture_iterator C = Lambda->capture_begin(), 
-                                 CEnd = Lambda->capture_end();
+  for (LambdaExpr::Capture *C = Lambda.getCaptures(), 
+                        *CEnd = C + Lambda.NumCaptures;
        C != CEnd; ++C, ++Field) {
     if (C->capturesThis()) {
       ThisCapture = *Field;

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Feb 13 09:44:47 2012
@@ -758,30 +758,16 @@
          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();
+  CXXRecordDecl *Class = getLambdaClass();
+  CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
+  Data.allocateExtra(Captures, CaptureInits, getCallOperator()->getBody());
+  
+  // FIXME: Propagate "has unexpanded parameter pack" bit.
 }
 
 LambdaExpr *LambdaExpr::Create(ASTContext &Context, 
@@ -804,6 +790,45 @@
                               ClosingBrace);
 }
 
+LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
+  return getLambdaClass()->getLambdaData().getCaptures();
+}
+
+LambdaExpr::capture_iterator LambdaExpr::capture_end() const {
+  struct CXXRecordDecl::LambdaDefinitionData &Data
+    = getLambdaClass()->getLambdaData();
+  return Data.getCaptures() + Data.NumCaptures;
+}
+
+LambdaExpr::capture_iterator LambdaExpr::explicit_capture_begin() const {
+  return capture_begin();
+}
+
+LambdaExpr::capture_iterator LambdaExpr::explicit_capture_end() const {
+  struct CXXRecordDecl::LambdaDefinitionData &Data
+    = getLambdaClass()->getLambdaData();
+  return Data.getCaptures() + Data.NumExplicitCaptures;
+}
+
+LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const {
+  return explicit_capture_end();
+}
+
+LambdaExpr::capture_iterator LambdaExpr::implicit_capture_end() const {
+  return capture_end();
+}
+
+LambdaExpr::capture_init_iterator LambdaExpr::capture_init_begin() const {
+  return reinterpret_cast<Expr **>(
+           getLambdaClass()->getLambdaData().getStoredStmts());
+}
+
+LambdaExpr::capture_init_iterator LambdaExpr::capture_init_end() const {
+  struct CXXRecordDecl::LambdaDefinitionData &Data
+    = getLambdaClass()->getLambdaData();
+  return reinterpret_cast<Expr **>(Data.getStoredStmts() + Data.NumCaptures);
+}
+
 CXXRecordDecl *LambdaExpr::getLambdaClass() const {
   return getType()->getAsCXXRecordDecl();
 }
@@ -819,10 +844,22 @@
   return Result;
 }
 
+/// \brief Retrieve the body of the lambda.
+CompoundStmt *LambdaExpr::getBody() const {
+  return cast<CompoundStmt>(*capture_init_end());
+}
+
 bool LambdaExpr::isMutable() const {
   return (getCallOperator()->getTypeQualifiers() & Qualifiers::Const) == 0;
 }
 
+Stmt::child_range LambdaExpr::children() {
+  struct CXXRecordDecl::LambdaDefinitionData &Data
+    = getLambdaClass()->getLambdaData();
+  return child_range(Data.getStoredStmts(), 
+                     Data.getStoredStmts() + Data.NumCaptures + 1);
+}
+
 ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
                                    ArrayRef<CleanupObject> objects)
   : Expr(ExprWithCleanupsClass, subexpr->getType(),

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150393&r1=150392&r2=150393&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 13 09:44:47 2012
@@ -28,12 +28,8 @@
     DC = DC->getParent();
 
   // Start constructing the lambda class.
-  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
-                                               Intro.Range.getBegin(),
-                                               /*IdLoc=*/Intro.Range.getBegin(),
-                                               /*Id=*/0);
-  Class->startDefinition();
-  Class->makeLambda();
+  CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, 
+                                                     Intro.Range.getBegin());
   CurContext->addDecl(Class);
 
   // Build the call operator; we don't really have all the relevant information
@@ -472,7 +468,6 @@
                                           CaptureDefault, Captures, 
                                           ExplicitParams, CaptureInits, 
                                           Body->getLocEnd());
-  Class->setLambda(Lambda);
 
   // C++11 [expr.prim.lambda]p2:
   //   A lambda-expression shall not appear in an unevaluated operand





More information about the cfe-commits mailing list