From: Eli Friedman Date: Fri, 6 Jan 2012 03:05:34 +0000 (+0000) Subject: More lambda work. Fixes a minor bug Richard pointed out, makes lookup for lambda... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=906a7e1c0f272f7e539c82dda01f4644031ce637;p=clang 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 caa4c1a6c8..1edeff5b43 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -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; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 7bf2de492c..6d20480b57 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 &WeakTopLevelDecls() { return WeakTopLevelDecl; } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index e54858f747..cad0a4ae6c 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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(); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 6a77d8c673..4ab960de0e 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -869,6 +869,13 @@ BlockScopeInfo *Sema::getCurBlock() { return dyn_cast(FunctionScopes.back()); } +LambdaScopeInfo *Sema::getCurLambda() { + if (FunctionScopes.empty()) + return 0; + + return dyn_cast(FunctionScopes.back()); +} + // Pin this vtable to this file. ExternalSemaSource::~ExternalSemaSource() {} diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fd47dc75b2..0b1dcbda4f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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(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(); + 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) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a3b6768961..3bdb3b6d2c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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());