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.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154029 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 2a09da0..6ef8d88 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -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
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index c759e7a..f16b667 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -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>