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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150393 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index f9d95b1..257a507 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -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;
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a38488b..29ff69d 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -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(),
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 2bd69ed..44b3883 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -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