diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp | 128 |
1 files changed, 42 insertions, 86 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp index 0b3af26..a0d5749 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -238,7 +238,7 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { /*Template kw loc*/ SourceLocation(), LAngleLoc, llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(), LSI->AutoTemplateParams.size()), - RAngleLoc); + RAngleLoc, nullptr); } return LSI->GLTemplateParameterList; } @@ -361,7 +361,8 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, - ArrayRef<ParmVarDecl *> Params) { + ArrayRef<ParmVarDecl *> Params, + const bool IsConstexprSpecified) { QualType MethodType = MethodTypeInfo->getType(); TemplateParameterList *TemplateParams = getGenericLambdaTemplateParameterList(getCurLambda(), *this); @@ -398,7 +399,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, MethodType, MethodTypeInfo, SC_None, /*isInline=*/true, - /*isConstExpr=*/false, + IsConstexprSpecified, EndLoc); Method->setAccess(AS_public); @@ -883,14 +884,20 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, KnownDependent, Intro.Default); - CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, - MethodTyInfo, EndLoc, Params); + CXXMethodDecl *Method = + startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params, + ParamInfo.getDeclSpec().isConstexprSpecified()); if (ExplicitParams) CheckCXXDefaultArguments(Method); // Attributes on the lambda apply to the method. ProcessDeclAttributes(CurScope, Method, ParamInfo); - + + // CUDA lambdas get implicit attributes based on the scope in which they're + // declared. + if (getLangOpts().CUDA) + CUDASetLambdaAttrs(Method); + // Introduce the function call operator as the current declaration context. PushDeclContext(CurScope, Method); @@ -1148,14 +1155,16 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, /// \brief Add a lambda's conversion to function pointer, as described in /// C++11 [expr.prim.lambda]p6. -static void addFunctionPointerConversion(Sema &S, +static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { // This conversion is explicitly disabled if the lambda's function has // pass_object_size attributes on any of its parameters. - if (llvm::any_of(CallOperator->parameters(), - std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>))) + auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) { + return P->hasAttr<PassObjectSizeAttr>(); + }; + if (llvm::any_of(CallOperator->parameters(), HasPassObjectSizeAttr)) return; // Add the conversion to function pointer. @@ -1265,7 +1274,7 @@ static void addFunctionPointerConversion(Sema &S, ConvTy, ConvTSI, /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/false, + /*isConstexpr=*/S.getLangOpts().CPlusPlus1z, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1375,10 +1384,7 @@ static void addBlockPointerConversion(Sema &S, } static ExprResult performLambdaVarCaptureInitialization( - Sema &S, LambdaScopeInfo::Capture &Capture, - FieldDecl *Field, - SmallVectorImpl<VarDecl *> &ArrayIndexVars, - SmallVectorImpl<unsigned> &ArrayIndexStarts) { + Sema &S, LambdaScopeInfo::Capture &Capture, FieldDecl *Field) { assert(Capture.isVariableCapture() && "not a variable capture"); auto *Var = Capture.getVariable(); @@ -1402,69 +1408,11 @@ static ExprResult performLambdaVarCaptureInitialization( return ExprError(); Expr *Ref = RefResult.get(); - QualType FieldType = Field->getType(); - - // When the variable has array type, create index variables for each - // dimension of the array. We use these index variables to subscript - // the source array, and other clients (e.g., CodeGen) will perform - // the necessary iteration with these index variables. - // - // FIXME: This is dumb. Add a proper AST representation for array - // copy-construction and use it here. - SmallVector<VarDecl *, 4> IndexVariables; - QualType BaseType = FieldType; - QualType SizeType = S.Context.getSizeType(); - ArrayIndexStarts.push_back(ArrayIndexVars.size()); - while (const ConstantArrayType *Array - = S.Context.getAsConstantArrayType(BaseType)) { - // Create the iteration variable for this array index. - IdentifierInfo *IterationVarName = nullptr; - { - SmallString<8> Str; - llvm::raw_svector_ostream OS(Str); - OS << "__i" << IndexVariables.size(); - IterationVarName = &S.Context.Idents.get(OS.str()); - } - VarDecl *IterationVar = VarDecl::Create( - S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, - S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None); - IterationVar->setImplicit(); - IndexVariables.push_back(IterationVar); - ArrayIndexVars.push_back(IterationVar); - - // Create a reference to the iteration variable. - ExprResult IterationVarRef = - S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); - assert(!IterationVarRef.isInvalid() && - "Reference to invented variable cannot fail!"); - IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get()); - assert(!IterationVarRef.isInvalid() && - "Conversion of invented variable cannot fail!"); - - // Subscript the array with this iteration variable. - ExprResult Subscript = - S.CreateBuiltinArraySubscriptExpr(Ref, Loc, IterationVarRef.get(), Loc); - if (Subscript.isInvalid()) - return ExprError(); - - Ref = Subscript.get(); - BaseType = Array->getElementType(); - } - - // Construct the entity that we will be initializing. For an array, this - // will be first element in the array, which may require several levels - // of array-subscript entities. - SmallVector<InitializedEntity, 4> Entities; - Entities.reserve(1 + IndexVariables.size()); - Entities.push_back(InitializedEntity::InitializeLambdaCapture( - Var->getIdentifier(), FieldType, Loc)); - for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) - Entities.push_back( - InitializedEntity::InitializeElement(S.Context, 0, Entities.back())); - + auto Entity = InitializedEntity::InitializeLambdaCapture( + Var->getIdentifier(), Field->getType(), Loc); InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); - InitializationSequence Init(S, Entities.back(), InitKind, Ref); - return Init.Perform(S, Entities.back(), InitKind, Ref); + InitializationSequence Init(S, Entity, InitKind, Ref); + return Init.Perform(S, Entity, InitKind, Ref); } ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, @@ -1505,8 +1453,6 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool ExplicitResultType; CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; - SmallVector<VarDecl *, 4> ArrayIndexVars; - SmallVector<unsigned, 4> ArrayIndexStarts; { CallOperator = LSI->CallOperator; Class = LSI->Lambda; @@ -1540,14 +1486,12 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaCapture(From.getLocation(), IsImplicit, From.isCopyCapture() ? LCK_StarThis : LCK_This)); CaptureInits.push_back(From.getInitExpr()); - ArrayIndexStarts.push_back(ArrayIndexVars.size()); continue; } if (From.isVLATypeCapture()) { Captures.push_back( LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); CaptureInits.push_back(nullptr); - ArrayIndexStarts.push_back(ArrayIndexVars.size()); continue; } @@ -1557,13 +1501,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, Var, From.getEllipsisLoc())); Expr *Init = From.getInitExpr(); if (!Init) { - auto InitResult = performLambdaVarCaptureInitialization( - *this, From, *CurField, ArrayIndexVars, ArrayIndexStarts); + auto InitResult = + performLambdaVarCaptureInitialization(*this, From, *CurField); if (InitResult.isInvalid()) return ExprError(); Init = InitResult.get(); - } else { - ArrayIndexStarts.push_back(ArrayIndexVars.size()); } CaptureInits.push_back(Init); } @@ -1600,9 +1542,22 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CaptureDefault, CaptureDefaultLoc, Captures, ExplicitParams, ExplicitResultType, - CaptureInits, ArrayIndexVars, - ArrayIndexStarts, EndLoc, + CaptureInits, EndLoc, ContainsUnexpandedParameterPack); + // If the lambda expression's call operator is not explicitly marked constexpr + // and we are not in a dependent context, analyze the call operator to infer + // its constexpr-ness, supressing diagnostics while doing so. + if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() && + !CallOperator->isConstexpr() && + !Class->getDeclContext()->isDependentContext()) { + TentativeAnalysisScope DiagnosticScopeGuard(*this); + CallOperator->setConstexpr( + CheckConstexprFunctionDecl(CallOperator) && + CheckConstexprFunctionBody(CallOperator, CallOperator->getBody())); + } + + // Emit delayed shadowing warnings now that the full capture list is known. + DiagnoseShadowingLambdaDecls(LSI); if (!CurContext->isDependentContext()) { switch (ExprEvalContexts.back().Context) { @@ -1610,6 +1565,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). case Unevaluated: + case UnevaluatedList: case UnevaluatedAbstract: // C++1y [expr.const]p2: // A conditional-expression e is a core constant expression unless the |