diff options
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 218 |
1 files changed, 131 insertions, 87 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index f91b93f957..f97b5232ac 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { 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 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, CXXMethodDecl *CallOperator; SourceRange IntroducerRange; bool ExplicitParams; + bool ExplicitResultType; bool LambdaExprNeedsCleanups; llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; llvm::SmallVector<unsigned, 4> ArrayIndexStarts; @@ -314,6 +357,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, 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 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, // 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 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, 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 |