[cfe-commits] r154029 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/AST/ExprCXX.cpp lib/AST/ItaniumMangle.cpp lib/Sema/SemaLambda.cpp lib/Sema/TreeTransform.h test/CodeGenCXX/mangle-lambdas.cpp

Douglas Gregor dgregor at apple.com
Wed Apr 4 10:40:11 PDT 2012


Author: dgregor
Date: Wed Apr  4 12:40:10 2012
New Revision: 154029

URL: http://llvm.org/viewvc/llvm-project?rev=154029&view=rev
Log:
Move the computation of the lambda mangling information (mangling
number + context) to the point where we initially start defining the
lambda, so that the linkage won't change when that information is made
available. Fixes the assertion in <rdar://problem/11182962>.

Plus, actually mangle the context of lambdas properly.


Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Apr  4 12:40:10 2012
@@ -621,7 +621,7 @@
            "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.
   ///
@@ -1503,6 +1503,13 @@
     return getLambdaData().ContextDecl;    
   }
   
+  /// \brief Set the mangling number and context declaration for a lambda
+  /// class.
+  void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
+    getLambdaData().ManglingNumber = ManglingNumber;
+    getLambdaData().ContextDecl = ContextDecl;
+  }
+
   /// \brief Determine whether this lambda expression was known to be dependent
   /// at the time it was created, even if its context does not appear to be
   /// dependent.

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Apr  4 12:40:10 2012
@@ -1231,9 +1231,7 @@
              ArrayRef<Expr *> CaptureInits,
              ArrayRef<VarDecl *> ArrayIndexVars,
              ArrayRef<unsigned> ArrayIndexStarts,
-             SourceLocation ClosingBrace,
-             unsigned ManglingNumber,
-             Decl *ContextDecl);
+             SourceLocation ClosingBrace);
 
   /// \brief Construct an empty lambda expression.
   LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
@@ -1271,9 +1269,7 @@
                             ArrayRef<Expr *> CaptureInits,
                             ArrayRef<VarDecl *> ArrayIndexVars,
                             ArrayRef<unsigned> ArrayIndexStarts,
-                            SourceLocation ClosingBrace,
-                            unsigned ManglingNumber,
-                            Decl *ContextDecl);
+                            SourceLocation ClosingBrace);
 
   /// \brief Construct a new lambda expression that will be deserialized from
   /// an external source.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr  4 12:40:10 2012
@@ -3700,7 +3700,10 @@
                                        SourceRange IntroducerRange,
                                        TypeSourceInfo *MethodType,
                                        SourceLocation EndLoc,
-                                       llvm::ArrayRef<ParmVarDecl *> Params);
+                                       llvm::ArrayRef<ParmVarDecl *> Params,
+                                       llvm::Optional<unsigned> ManglingNumber 
+                                         = llvm::Optional<unsigned>(),
+                                       Decl *ContextDecl = 0);
   
   /// \brief Introduce the scope for a lambda expression.
   sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
@@ -3733,9 +3736,6 @@
   /// was successfully completed.
   ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
                              Scope *CurScope, 
-                             llvm::Optional<unsigned> ManglingNumber 
-                               = llvm::Optional<unsigned>(),
-                             Decl *ContextDecl = 0,
                              bool IsInstantiation = false);
 
   /// \brief Define the "body" of the conversion from a lambda object to a 

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Apr  4 12:40:10 2012
@@ -796,9 +796,7 @@
                        ArrayRef<Expr *> CaptureInits,
                        ArrayRef<VarDecl *> ArrayIndexVars,
                        ArrayRef<unsigned> ArrayIndexStarts,
-                       SourceLocation ClosingBrace,
-                       unsigned ManglingNumber,
-                       Decl *ContextDecl)
+                       SourceLocation ClosingBrace)
   : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
          T->isDependentType(), T->isDependentType(), T->isDependentType(),
          /*ContainsUnexpandedParameterPack=*/false),
@@ -819,8 +817,6 @@
   ASTContext &Context = Class->getASTContext();
   Data.NumCaptures = NumCaptures;
   Data.NumExplicitCaptures = 0;
-  Data.ManglingNumber = ManglingNumber;
-  Data.ContextDecl = ContextDecl;
   Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
   Capture *ToCapture = Data.Captures;
   for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
@@ -848,9 +844,6 @@
            sizeof(unsigned) * Captures.size());
     getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
   }
-  
-  if (ManglingNumber)
-    Class->ClearLinkageCache();
 }
 
 LambdaExpr *LambdaExpr::Create(ASTContext &Context, 
@@ -863,9 +856,7 @@
                                ArrayRef<Expr *> CaptureInits,
                                ArrayRef<VarDecl *> ArrayIndexVars,
                                ArrayRef<unsigned> ArrayIndexStarts,
-                               SourceLocation ClosingBrace,
-                               unsigned ManglingNumber,
-                               Decl *ContextDecl) {
+                               SourceLocation ClosingBrace) {
   // Determine the type of the expression (i.e., the type of the
   // function object we're creating).
   QualType T = Context.getTypeDeclType(Class);
@@ -878,7 +869,7 @@
   return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, 
                               Captures, ExplicitParams, ExplicitResultType,
                               CaptureInits, ArrayIndexVars, ArrayIndexStarts,
-                              ClosingBrace, ManglingNumber, ContextDecl);
+                              ClosingBrace);
 }
 
 LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Apr  4 12:40:10 2012
@@ -535,6 +535,14 @@
   return 0;
 }
 
+static bool isLambda(const NamedDecl *ND) {
+  const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
+  if (!Record)
+    return false;
+  
+  return Record->isLambda();
+}
+
 void CXXNameMangler::mangleName(const NamedDecl *ND) {
   //  <name> ::= <nested-name>
   //         ::= <unscoped-name>
@@ -545,7 +553,9 @@
 
   // If this is an extern variable declared locally, the relevant DeclContext
   // is that of the containing namespace, or the translation unit.
-  if (isa<FunctionDecl>(DC) && ND->hasLinkage())
+  // FIXME: This is a hack; extern variables declared locally should have
+  // a proper semantic declaration context!
+  if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND))
     while (!DC->isNamespace() && !DC->isTranslationUnit())
       DC = getEffectiveParentContext(DC);
   else if (GetLocalClassDecl(ND)) {

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Apr  4 12:40:10 2012
@@ -36,11 +36,27 @@
   return Class;
 }
 
+/// \brief Determine whether the given context is or is enclosed in an inline
+/// function.
+static bool isInInlineFunction(const DeclContext *DC) {
+  while (!DC->isFileContext()) {
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+      if (FD->isInlined())
+        return true;
+    
+    DC = DC->getLexicalParent();
+  }
+  
+  return false;
+}
+
 CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
-                                           SourceRange IntroducerRange,
-                                           TypeSourceInfo *MethodType,
-                                           SourceLocation EndLoc,
-                 llvm::ArrayRef<ParmVarDecl *> Params) {
+                 SourceRange IntroducerRange,
+                 TypeSourceInfo *MethodType,
+                 SourceLocation EndLoc,
+                 llvm::ArrayRef<ParmVarDecl *> Params,
+                 llvm::Optional<unsigned> ManglingNumber,
+                 Decl *ContextDecl) {
   // C++11 [expr.prim.lambda]p5:
   //   The closure type for a lambda-expression has a public inline function 
   //   call operator (13.5.4) whose parameters and return type are described by
@@ -83,6 +99,63 @@
       (*P)->setOwningFunction(Method);
   }
   
+  // If we don't already have a mangling number for this lambda expression,
+  // allocate one now.
+  if (!ManglingNumber) {
+    ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
+    
+    enum ContextKind {
+      Normal,
+      DefaultArgument,
+      DataMember,
+      StaticDataMember
+    } Kind = Normal;
+    
+    // Default arguments of member function parameters that appear in a class
+    // definition, as well as the initializers of data members, receive special
+    // treatment. Identify them.
+    if (ContextDecl) {
+      if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
+        if (const DeclContext *LexicalDC
+            = Param->getDeclContext()->getLexicalParent())
+          if (LexicalDC->isRecord())
+            Kind = DefaultArgument;
+      } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
+        if (Var->getDeclContext()->isRecord())
+          Kind = StaticDataMember;
+      } else if (isa<FieldDecl>(ContextDecl)) {
+        Kind = DataMember;
+      }
+    }        
+    
+    switch (Kind) {
+      case Normal:
+        if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
+          ManglingNumber = Context.getLambdaManglingNumber(Method);
+        else
+          ManglingNumber = 0;
+        
+        // There is no special context for this lambda.
+        ContextDecl = 0;        
+        break;
+        
+      case StaticDataMember:
+        if (!CurContext->isDependentContext()) {
+          ManglingNumber = 0;
+          ContextDecl = 0;
+          break;
+        }
+        // Fall through to assign a mangling number.
+        
+      case DataMember:
+      case DefaultArgument:
+        ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
+                           .getManglingNumber(Method);
+        break;
+    }
+  }
+
+  Class->setLambdaMangling(*ManglingNumber, ContextDecl);
   return Method;
 }
 
@@ -491,25 +564,9 @@
   Conversion->setImplicit(true);
   Class->addDecl(Conversion);
 }
-
-/// \brief Determine whether the given context is or is enclosed in an inline
-/// function.
-static bool isInInlineFunction(const DeclContext *DC) {
-  while (!DC->isFileContext()) {
-    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
-      if (FD->isInlined())
-        return true;
-    
-    DC = DC->getLexicalParent();
-  }
-  
-  return false;
-}
          
 ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, 
                                  Scope *CurScope, 
-                                 llvm::Optional<unsigned> ManglingNumber,
-                                 Decl *ContextDecl,
                                  bool IsInstantiation) {
   // Collect information from the lambda scope.
   llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
@@ -655,69 +712,12 @@
 
   if (LambdaExprNeedsCleanups)
     ExprNeedsCleanups = true;
-
-  // If we don't already have a mangling number for this lambda expression,
-  // allocate one now.
-  if (!ManglingNumber) {
-    ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
-    
-    enum ContextKind {
-      Normal,
-      DefaultArgument,
-      DataMember,
-      StaticDataMember
-    } Kind = Normal;
-
-    // Default arguments of member function parameters that appear in a class
-    // definition, as well as the initializers of data members, receive special
-    // treatment. Identify them.
-    if (ContextDecl) {
-      if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
-        if (const DeclContext *LexicalDC
-              = Param->getDeclContext()->getLexicalParent())
-          if (LexicalDC->isRecord())
-            Kind = DefaultArgument;
-      } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
-        if (Var->getDeclContext()->isRecord())
-          Kind = StaticDataMember;
-      } else if (isa<FieldDecl>(ContextDecl)) {
-        Kind = DataMember;
-      }
-    }        
-    
-    switch (Kind) {
-    case Normal:
-      if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
-        ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
-      else
-        ManglingNumber = 0;
-        
-      // There is no special context for this lambda.
-      ContextDecl = 0;        
-      break;
-      
-    case StaticDataMember:
-      if (!CurContext->isDependentContext()) {
-        ManglingNumber = 0;
-        ContextDecl = 0;
-        break;
-      }
-      // Fall through to assign a mangling number.
-        
-    case DataMember:
-    case DefaultArgument:
-      ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
-                         .getManglingNumber(CallOperator);
-      break;
-    }
-  }
   
   LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
                                           CaptureDefault, Captures, 
                                           ExplicitParams, ExplicitResultType,
                                           CaptureInits, ArrayIndexVars, 
-                                          ArrayIndexStarts, Body->getLocEnd(),
-                                          *ManglingNumber, ContextDecl);
+                                          ArrayIndexStarts, Body->getLocEnd());
 
   // C++11 [expr.prim.lambda]p2:
   //   A lambda-expression shall not appear in an unevaluated operand

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Apr  4 12:40:10 2012
@@ -7815,7 +7815,8 @@
 TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   // Create the local class that will describe the lambda.
   CXXRecordDecl *Class
-    = getSema().createLambdaClosureType(E->getIntroducerRange());
+    = getSema().createLambdaClosureType(E->getIntroducerRange(),
+                                        /*KnownDependent=*/false);
   getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
   
   // Transform the type of the lambda parameters and start the definition of
@@ -7836,11 +7837,15 @@
     Invalid = true;  
 
   // Build the call operator.
+  // Note: Once a lambda mangling number and context declaration have been
+  // assigned, they never change.
+  unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
+  Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();  
   CXXMethodDecl *CallOperator
     = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
                                       MethodTy, 
                                       E->getCallOperator()->getLocEnd(),
-                                      Params);
+                                      Params, ManglingNumber, ContextDecl);
   getDerived().transformAttrs(E->getCallOperator(), CallOperator);
   
   // FIXME: Instantiation-specific.
@@ -7953,14 +7958,8 @@
     return ExprError();    
   }
 
-  // Note: Once a lambda mangling number and context declaration have been
-  // assigned, they never change.
-  unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
-  Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();
   return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), 
-                                   /*CurScope=*/0, ManglingNumber,
-                                   ContextDecl,
-                                   /*IsInstantiation=*/true);
+                                   /*CurScope=*/0, /*IsInstantiation=*/true);
 }
 
 template<typename Derived>

Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=154029&r1=154028&r2=154029&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Wed Apr  4 12:40:10 2012
@@ -150,6 +150,8 @@
   func_template<int>();
 }
 
+// CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_
+
 struct Members {
   int x = [] { return 1; }() + [] { return 2; }();
   int y = [] { return 3; }();
@@ -165,6 +167,20 @@
   // CHECK: ret void
 }
 
+template<typename P> void f(P) { }
+
+struct TestNestedInstantiation {
+   void operator()() const {
+     []() -> void {
+       return f([]{});
+     }();
+   }
+};
+
+void test_NestedInstantiation() {
+  TestNestedInstantiation()();
+}
+
 // Check the linkage of the lambdas used in test_Members.
 // CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE_clEv
 // CHECK: ret i32 1





More information about the cfe-commits mailing list