]> granicus.if.org Git - clang/commitdiff
Extend CXXRecordDecl with a function that determines the mapping from
authorDouglas Gregor <dgregor@apple.com>
Fri, 10 Feb 2012 07:45:31 +0000 (07:45 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 10 Feb 2012 07:45:31 +0000 (07:45 +0000)
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
include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Sema/SemaLambda.cpp

index 3236977030e82d064e11f2c04088193e99b91c89..82570f594d4a1391cc64c20758bfc6ba86daffd5 100644 (file)
@@ -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<ASTContext> {
   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 {
@@ -358,7 +363,8 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
   friend class ASTDeclReader;
   friend class ASTReader;
   friend class ASTWriter;
-  
+  friend class CXXRecordDecl;
+
   const TargetInfo *Target;
   clang::PrintingPolicy PrintingPolicy;
   
index f33b762644e13899aa8b1d7a8a737fdcf2c10e65..5d333fa41bb8db3aadbde977a42e3d72dc838142 100644 (file)
@@ -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<const VarDecl *, FieldDecl *> &Captures,
+                        FieldDecl *&ThisCapture);
 
   /// getConversions - Retrieve the overload set containing all of the
   /// conversion functions in this class.
index aa24e9b625d656313a4cca1e801a72e233f551ea..b65daa5e5edfcf0441b4125c066867c9ca1c17a9 100644 (file)
@@ -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<const VarDecl *, FieldDecl *> &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<UsingShadowDecl>(Conv))
index 73ef229a6bd4281e9a855e2cdab4e2c96bf181b1..6e9bea781db32d52a78a2b595c3e549ca875abdb 100644 (file)
@@ -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