From 7ae282fde0a12635893931ebf31b35b0d5d5cab3 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 13 Feb 2012 17:20:40 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150401 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 37 +-------------- include/clang/AST/ExprCXX.h | 44 ++++++++++++++++-- lib/AST/DeclCXX.cpp | 52 +-------------------- lib/AST/ExprCXX.cpp | 93 +++++++++++++++++++++---------------- 4 files changed, 95 insertions(+), 131 deletions(-) diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 5487c77a3c..4ea9974299 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -561,8 +561,7 @@ class CXXRecordDecl : public RecordDecl { 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 @@ class CXXRecordDecl : public RecordDecl { /// \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 Captures, - ArrayRef CaptureInits, - ArrayRef ArrayIndexVars, - ArrayRef ArrayIndexStarts, - Stmt *Body); - - /// \brief Retrieve the set of captures. - Capture *getCaptures() const { return reinterpret_cast(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(getCaptures() + NumCaptures); - } - - /// \brief Retrieve the mapping from captures to the first array index - /// variable. - unsigned *getArrayIndexStarts() const { - return reinterpret_cast(getStoredStmts() + NumCaptures + 1); - } - - /// \brief Retrieve the complete set of array-index variables. - VarDecl **getArrayIndexVars() const { - return reinterpret_cast( - getArrayIndexStarts() + NumCaptures + 1); - } + Capture *Captures; }; struct DefinitionData &data() { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 55ad4861ab..7f68b2667f 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1048,6 +1048,9 @@ class LambdaExpr : public Expr { /// \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 @@ class LambdaExpr : public Expr { /// 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 @@ class LambdaExpr : public Expr { /// 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 @@ private: ArrayRef ArrayIndexStarts, SourceLocation ClosingBrace); + Stmt **getStoredStmts() const { + return reinterpret_cast(const_cast(this) + 1); + } + + /// \brief Retrieve the mapping from captures to the first array index + /// variable. + unsigned *getArrayIndexStarts() const { + return reinterpret_cast(getStoredStmts() + NumCaptures + 1); + } + + /// \brief Retrieve the complete set of array-index variables. + VarDecl **getArrayIndexVars() const { + return reinterpret_cast( + getArrayIndexStarts() + NumCaptures + 1); + } + public: /// \brief Construct a new lambda expression. static LambdaExpr *Create(ASTContext &C, @@ -1182,6 +1207,9 @@ public: /// 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 @@ public: /// \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(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 @@ public: CXXMethodDecl *getCallOperator() const; /// \brief Retrieve the body of the lambda. - CompoundStmt *getBody() const; + CompoundStmt *getBody() const { + return reinterpret_cast(getStoredStmts()[NumCaptures]); + } /// \brief Determine whether the lambda is mutable, meaning that any /// captures values can be modified. @@ -1251,7 +1285,9 @@ public: return SourceRange(IntroducerRange.getBegin(), ClosingBrace); } - child_range children(); + child_range children() { + return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); + } friend class ASTStmtReader; friend class ASTStmtWriter; diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index fcd45088c2..5b9ab4ff5c 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -35,55 +35,6 @@ AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (Mem) AccessSpecDecl(EmptyShell()); } -void CXXRecordDecl::LambdaDefinitionData::allocateExtra( - ArrayRef Captures, - ArrayRef CaptureInits, - ArrayRef ArrayIndexVars, - ArrayRef 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 @@ void CXXRecordDecl::getCaptureFields( 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; diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 1e766ada23..4962bf4b92 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -753,13 +753,14 @@ LambdaExpr::LambdaExpr(QualType T, ArrayRef Captures, bool ExplicitParams, ArrayRef CaptureInits, - ArrayRef ArrayElementVars, - ArrayRef ArrayElementStarts, + ArrayRef ArrayIndexVars, + ArrayRef 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 @@ 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, 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 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context, ArrayRef Captures, bool ExplicitParams, ArrayRef CaptureInits, - ArrayRef ArrayElementVars, - ArrayRef ArrayElementStarts, + ArrayRef ArrayIndexVars, + ArrayRef 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_begin() const { 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 @@ LambdaExpr::capture_iterator LambdaExpr::implicit_capture_end() const { return capture_end(); } -LambdaExpr::capture_init_iterator LambdaExpr::capture_init_begin() const { - return reinterpret_cast( - getLambdaClass()->getLambdaData().getStoredStmts()); -} - -LambdaExpr::capture_init_iterator LambdaExpr::capture_init_end() const { - struct CXXRecordDecl::LambdaDefinitionData &Data - = getLambdaClass()->getLambdaData(); - return reinterpret_cast(Data.getStoredStmts() + Data.NumCaptures); -} - ArrayRef 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(IndexVars + IndexStarts[Index], IndexVars + IndexStarts[Index + 1]); } @@ -860,22 +883,10 @@ CXXMethodDecl *LambdaExpr::getCallOperator() const { return Result; } -/// \brief Retrieve the body of the lambda. -CompoundStmt *LambdaExpr::getBody() const { - return cast(*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 objects) : Expr(ExprWithCleanupsClass, subexpr->getType(), -- 2.40.0