More lambda work. Fixes a minor bug Richard pointed out, makes lookup for lambda...
authorEli Friedman <eli.friedman@gmail.com>
Fri, 6 Jan 2012 03:05:34 +0000 (03:05 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 6 Jan 2012 03:05:34 +0000 (03:05 +0000)
llvm-svn: 147650

clang/include/clang/Sema/ScopeInfo.h
clang/include/clang/Sema/Sema.h
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaType.cpp

index caa4c1a..1edeff5 100644 (file)
@@ -180,9 +180,15 @@ public:
   /// \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;
   }
index 7bf2de4..6d20480 100644 (file)
@@ -164,6 +164,7 @@ namespace sema {
   class BlockScopeInfo;
   class DelayedDiagnostic;
   class FunctionScopeInfo;
+  class LambdaScopeInfo;
   class TemplateDeductionInfo;
 }
 
@@ -780,6 +781,9 @@ public:
   /// \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; }
 
index e54858f..cad0a4a 100644 (file)
@@ -792,6 +792,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
                   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 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
     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();
 
index 6a77d8c..4ab960d 100644 (file)
@@ -869,6 +869,13 @@ BlockScopeInfo *Sema::getCurBlock() {
   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() {}
 
index fd47dc7..0b1dcbd 100644 (file)
@@ -4782,7 +4782,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                                         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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
 
   // 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                             ParamInfo.getSourceRange().getEnd(),
                             DeclarationNameInfo(MethodName,
                                                 /*NameLoc=*/SourceLocation()),
-                            MethodTyInfo->getType(),
+                            MethodTy,
                             MethodTyInfo,
                             /*isStatic=*/false,
                             SC_None,
@@ -4817,6 +4835,19 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
   Class->addDecl(Method);
   Method->setLexicalDeclContext(DC); // FIXME: Is this really correct?
 
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+
+  // 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);
+
+  LambdaScopeInfo *LSI = getCurLambda();
+
   // Set the parameters on the decl, if specified.
   if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
     FunctionProtoTypeLoc Proto =
@@ -4825,21 +4856,30 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
     CheckParmsForFunctionDef(Method->param_begin(),
                              Method->param_end(),
                              /*CheckParameterNames=*/false);
-  }
 
-  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+    // 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);
 
-  // FIXME: There's a bunch of missing checking etc;
-  // see ActOnBlockArguments
+      // If this has an identifier, add it to the scope stack.
+      if (Param->getIdentifier()) {
+        CheckShadow(CurScope, Param);
 
-  // Introduce the lambda scope.
-  PushLambdaScope(Class);
+        PushOnScopeChains(Param, CurScope);
+      }
+    }
+  }
 
-  // Enter a new evaluation context to insulate the block from any
-  // cleanups from the enclosing full-expression.
-  PushExpressionEvaluationContext(PotentiallyEvaluated);
+  const FunctionType *Fn = MethodTy->getAs<FunctionType>();
+  QualType RetTy = Fn->getResultType();
+  if (RetTy != Context.DependentTy) {
+    LSI->ReturnType = RetTy;
+    LSI->HasImplicitReturnType = true;
+  }
 
-  PushDeclContext(CurScope, Method);
+  // FIXME: Check return type is complete, !isObjCObjectType
+  
 }
 
 void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
index a3b6768..3bdb3b6 100644 (file)
@@ -2378,7 +2378,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
     // 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());