More lambda work. Tweak the Sema interface slightly.  Start adding the pieces to build the lambda class and its call operator.  Create an actual scope for the lambda body.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147595 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index e53e5cd..fd47dc7 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4778,20 +4778,68 @@
 // Lambdas.
 //===----------------------------------------------------------------------===//
 
-void Sema::ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope) {
-  // FIXME: Add lambda-scope
-  // FIXME: PushDeclContext
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  DeclContext *DC = CurContext;
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isNamespace()))
+    DC = DC->getParent();
 
-  // Enter a new evaluation context to insulate the block from any
-  // cleanups from the enclosing full-expression.
-  PushExpressionEvaluationContext(PotentiallyEvaluated);  
-}
+  // Start constructing the lambda class.
+  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
+                                               Intro.Range.getBegin(),
+                                               /*IdLoc=*/SourceLocation(),
+                                               /*Id=*/0);
+  Class->startDefinition();
+  CurContext->addDecl(Class);
 
-void Sema::ActOnLambdaArguments(Declarator &ParamInfo, Scope *CurScope) {
+  // 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.
   TypeSourceInfo *MethodTyInfo;
   MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
 
-  // FIXME: Build CXXMethodDecl
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context,
+                            Class,
+                            ParamInfo.getSourceRange().getEnd(),
+                            DeclarationNameInfo(MethodName,
+                                                /*NameLoc=*/SourceLocation()),
+                            MethodTyInfo->getType(),
+                            MethodTyInfo,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            ParamInfo.getSourceRange().getEnd());
+  Method->setAccess(AS_public);
+  Class->addDecl(Method);
+  Method->setLexicalDeclContext(DC); // FIXME: Is this really correct?
+
+  // 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);
+  }
+
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+
+  // FIXME: There's a bunch of missing checking etc;
+  // see ActOnBlockArguments
+
+  // Introduce the lambda scope.
+  PushLambdaScope(Class);
+
+  // Enter a new evaluation context to insulate the block from any
+  // cleanups from the enclosing full-expression.
+  PushExpressionEvaluationContext(PotentiallyEvaluated);
+
+  PushDeclContext(CurScope, Method);
 }
 
 void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
@@ -4800,8 +4848,8 @@
   PopExpressionEvaluationContext();
 
   // Leave the context of the lambda.
-  // FIXME: PopDeclContext
-  // FIXME: Pop lambda-scope
+  PopDeclContext();
+  PopFunctionScopeInfo();
 }
 
 ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,