[cfe-commits] r150401 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h lib/AST/DeclCXX.cpp lib/AST/ExprCXX.cpp

Douglas Gregor dgregor at apple.com
Mon Feb 13 09:20:40 PST 2012


Author: dgregor
Date: Mon Feb 13 11:20:40 2012
New Revision: 150401

URL: http://llvm.org/viewvc/llvm-project?rev=150401&view=rev
Log:
Split the storage of lambda information between the LambdaExpr and the
CXXRecordDecl in a way that actually makes some sense:
  - LambdaExpr contains all of the information for initializing the
  lambda object, including the capture initializers and associated
  array index variables.
  - CXXRecordDecl's LambdaDefinitionData contains the captures, which
  are needed to understand the captured variable references in the
  body of the lambda.


Modified:
    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

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=150401&r1=150400&r2=150401&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Feb 13 11:20:40 2012
@@ -561,8 +561,7 @@
     typedef LambdaExpr::Capture Capture;
     
     LambdaDefinitionData(CXXRecordDecl *D) 
-      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), 
-        HasArrayIndexVars(false), Extra(0) { 
+      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), Captures(0) { 
       IsLambda = true;
     }
 
@@ -572,42 +571,10 @@
     /// \brief The number of explicit captures in this lambda.
     unsigned NumExplicitCaptures : 15;
 
-    /// \brief Whether This lambda has any by-copy array captures, and therefore
-    /// has array index variables.
-    unsigned HasArrayIndexVars : 1;
-    
     /// \brief The "extra" data associated with the lambda, including
     /// captures, capture initializers, the body of the lambda, and the
     /// array-index variables for array captures.
-    void *Extra;
-    
-    /// \brief Allocate the "extra" data associated with a lambda definition.
-    void allocateExtra(ArrayRef<Capture> Captures,
-                       ArrayRef<Expr *> CaptureInits,
-                       ArrayRef<VarDecl *> ArrayIndexVars,
-                       ArrayRef<unsigned> ArrayIndexStarts,
-                       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);
-    }
-
-    /// \brief Retrieve the mapping from captures to the first array index
-    /// variable.
-    unsigned *getArrayIndexStarts() const {
-      return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1);
-    }
-
-    /// \brief Retrieve the complete set of array-index variables.
-    VarDecl **getArrayIndexVars() const {
-      return reinterpret_cast<VarDecl **>(
-               getArrayIndexStarts() + NumCaptures + 1);
-    }
+    Capture *Captures;    
   };
 
   struct DefinitionData &data() {

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=150401&r1=150400&r2=150401&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Feb 13 11:20:40 2012
@@ -1048,6 +1048,9 @@
   /// \brief The source range that covers the lambda introducer ([...]).
   SourceRange IntroducerRange;
 
+  /// \brief The number of captures.
+  unsigned NumCaptures : 16;
+  
   /// \brief The default capture kind, which is a value of type
   /// LambdaCaptureDefault.
   unsigned CaptureDefault : 2;
@@ -1056,6 +1059,8 @@
   /// implicit (and empty) parameter list.
   unsigned ExplicitParams : 1;
 
+  unsigned HasArrayIndexVars : 1;
+  
   /// \brief The location of the closing brace ('}') that completes
   /// the lambda.
   /// 
@@ -1066,6 +1071,10 @@
   /// module file just to determine the source range.
   SourceLocation ClosingBrace;
 
+  // Note: The capture initializers are stored directly after the lambda
+  // expression, along with the index variables used to initialize by-copy
+  // array captures.
+
 public:
   /// \brief Describes the capture of either a variable or 'this'.
   class Capture {
@@ -1153,6 +1162,22 @@
              ArrayRef<unsigned> ArrayIndexStarts,
              SourceLocation ClosingBrace);
 
+  Stmt **getStoredStmts() const {
+    return reinterpret_cast<Stmt **>(const_cast<LambdaExpr *>(this) + 1);
+  }
+  
+  /// \brief Retrieve the mapping from captures to the first array index
+  /// variable.
+  unsigned *getArrayIndexStarts() const {
+    return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1);
+  }
+  
+  /// \brief Retrieve the complete set of array-index variables.
+  VarDecl **getArrayIndexVars() const {
+    return reinterpret_cast<VarDecl **>(
+             getArrayIndexStarts() + NumCaptures + 1);
+  }
+
 public:
   /// \brief Construct a new lambda expression.
   static LambdaExpr *Create(ASTContext &C, 
@@ -1182,6 +1207,9 @@
   /// sequence of lambda captures.
   capture_iterator capture_end() const;
 
+  /// \brief Determine the number of captures in this lambda.
+  unsigned capture_size() const { return NumCaptures; }
+  
   /// \brief Retrieve an iterator pointing to the first explicit
   /// lambda capture.
   capture_iterator explicit_capture_begin() const;
@@ -1204,11 +1232,15 @@
 
   /// \brief Retrieve the first initialization argument for this
   /// lambda expression (which initializes the first capture field).
-  capture_init_iterator capture_init_begin() const;
+  capture_init_iterator capture_init_begin() const {
+    return reinterpret_cast<Expr **>(getStoredStmts());
+  }
 
   /// \brief Retrieve the iterator pointing one past the last
   /// initialization argument for this lambda expression.
-  capture_init_iterator capture_init_end() const;
+  capture_init_iterator capture_init_end() const {
+    return capture_init_begin() + NumCaptures;    
+  }
 
   /// \brief Retrieve the set of index variables used in the capture 
   /// initializer of an array captured by copy.
@@ -1232,7 +1264,9 @@
   CXXMethodDecl *getCallOperator() const;
 
   /// \brief Retrieve the body of the lambda.
-  CompoundStmt *getBody() const;
+  CompoundStmt *getBody() const {
+    return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
+  }
 
   /// \brief Determine whether the lambda is mutable, meaning that any
   /// captures values can be modified.
@@ -1251,7 +1285,9 @@
     return SourceRange(IntroducerRange.getBegin(), ClosingBrace);
   }
 
-  child_range children();
+  child_range children() {
+    return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
+  }
 
   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=150401&r1=150400&r2=150401&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Feb 13 11:20:40 2012
@@ -35,55 +35,6 @@
   return new (Mem) AccessSpecDecl(EmptyShell());
 }
 
-void CXXRecordDecl::LambdaDefinitionData::allocateExtra(
-       ArrayRef<LambdaExpr::Capture> Captures,
-       ArrayRef<Expr *> CaptureInits,
-       ArrayRef<VarDecl *> ArrayIndexVars,
-       ArrayRef<unsigned> ArrayIndexStarts,
-       Stmt *Body) {
-  NumCaptures = Captures.size();
-  NumExplicitCaptures = 0;
-  
-  ASTContext &Context = Definition->getASTContext();
-  unsigned ArrayIndexSize = 0;
-  if (ArrayIndexVars.size() > 0) {
-    HasArrayIndexVars = true;
-    ArrayIndexSize = sizeof(unsigned) * (Captures.size() + 1)
-                   + sizeof(VarDecl *) * ArrayIndexVars.size();
-  }
-  
-  this->Extra = Context.Allocate(sizeof(Capture) * Captures.size() +
-                                 sizeof(Stmt*) * (Captures.size() + 1) +
-                                 ArrayIndexSize);
-  
-  // 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;
-  
-  if (ArrayIndexVars.size() > 0) {
-    assert(ArrayIndexStarts.size() == Captures.size());
-    memcpy(getArrayIndexVars(), ArrayIndexVars.data(),
-           sizeof(VarDecl *) * ArrayIndexVars.size());
-    memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), 
-           sizeof(unsigned) * Captures.size());
-    getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
-  }
-}
-
-
 CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
   : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
     UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false),
@@ -1035,8 +986,7 @@
 
   LambdaDefinitionData &Lambda = getLambdaData();
   RecordDecl::field_iterator Field = field_begin();
-  for (LambdaExpr::Capture *C = Lambda.getCaptures(), 
-                        *CEnd = C + Lambda.NumCaptures;
+  for (LambdaExpr::Capture *C = Lambda.Captures, *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=150401&r1=150400&r2=150401&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Feb 13 11:20:40 2012
@@ -753,13 +753,14 @@
                        ArrayRef<Capture> Captures, 
                        bool ExplicitParams,
                        ArrayRef<Expr *> CaptureInits,
-                       ArrayRef<VarDecl *> ArrayElementVars,
-                       ArrayRef<unsigned> ArrayElementStarts,
+                       ArrayRef<VarDecl *> ArrayIndexVars,
+                       ArrayRef<unsigned> ArrayIndexStarts,
                        SourceLocation ClosingBrace)
   : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
          T->isDependentType(), T->isDependentType(), T->isDependentType(),
          /*ContainsUnexpandedParameterPack=*/false),
     IntroducerRange(IntroducerRange),
+    NumCaptures(Captures.size()),
     CaptureDefault(CaptureDefault),
     ExplicitParams(ExplicitParams),
     ClosingBrace(ClosingBrace)
@@ -767,10 +768,40 @@
   assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
   CXXRecordDecl *Class = getLambdaClass();
   CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
-  Data.allocateExtra(Captures, CaptureInits, ArrayElementVars, 
-                     ArrayElementStarts, getCallOperator()->getBody());
   
   // FIXME: Propagate "has unexpanded parameter pack" bit.
+  
+  // Copy captures.
+  ASTContext &Context = Class->getASTContext();
+  Data.NumCaptures = NumCaptures;
+  Data.NumExplicitCaptures = 0;
+  Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
+  Capture *ToCapture = Data.Captures;
+  for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
+    if (Captures[I].isExplicit())
+      ++Data.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();
+
+  // Copy the array index variables, if any.
+  HasArrayIndexVars = !ArrayIndexVars.empty();
+  if (HasArrayIndexVars) {
+    assert(ArrayIndexStarts.size() == NumCaptures);
+    memcpy(getArrayIndexVars(), ArrayIndexVars.data(),
+           sizeof(VarDecl *) * ArrayIndexVars.size());
+    memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), 
+           sizeof(unsigned) * Captures.size());
+    getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
+  }  
 }
 
 LambdaExpr *LambdaExpr::Create(ASTContext &Context, 
@@ -780,27 +811,30 @@
                                ArrayRef<Capture> Captures, 
                                bool ExplicitParams,
                                ArrayRef<Expr *> CaptureInits,
-                               ArrayRef<VarDecl *> ArrayElementVars,
-                               ArrayRef<unsigned> ArrayElementStarts,
+                               ArrayRef<VarDecl *> ArrayIndexVars,
+                               ArrayRef<unsigned> ArrayIndexStarts,
                                SourceLocation ClosingBrace) {
   // Determine the type of the expression (i.e., the type of the
   // function object we're creating).
   QualType T = Context.getTypeDeclType(Class);
 
-  return new (Context) LambdaExpr(T, IntroducerRange, CaptureDefault, 
-                                  Captures, ExplicitParams, CaptureInits,
-                                  ArrayElementVars, ArrayElementStarts,
-                                  ClosingBrace);
+  unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (Captures.size() + 1);
+  if (!ArrayIndexVars.empty())
+    Size += sizeof(VarDecl *) * ArrayIndexVars.size()
+          + sizeof(unsigned) * (Captures.size() + 1);
+  void *Mem = Context.Allocate(Size);
+  return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, 
+                              Captures, ExplicitParams, CaptureInits,
+                              ArrayIndexVars, ArrayIndexStarts,
+                              ClosingBrace);
 }
 
 LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
-  return getLambdaClass()->getLambdaData().getCaptures();
+  return getLambdaClass()->getLambdaData().Captures;
 }
 
 LambdaExpr::capture_iterator LambdaExpr::capture_end() const {
-  struct CXXRecordDecl::LambdaDefinitionData &Data
-    = getLambdaClass()->getLambdaData();
-  return Data.getCaptures() + Data.NumCaptures;
+  return capture_begin() + NumCaptures;
 }
 
 LambdaExpr::capture_iterator LambdaExpr::explicit_capture_begin() const {
@@ -810,7 +844,7 @@
 LambdaExpr::capture_iterator LambdaExpr::explicit_capture_end() const {
   struct CXXRecordDecl::LambdaDefinitionData &Data
     = getLambdaClass()->getLambdaData();
-  return Data.getCaptures() + Data.NumExplicitCaptures;
+  return Data.Captures + Data.NumExplicitCaptures;
 }
 
 LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const {
@@ -821,26 +855,15 @@
   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);
-}
-
 ArrayRef<VarDecl *> 
 LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const {
   CXXRecordDecl::LambdaDefinitionData &Data = getLambdaClass()->getLambdaData();
-  assert(Data.HasArrayIndexVars && "No array index-var data?");
+  assert(HasArrayIndexVars && "No array index-var data?");
   
   unsigned Index = Iter - capture_init_begin();
   assert(Index < Data.NumCaptures && "Capture index out-of-range");
-  VarDecl **IndexVars = Data.getArrayIndexVars();
-  unsigned *IndexStarts = Data.getArrayIndexStarts();
+  VarDecl **IndexVars = getArrayIndexVars();
+  unsigned *IndexStarts = getArrayIndexStarts();
   return ArrayRef<VarDecl *>(IndexVars + IndexStarts[Index],
                              IndexVars + IndexStarts[Index + 1]);
 }
@@ -860,22 +883,10 @@
   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(),





More information about the cfe-commits mailing list