]> granicus.if.org Git - clang/commitdiff
Keep track of the set of array index variables we use when we
authorDouglas Gregor <dgregor@apple.com>
Mon, 13 Feb 2012 16:35:30 +0000 (16:35 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 13 Feb 2012 16:35:30 +0000 (16:35 +0000)
synthesize a by-copy captured array in a lambda. This information will
be needed by IR generation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150396 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
include/clang/AST/ExprCXX.h
include/clang/Sema/ScopeInfo.h
lib/AST/DeclCXX.cpp
lib/AST/ExprCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaLambda.cpp

index 2b568718105d6ddeb510ba32a395f504bcc5bca5..5487c77a3cb87771c482802c06c247e7230348b9 100644 (file)
@@ -561,7 +561,8 @@ class CXXRecordDecl : public RecordDecl {
     typedef LambdaExpr::Capture Capture;
     
     LambdaDefinitionData(CXXRecordDecl *D) 
-      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), Extra(0) { 
+      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), 
+        HasArrayIndexVars(false), Extra(0) { 
       IsLambda = true;
     }
 
@@ -569,15 +570,22 @@ class CXXRecordDecl : public RecordDecl {
     unsigned NumCaptures : 16;
 
     /// \brief The number of explicit captures in this lambda.
-    unsigned NumExplicitCaptures : 16;
+    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, and the body of the lambda.
+    /// 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.
@@ -588,6 +596,18 @@ class CXXRecordDecl : public RecordDecl {
     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);
+    }
   };
 
   struct DefinitionData &data() {
index 5037347773b47869e2940ed8766d2d633fbb71d0..55ad4861abd1daa221ec629ebb31f662e1b398e3 100644 (file)
@@ -1066,22 +1066,16 @@ class LambdaExpr : public Expr {
   /// 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.
     ///
@@ -1155,6 +1149,8 @@ private:
              ArrayRef<Capture> Captures,
              bool ExplicitParams,
              ArrayRef<Expr *> CaptureInits,
+             ArrayRef<VarDecl *> ArrayIndexVars,
+             ArrayRef<unsigned> ArrayIndexStarts,
              SourceLocation ClosingBrace);
 
 public:
@@ -1166,6 +1162,8 @@ public:
                             ArrayRef<Capture> Captures,
                             bool ExplicitParams,
                             ArrayRef<Expr *> CaptureInits,
+                            ArrayRef<VarDecl *> ArrayIndexVars,
+                            ArrayRef<unsigned> ArrayIndexStarts,
                             SourceLocation ClosingBrace);
 
   /// \brief Determine the default capture kind for this lambda.
@@ -1212,6 +1210,13 @@ public:
   /// initialization argument for this lambda expression.
   capture_init_iterator capture_init_end() const;
 
+  /// \brief Retrieve the set of index variables used in the capture 
+  /// initializer of an array captured by copy.
+  ///
+  /// \param Iter The iterator that points at the capture initializer for 
+  /// which we are extracting the corresponding index variables.
+  ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const;
+  
   /// \brief Retrieve the source range covering the lambda introducer,
   /// which contains the explicit capture list surrounded by square
   /// brackets ([...]).
index 1861e958ae6cce7fa2fd0a82bea6e56c17137768..57a49e6114e394aad0cce69ba464e1673a7e2106 100644 (file)
@@ -301,6 +301,13 @@ public:
   /// \brief Whether any of the capture expressions requires cleanups.
   bool ExprNeedsCleanups;
 
+  /// \brief Variables used to index into by-copy array captures.
+  llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
+
+  /// \brief Offsets into the ArrayIndexVars array at which each capture starts
+  /// its list of array index variables.
+  llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
+  
   LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
                   CXXMethodDecl *CallOperator)
     : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
index 257a507b236debe5c7a6d09f7d80b878007dc135..fcd45088c2e7bea5317549e34508d0c40be1bcb9 100644 (file)
@@ -38,13 +38,23 @@ AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 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));
+                                 sizeof(Stmt*) * (Captures.size() + 1) +
+                                 ArrayIndexSize);
   
   // Copy captures.
   Capture *ToCapture = getCaptures();
@@ -62,6 +72,15 @@ void CXXRecordDecl::LambdaDefinitionData::allocateExtra(
   
   // 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();
+  }
 }
 
 
index 1f8a57a4e353bedeff356107a0104dafcf09ab65..1e766ada239603a72de6d8c9a81593e2ce92d08a 100644 (file)
@@ -753,6 +753,8 @@ LambdaExpr::LambdaExpr(QualType T,
                        ArrayRef<Capture> Captures, 
                        bool ExplicitParams,
                        ArrayRef<Expr *> CaptureInits,
+                       ArrayRef<VarDecl *> ArrayElementVars,
+                       ArrayRef<unsigned> ArrayElementStarts,
                        SourceLocation ClosingBrace)
   : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
          T->isDependentType(), T->isDependentType(), T->isDependentType(),
@@ -765,7 +767,8 @@ LambdaExpr::LambdaExpr(QualType T,
   assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
   CXXRecordDecl *Class = getLambdaClass();
   CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
-  Data.allocateExtra(Captures, CaptureInits, getCallOperator()->getBody());
+  Data.allocateExtra(Captures, CaptureInits, ArrayElementVars, 
+                     ArrayElementStarts, getCallOperator()->getBody());
   
   // FIXME: Propagate "has unexpanded parameter pack" bit.
 }
@@ -777,6 +780,8 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
                                ArrayRef<Capture> Captures, 
                                bool ExplicitParams,
                                ArrayRef<Expr *> CaptureInits,
+                               ArrayRef<VarDecl *> ArrayElementVars,
+                               ArrayRef<unsigned> ArrayElementStarts,
                                SourceLocation ClosingBrace) {
   // Determine the type of the expression (i.e., the type of the
   // function object we're creating).
@@ -784,6 +789,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
 
   return new (Context) LambdaExpr(T, IntroducerRange, CaptureDefault, 
                                   Captures, ExplicitParams, CaptureInits,
+                                  ArrayElementVars, ArrayElementStarts,
                                   ClosingBrace);
 }
 
@@ -826,6 +832,19 @@ LambdaExpr::capture_init_iterator LambdaExpr::capture_init_end() const {
   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?");
+  
+  unsigned Index = Iter - capture_init_begin();
+  assert(Index < Data.NumCaptures && "Capture index out-of-range");
+  VarDecl **IndexVars = Data.getArrayIndexVars();
+  unsigned *IndexStarts = Data.getArrayIndexStarts();
+  return ArrayRef<VarDecl *>(IndexVars + IndexStarts[Index],
+                             IndexVars + IndexStarts[Index + 1]);
+}
+
 CXXRecordDecl *LambdaExpr::getLambdaClass() const {
   return getType()->getAsCXXRecordDecl();
 }
index 9bd1074116ff31a87ecae01d8347f8a7699ad4d1..0d43afcd81cf51aca778184b76a53f7e08ab4dcb 100644 (file)
@@ -9642,6 +9642,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
   bool InitializingArray = false;
   QualType BaseType = FieldType;
   QualType SizeType = S.Context.getSizeType();
+  LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size());
   while (const ConstantArrayType *Array
                         = S.Context.getAsConstantArrayType(BaseType)) {
     InitializingArray = true;
@@ -9660,7 +9661,8 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
                         S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
                         SC_None, SC_None);
     IndexVariables.push_back(IterationVar);
-
+    LSI->ArrayIndexVars.push_back(IterationVar);
+    
     // Create a reference to the iteration variable.
     ExprResult IterationVarRef
       = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
index 44b388364a7afb09f3f63d75a03522ea79f1b2b0..f91b93f957e61a307422dfee226a2fffa603b092 100644 (file)
@@ -306,6 +306,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
   SourceRange IntroducerRange;
   bool ExplicitParams;
   bool LambdaExprNeedsCleanups;
+  llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
+  llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
   {
     LambdaScopeInfo *LSI = getCurLambda();
     CallOperator = LSI->CallOperator;
@@ -313,7 +315,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
     IntroducerRange = LSI->IntroducerRange;
     ExplicitParams = LSI->ExplicitParams;
     LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
-
+    ArrayIndexVars.swap(LSI->ArrayIndexVars);
+    ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
+    
     // Translate captures.
     for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
       LambdaScopeInfo::Capture From = LSI->Captures[I];
@@ -467,6 +471,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
   LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
                                           CaptureDefault, Captures, 
                                           ExplicitParams, CaptureInits, 
+                                          ArrayIndexVars, ArrayIndexStarts,
                                           Body->getLocEnd());
 
   // C++11 [expr.prim.lambda]p2: