[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