diff options
-rw-r--r-- | include/clang/AST/DeclCXX.h | 26 | ||||
-rw-r--r-- | include/clang/AST/ExprCXX.h | 21 | ||||
-rw-r--r-- | include/clang/Sema/ScopeInfo.h | 7 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 21 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 7 |
7 files changed, 92 insertions, 15 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 2b56871810..5487c77a3c 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -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() { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 5037347773..55ad4861ab 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -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 ([...]). diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index 1861e958ae..57a49e6114 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -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), diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 257a507b23..fcd45088c2 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -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(); + } } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 1f8a57a4e3..1e766ada23 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -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(); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9bd1074116..0d43afcd81 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 44b388364a..f91b93f957 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -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: |