Introduce support for template instantiation of lambda
expressions. This is mostly a simple refact, splitting the main "start
a lambda expression" function into smaller chunks that are driven
either from the parser (Sema::ActOnLambdaExpr) or during AST
transformation (TreeTransform::TransformLambdaExpr). A few minor
interesting points:

  - Added new entry points for TreeTransform, so that we can
  explicitly establish the link between the lambda closure type in the
  template and the lambda closure type in the instantiation.
  - Added a bit into LambdaExpr specifying whether it had an explicit
  result type or not. We should have had this anyway.

This code is 'lightly' tested.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150417 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0d43afc..a67bcf4 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9283,8 +9283,6 @@
       return BaseTransform::TransformUnaryOperator(E);
     }
 
-    /// \brief Transform the capture expressions in the lambda
-    /// expression.
     ExprResult TransformLambdaExpr(LambdaExpr *E) {
       // Lambdas never need to be transformed.
       return E;
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index f91b93f..f97b523 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -20,23 +20,115 @@
 using namespace clang;
 using namespace sema;
 
-void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                        Declarator &ParamInfo,
-                                        Scope *CurScope) {
+CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange) {
   DeclContext *DC = CurContext;
   while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
     DC = DC->getParent();
-
+  
   // Start constructing the lambda class.
   CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, 
-                                                     Intro.Range.getBegin());
+                                                     IntroducerRange.getBegin());
   CurContext->addDecl(Class);
+  
+  return Class;
+}
 
-  // Build the call operator; we don't really have all the relevant information
-  // at this point, but we need something to attach child declarations to.
-  QualType MethodTy;
+CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
+                                           SourceRange IntroducerRange,
+                                           TypeSourceInfo *MethodType,
+                                           SourceLocation EndLoc) {
+  // 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
+  //   the lambda-expression's parameter-declaration-clause and 
+  //   trailing-return-type respectively.
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclarationNameLoc MethodNameLoc;
+  MethodNameLoc.CXXOperatorName.BeginOpNameLoc
+    = IntroducerRange.getBegin().getRawEncoding();
+  MethodNameLoc.CXXOperatorName.EndOpNameLoc
+    = IntroducerRange.getEnd().getRawEncoding();
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context, Class, EndLoc,
+                            DeclarationNameInfo(MethodName, 
+                                                IntroducerRange.getBegin(),
+                                                MethodNameLoc),
+                            MethodType->getType(), MethodType,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            EndLoc);
+  Method->setAccess(AS_public);
+  
+  // Temporarily set the lexical declaration context to the current
+  // context, so that the Scope stack matches the lexical nesting.
+  Method->setLexicalDeclContext(Class->getDeclContext());  
+  
+  return Method;
+}
+
+LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
+                                        SourceRange IntroducerRange,
+                                        LambdaCaptureDefault CaptureDefault,
+                                        bool ExplicitParams,
+                                        bool ExplicitResultType,
+                                        bool Mutable) {
+  PushLambdaScope(CallOperator->getParent(), CallOperator);
+  LambdaScopeInfo *LSI = getCurLambda();
+  if (CaptureDefault == LCD_ByCopy)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
+  else if (CaptureDefault == LCD_ByRef)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
+  LSI->IntroducerRange = IntroducerRange;
+  LSI->ExplicitParams = ExplicitParams;
+  LSI->Mutable = Mutable;
+
+  if (ExplicitResultType) {
+    LSI->ReturnType = CallOperator->getResultType();
+  } else {
+    LSI->HasImplicitReturnType = true;
+  }
+
+  return LSI;
+}
+
+void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
+  LSI->finishedExplicitCaptures();
+}
+
+void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope,
+                               llvm::ArrayRef<ParmVarDecl *> Params) {
+  CallOperator->setParams(Params);
+  CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), 
+                           const_cast<ParmVarDecl **>(Params.end()),
+                           /*CheckParameterNames=*/false);
+  
+  // Introduce our parameters into the function scope
+  for (unsigned p = 0, NumParams = CallOperator->getNumParams(); 
+       p < NumParams; ++p) {
+    ParmVarDecl *Param = CallOperator->getParamDecl(p);
+    Param->setOwningFunction(CallOperator);
+    
+    // If this has an identifier, add it to the scope stack.
+    if (CurScope && Param->getIdentifier()) {
+      CheckShadow(CurScope, Param);
+      
+      PushOnScopeChains(Param, CurScope);
+    }
+  }
+}
+
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  CXXRecordDecl *Class = createLambdaClosureType(Intro.Range);
+  
+  // Determine the signature of the call operator.
   TypeSourceInfo *MethodTyInfo;
   bool ExplicitParams = true;
+  bool ExplicitResultType = true;
   SourceLocation EndLoc;
   if (ParamInfo.getNumTypeObjects() == 0) {
     // C++11 [expr.prim.lambda]p4:
@@ -45,10 +137,11 @@
     FunctionProtoType::ExtProtoInfo EPI;
     EPI.HasTrailingReturn = true;
     EPI.TypeQuals |= DeclSpec::TQ_const;
-    MethodTy = Context.getFunctionType(Context.DependentTy,
-                                       /*Args=*/0, /*NumArgs=*/0, EPI);
+    QualType MethodTy = Context.getFunctionType(Context.DependentTy,
+                                                /*Args=*/0, /*NumArgs=*/0, EPI);
     MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
     ExplicitParams = false;
+    ExplicitResultType = false;
     EndLoc = Intro.Range.getEnd();
   } else {
     assert(ParamInfo.isFunctionDeclarator() &&
@@ -70,40 +163,16 @@
     MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
     // FIXME: Can these asserts actually fail?
     assert(MethodTyInfo && "no type from lambda-declarator");
-    MethodTy = MethodTyInfo->getType();
-    assert(!MethodTy.isNull() && "no type from lambda declarator");
     EndLoc = ParamInfo.getSourceRange().getEnd();
+    
+    ExplicitResultType
+      = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() 
+                                                        != Context.DependentTy;
   }
   
-  // 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
-  //   the lambda-expression's parameter-declaration-clause and 
-  //   trailing-return-type respectively.
-  DeclarationName MethodName
-    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
-  DeclarationNameLoc MethodNameLoc;
-  MethodNameLoc.CXXOperatorName.BeginOpNameLoc
-    = Intro.Range.getBegin().getRawEncoding();
-  MethodNameLoc.CXXOperatorName.EndOpNameLoc
-    = Intro.Range.getEnd().getRawEncoding();
-  CXXMethodDecl *Method
-    = CXXMethodDecl::Create(Context, Class, EndLoc,
-                            DeclarationNameInfo(MethodName, 
-                                                Intro.Range.getBegin(),
-                                                MethodNameLoc),
-                            MethodTy, MethodTyInfo,
-                            /*isStatic=*/false,
-                            SC_None,
-                            /*isInline=*/true,
-                            /*isConstExpr=*/false,
-                            EndLoc);
-  Method->setAccess(AS_public);
-
-  // Temporarily set the lexical declaration context to the current
-  // context, so that the Scope stack matches the lexical nesting.
-  Method->setLexicalDeclContext(DC);
-
+  CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, 
+                                                MethodTyInfo, EndLoc);
+  
   // Attributes on the lambda apply to the method.  
   ProcessDeclAttributes(CurScope, Method, ParamInfo);
   
@@ -111,15 +180,10 @@
   PushDeclContext(CurScope, Method);
     
   // Introduce the lambda scope.
-  PushLambdaScope(Class, Method);
-  LambdaScopeInfo *LSI = getCurLambda();
-  if (Intro.Default == LCD_ByCopy)
-    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
-  else if (Intro.Default == LCD_ByRef)
-    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
-  LSI->IntroducerRange = Intro.Range;
-  LSI->ExplicitParams = ExplicitParams;
-  LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0;
+  LambdaScopeInfo *LSI
+    = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
+                       ExplicitResultType,
+                       (Method->getTypeQualifiers() & Qualifiers::Const) == 0);
  
   // Handle explicit captures.
   SourceLocation PrevCaptureLoc
@@ -231,53 +295,31 @@
                                                  TryCapture_ExplicitByVal;
     TryCaptureVar(Var, C->Loc, Kind);
   }
-  LSI->finishedExplicitCaptures();
+  finishLambdaExplicitCaptures(LSI);
 
   // Set the parameters on the decl, if specified.
   if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
-    FunctionProtoTypeLoc Proto =
-    cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
-    Method->setParams(Proto.getParams());
-    CheckParmsForFunctionDef(Method->param_begin(),
-                             Method->param_end(),
-                             /*CheckParameterNames=*/false);
-    
-    // Introduce our parameters into the function scope
-    for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) {
-      ParmVarDecl *Param = Method->getParamDecl(p);
-      Param->setOwningFunction(Method);
-      
-      // If this has an identifier, add it to the scope stack.
-      if (Param->getIdentifier()) {
-        CheckShadow(CurScope, Param);
-        
-        PushOnScopeChains(Param, CurScope);
-      }
-    }
-  }
-
-  const FunctionType *Fn = MethodTy->getAs<FunctionType>();
-  QualType RetTy = Fn->getResultType();
-  if (RetTy != Context.DependentTy) {
-    LSI->ReturnType = RetTy;
-  } else {
-    LSI->HasImplicitReturnType = true;
+    FunctionProtoTypeLoc Proto
+      = cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
+    addLambdaParameters(Method, CurScope, Proto.getParams());
   }
 
   // FIXME: Check return type is complete, !isObjCObjectType
   
-  // Enter a new evaluation context to insulate the block from any
+  // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.
   PushExpressionEvaluationContext(PotentiallyEvaluated);  
 }
 
-void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
+void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
+                            bool IsInstantiation) {
   // Leave the expression-evaluation context.
   DiscardCleanupsInEvaluationContext();
   PopExpressionEvaluationContext();
 
   // Leave the context of the lambda.
-  PopDeclContext();
+  if (!IsInstantiation)
+    PopDeclContext();
 
   // Finalize the lambda.
   LambdaScopeInfo *LSI = getCurLambda();
@@ -291,8 +333,8 @@
   PopFunctionScopeInfo();
 }
 
-ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
-                                 Stmt *Body, Scope *CurScope) {
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, 
+                                 Scope *CurScope, bool IsInstantiation) {
   // Leave the expression-evaluation context.
   DiscardCleanupsInEvaluationContext();
   PopExpressionEvaluationContext();
@@ -305,6 +347,7 @@
   CXXMethodDecl *CallOperator;
   SourceRange IntroducerRange;
   bool ExplicitParams;
+  bool ExplicitResultType;
   bool LambdaExprNeedsCleanups;
   llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
   llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
@@ -314,6 +357,7 @@
     Class = LSI->Lambda;
     IntroducerRange = LSI->IntroducerRange;
     ExplicitParams = LSI->ExplicitParams;
+    ExplicitResultType = !LSI->HasImplicitReturnType;
     LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
     ArrayIndexVars.swap(LSI->ArrayIndexVars);
     ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
@@ -409,7 +453,7 @@
     // C++ [expr.prim.lambda]p7:
     //   The lambda-expression's compound-statement yields the
     //   function-body (8.4) of the function call operator [...].
-    ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false);
+    ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
     CallOperator->setLexicalDeclContext(Class);
     Class->addDecl(CallOperator);
 
@@ -470,9 +514,9 @@
 
   LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
                                           CaptureDefault, Captures, 
-                                          ExplicitParams, CaptureInits, 
-                                          ArrayIndexVars, ArrayIndexStarts,
-                                          Body->getLocEnd());
+                                          ExplicitParams, ExplicitResultType,
+                                          CaptureInits, ArrayIndexVars, 
+                                          ArrayIndexStarts, Body->getLocEnd());
 
   // C++11 [expr.prim.lambda]p2:
   //   A lambda-expression shall not appear in an unevaluated operand
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index af2c6ef..17bdd69 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -6842,6 +6842,11 @@
       this->Loc = Loc;
       this->Entity = Entity;
     }
+      
+    ExprResult TransformLambdaExpr(LambdaExpr *E) {
+      // Lambdas never need to be transformed.
+      return E;
+    }
   };
 }
 
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 1d84ce3..fa66a5a 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3379,6 +3379,11 @@
         return Result;
       }
     }
+
+    ExprResult TransformLambdaExpr(LambdaExpr *E) {
+      // Lambdas never need to be transformed.
+      return E;
+    }
   };
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index bd5a1ed..073d644 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -732,6 +732,14 @@
     /// this declaration.
     Decl *TransformDecl(SourceLocation Loc, Decl *D);
 
+    void transformAttrs(Decl *Old, Decl *New) { 
+      SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+    }
+
+    void transformedLocalDecl(Decl *Old, Decl *New) {
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
+    }
+    
     /// \brief Transform the definition of the given declaration by
     /// instantiating it.
     Decl *TransformDefinition(SourceLocation Loc, Decl *D);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 8744f41..ba6ec82 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -112,6 +112,11 @@
 protected:
   Sema &SemaRef;
   
+  /// \brief The set of local declarations that have been transformed, for
+  /// cases where we are forced to build new declarations within the transformer
+  /// rather than in the subclass (e.g., lambda closure types).
+  llvm::DenseMap<Decl *, Decl *> TransformedLocalDecls;
+  
 public:
   /// \brief Initializes a new tree transformer.
   TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
@@ -351,10 +356,36 @@
   /// \brief Transform the given declaration, which is referenced from a type
   /// or expression.
   ///
-  /// By default, acts as the identity function on declarations. Subclasses
+  /// By default, acts as the identity function on declarations, unless the
+  /// transformer has had to transform the declaration itself. Subclasses
   /// may override this function to provide alternate behavior.
-  Decl *TransformDecl(SourceLocation Loc, Decl *D) { return D; }
+  Decl *TransformDecl(SourceLocation Loc, Decl *D) { 
+    llvm::DenseMap<Decl *, Decl *>::iterator Known
+      = TransformedLocalDecls.find(D);
+    if (Known != TransformedLocalDecls.end())
+      return Known->second;
+    
+    return D; 
+  }
 
+  /// \brief Transform the attributes associated with the given declaration and 
+  /// place them on the new declaration.
+  ///
+  /// By default, this operation does nothing. Subclasses may override this
+  /// behavior to transform attributes.
+  void transformAttrs(Decl *Old, Decl *New) { }
+  
+  /// \brief Note that a local declaration has been transformed by this
+  /// transformer.
+  ///
+  /// Local declarations are typically transformed via a call to 
+  /// TransformDefinition. However, in some cases (e.g., lambda expressions),
+  /// the transformer itself has to transform the declarations. This routine
+  /// can be overridden by a subclass that keeps track of such mappings.
+  void transformedLocalDecl(Decl *Old, Decl *New) {
+    TransformedLocalDecls[Old] = New;
+  }
+  
   /// \brief Transform the definition of the given declaration.
   ///
   /// By default, invokes TransformDecl() to transform the declaration.
@@ -7622,8 +7653,109 @@
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
-  assert(false && "Lambda expressions cannot be instantiated (yet)");
-  return ExprError();
+  // Create the local class that will describe the lambda.
+  CXXRecordDecl *Class
+    = getSema().createLambdaClosureType(E->getIntroducerRange());
+  getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
+  
+  // Transform the type of the lambda parameters and start the definition of
+  // the lambda itself.
+  TypeSourceInfo *MethodTy
+    = TransformType(E->getCallOperator()->getTypeSourceInfo());  
+  if (!MethodTy)
+    return ExprError();
+
+  // Build the call operator.
+  CXXMethodDecl *CallOperator
+    = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
+                                      MethodTy, 
+                                      E->getCallOperator()->getLocEnd());
+  getDerived().transformAttrs(E->getCallOperator(), CallOperator);
+  
+  // Enter the scope of the lambda.
+  sema::LambdaScopeInfo *LSI
+    = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
+                                 E->getCaptureDefault(),
+                                 E->hasExplicitParameters(),
+                                 E->hasExplicitResultType(),
+                                 E->isMutable());
+  
+  // Transform captures.
+  bool Invalid = false;
+  bool FinishedExplicitCaptures = false;
+  for (LambdaExpr::capture_iterator C = E->capture_begin(), 
+                                 CEnd = E->capture_end();
+       C != CEnd; ++C) {
+    // When we hit the first implicit capture, tell Sema that we've finished
+    // the list of explicit captures.
+    if (!FinishedExplicitCaptures && C->isImplicit()) {
+      getSema().finishLambdaExplicitCaptures(LSI);
+      FinishedExplicitCaptures = true;
+    }
+    
+    // Capturing 'this' is trivial.
+    if (C->capturesThis()) {
+      getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit());
+      continue;
+    }
+    
+    // Transform the captured variable.
+    VarDecl *CapturedVar
+      = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), 
+                                                         C->getCapturedVar()));
+    if (!CapturedVar) {
+      Invalid = true;
+      continue;
+    }
+    
+    // Capture the transformed variable.
+    getSema().TryCaptureVar(CapturedVar, C->getLocation(),
+                            C->isImplicit()? Sema::TryCapture_Implicit
+                                           : C->getCaptureKind() == LCK_ByCopy
+                                             ? Sema::TryCapture_ExplicitByVal
+                                             : Sema::TryCapture_ExplicitByRef);
+  }
+  if (!FinishedExplicitCaptures)
+    getSema().finishLambdaExplicitCaptures(LSI);
+
+  // Transform lambda parameters.
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  llvm::SmallVector<ParmVarDecl *, 4> Params;
+  if (!getDerived().TransformFunctionTypeParams(E->getLocStart(),
+         E->getCallOperator()->param_begin(),
+         E->getCallOperator()->param_size(),
+         0, ParamTypes, &Params))
+    getSema().addLambdaParameters(CallOperator, /*CurScope=*/0, Params);
+  else
+    Invalid = true;
+  
+
+  // Enter a new evaluation context to insulate the lambda from any
+  // cleanups from the enclosing full-expression.
+  getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);  
+
+  if (Invalid) {
+    getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0, 
+                               /*IsInstantiation=*/true);
+    return ExprError();
+  }
+
+  // Instantiate the body of the lambda expression.
+  StmtResult Body;
+  {
+    Sema::ContextRAII SavedContext(getSema(), CallOperator);
+    
+    Body = getDerived().TransformStmt(E->getBody());
+    if (Body.isInvalid()) {
+      getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0, 
+                                 /*IsInstantiation=*/true);
+      return ExprError();    
+    }
+  } 
+  
+  return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), 
+                                   /*CurScope=*/0, 
+                                   /*IsInstantiation=*/true);
 }
 
 template<typename Derived>