More lambda work.  Fixes a minor bug Richard pointed out, makes lookup for lambda parameters work correctly, recording more information into the AST.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147650 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index caa4c1a..1edeff5 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -180,9 +180,15 @@
   /// \brief The field associated with the captured 'this' pointer.
   FieldDecl *ThisCapture;
 
+  /// \brief - Whether the return type of the lambda is implicit
+  bool HasImplicitReturnType;
+
+  /// ReturnType - The return type of the lambda, or null if unknown.
+  QualType ReturnType;
+
   LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda) 
     : FunctionScopeInfo(Diag), Lambda(Lambda), 
-      NumExplicitCaptures(0), ThisCapture(0) 
+      NumExplicitCaptures(0), ThisCapture(0) , HasImplicitReturnType(false)
   {
     Kind = SK_Lambda;
   }
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 7bf2de4..6d20480 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -164,6 +164,7 @@
   class BlockScopeInfo;
   class DelayedDiagnostic;
   class FunctionScopeInfo;
+  class LambdaScopeInfo;
   class TemplateDeductionInfo;
 }
 
@@ -780,6 +781,9 @@
   /// \brief Retrieve the current block, if any.
   sema::BlockScopeInfo *getCurBlock();
 
+  /// \brief Retrieve the current lambda expression, if any.
+  sema::LambdaScopeInfo *getCurLambda();
+
   /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
   SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
 
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index e54858f..cad0a4a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -792,6 +792,12 @@
                   Attr, DeclEndLoc);
   }
 
+  // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
+  // it.
+  ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+                             Scope::BreakScope | Scope::ContinueScope |
+                             Scope::DeclScope);
+
   Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
 
   // Parse compound-statement.
@@ -801,11 +807,6 @@
     return ExprError();
   }
 
-  // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
-  // it.
-  ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
-                             Scope::BreakScope | Scope::ContinueScope |
-                             Scope::DeclScope);
   StmtResult Stmt(ParseCompoundStatementBody());
   BodyScope.Exit();
 
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 6a77d8c..4ab960d 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -869,6 +869,13 @@
   return dyn_cast<BlockScopeInfo>(FunctionScopes.back());  
 }
 
+LambdaScopeInfo *Sema::getCurLambda() {
+  if (FunctionScopes.empty())
+    return 0;
+  
+  return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());  
+}
+
 // Pin this vtable to this file.
 ExternalSemaSource::~ExternalSemaSource() {}
 
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index fd47dc7..0b1dcbd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4782,7 +4782,7 @@
                                         Declarator &ParamInfo,
                                         Scope *CurScope) {
   DeclContext *DC = CurContext;
-  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isNamespace()))
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
     DC = DC->getParent();
 
   // Start constructing the lambda class.
@@ -4795,8 +4795,26 @@
 
   // 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;
   TypeSourceInfo *MethodTyInfo;
-  MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.TypeQuals |= DeclSpec::TQ_const;
+    MethodTy = Context.getFunctionType(Context.DependentTy,
+                                       /*Args=*/0, /*NumArgs=*/0, EPI);
+    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+  } else {
+    assert(ParamInfo.isFunctionDeclarator() &&
+           "lambda-declarator is a function");
+    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+    if (!FTI.hasMutableQualifier())
+      FTI.TypeQuals |= DeclSpec::TQ_const;
+    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");
+  }
 
   DeclarationName MethodName
     = Context.DeclarationNames.getCXXOperatorName(OO_Call);
@@ -4806,7 +4824,7 @@
                             ParamInfo.getSourceRange().getEnd(),
                             DeclarationNameInfo(MethodName,
                                                 /*NameLoc=*/SourceLocation()),
-                            MethodTyInfo->getType(),
+                            MethodTy,
                             MethodTyInfo,
                             /*isStatic=*/false,
                             SC_None,
@@ -4817,21 +4835,8 @@
   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);
 
@@ -4840,6 +4845,41 @@
   PushExpressionEvaluationContext(PotentiallyEvaluated);
 
   PushDeclContext(CurScope, Method);
+
+  LambdaScopeInfo *LSI = getCurLambda();
+
+  // 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;
+    LSI->HasImplicitReturnType = true;
+  }
+
+  // FIXME: Check return type is complete, !isObjCObjectType
+  
 }
 
 void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index a3b6768..3bdb3b6 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2378,7 +2378,8 @@
     // top-level template type arguments.
     bool FreeFunction;
     if (!D.getCXXScopeSpec().isSet()) {
-      FreeFunction = (D.getContext() != Declarator::MemberContext ||
+      FreeFunction = ((D.getContext() != Declarator::MemberContext &&
+                       D.getContext() != Declarator::LambdaExprContext) ||
                       D.getDeclSpec().isFriendSpecified());
     } else {
       DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());