From 4d8d22bfaed6e5d7da6b5556415b18c43b44e36c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 10 Feb 2012 07:45:31 +0000 Subject: [PATCH] Extend CXXRecordDecl with a function that determines the mapping from the variables captured by a lambda to the fields that store the captured values. To be used in IRgen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150235 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 8 +++++++- include/clang/AST/DeclCXX.h | 20 +++++++++++++++++++- lib/AST/DeclCXX.cpp | 29 +++++++++++++++++++++++++++++ lib/Sema/SemaLambda.cpp | 3 ++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 3236977030..82570f594d 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -59,6 +59,7 @@ namespace clang { class CXXRecordDecl; class Decl; class FieldDecl; + class LambdaExpr; class MangleContext; class ObjCIvarDecl; class ObjCIvarRefExpr; @@ -163,6 +164,10 @@ class ASTContext : public llvm::RefCountedBase { llvm::DenseMap ClassScopeSpecializationPattern; + /// \brief Mapping from closure types to the lambda expressions that + /// create instances of them. + llvm::DenseMap Lambdas; + /// \brief Representation of a "canonical" template template parameter that /// is used in canonical template names. class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { @@ -358,7 +363,8 @@ class ASTContext : public llvm::RefCountedBase { friend class ASTDeclReader; friend class ASTReader; friend class ASTWriter; - + friend class CXXRecordDecl; + const TargetInfo *Target; clang::PrintingPolicy PrintingPolicy; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index f33b762644..5d333fa41b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -19,6 +19,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" @@ -37,6 +38,7 @@ class CXXMemberLookupCriteria; class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; class FriendDecl; +class LambdaExpr; /// \brief Represents any kind of function declaration, whether it is a /// concrete function or a function template. @@ -925,7 +927,23 @@ public: /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { return hasDefinition() && data().IsLambda; } - void setLambda(bool Lambda = true) { data().IsLambda = Lambda; } + /// \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. + /// + /// \param Captures Will be populated with the mapping from captured + /// variables to the corresponding fields. + /// + /// \param ThisCapture Will be set to the field declaration for the + /// 'this' capture. + void getCaptureFields(llvm::DenseMap &Captures, + FieldDecl *&ThisCapture); /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index aa24e9b625..b65daa5e5e 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -969,6 +969,35 @@ bool CXXRecordDecl::isCLike() const { return isPOD() && data().HasOnlyCMembers; } +void CXXRecordDecl::setLambda(LambdaExpr *Lambda) { + if (!Lambda) + return; + + data().IsLambda = true; + getASTContext().Lambdas[this] = Lambda; +} + +void CXXRecordDecl::getCaptureFields( + llvm::DenseMap &Captures, + FieldDecl *&ThisCapture) { + Captures.clear(); + ThisCapture = 0; + + LambdaExpr *Lambda = getASTContext().Lambdas[this]; + RecordDecl::field_iterator Field = field_begin(); + for (LambdaExpr::capture_iterator C = Lambda->capture_begin(), + CEnd = Lambda->capture_end(); + C != CEnd; ++C, ++Field) { + if (C->capturesThis()) { + ThisCapture = *Field; + continue; + } + + Captures[C->getCapturedVar()] = *Field; + } +} + + static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T; if (isa(Conv)) diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 73ef229a6b..6e9bea781d 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -32,7 +32,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, /*IdLoc=*/Intro.Range.getBegin(), /*Id=*/0); Class->startDefinition(); - Class->setLambda(true); + Class->makeLambda(); CurContext->addDecl(Class); // Build the call operator; we don't really have all the relevant information @@ -408,6 +408,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, 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 -- 2.40.0