diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp | 503 |
1 files changed, 317 insertions, 186 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp index 03e9d7bc87a2..9e7c8c7e4e8c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp @@ -39,6 +39,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" using namespace clang; using namespace sema; @@ -216,9 +217,9 @@ static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A, return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2; } -void Sema::DiagnoseUnusedExprResult(const Stmt *S) { +void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) - return DiagnoseUnusedExprResult(Label->getSubStmt()); + return DiagnoseUnusedExprResult(Label->getSubStmt(), DiagID); const Expr *E = dyn_cast_or_null<Expr>(S); if (!E) @@ -264,7 +265,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { // Okay, we have an unused result. Depending on what the base expression is, // we might want to make a more specific diagnostic. Check for one of these // cases now. - unsigned DiagID = diag::warn_unused_expr; if (const FullExpr *Temps = dyn_cast<FullExpr>(E)) E = Temps->getSubExpr(); if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) @@ -339,10 +339,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (LangOpts.OpenMP && isa<CallExpr>(Source) && POE->getNumSemanticExprs() == 1 && isa<CallExpr>(POE->getSemanticExpr(0))) - return DiagnoseUnusedExprResult(POE->getSemanticExpr(0)); + return DiagnoseUnusedExprResult(POE->getSemanticExpr(0), DiagID); if (isa<ObjCSubscriptRefExpr>(Source)) DiagID = diag::warn_unused_container_subscript_expr; - else + else if (isa<ObjCPropertyRefExpr>(Source)) DiagID = diag::warn_unused_property_expr; } else if (const CXXFunctionalCastExpr *FC = dyn_cast<CXXFunctionalCastExpr>(E)) { @@ -379,7 +379,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { return; } - DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2); + // Do not diagnose use of a comma operator in a SFINAE context because the + // type of the left operand could be used for SFINAE, so technically it is + // *used*. + if (DiagID != diag::warn_unused_comma_left_operand || !isSFINAEContext()) + DiagIfReachable(Loc, S ? llvm::ArrayRef(S) : std::nullopt, + PDiag(DiagID) << R1 << R2); } void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) { @@ -406,9 +411,13 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); - // If we're in C89 mode, check that we don't have any decls after stmts. If - // so, emit an extension diagnostic. - if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { + // If we're in C mode, check that we don't have any decls after stmts. If + // so, emit an extension diagnostic in C89 and potentially a warning in later + // versions. + const unsigned MixedDeclsCodeID = getLangOpts().C99 + ? diag::warn_mixed_decls_code + : diag::ext_mixed_decls_code; + if (!getLangOpts().CPlusPlus && !Diags.isIgnored(MixedDeclsCodeID, L)) { // Note that __extension__ can be around a decl. unsigned i = 0; // Skip over all declarations. @@ -421,7 +430,7 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, if (i != NumElts) { Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin(); - Diag(D->getLocation(), diag::ext_mixed_decls_code); + Diag(D->getLocation(), MixedDeclsCodeID); } } @@ -434,7 +443,16 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); } - return CompoundStmt::Create(Context, Elts, L, R); + // Calculate difference between FP options in this compound statement and in + // the enclosing one. If this is a function body, take the difference against + // default options. In this case the difference will indicate options that are + // changed upon entry to the statement. + FPOptions FPO = (getCurFunction()->CompoundScopes.size() == 1) + ? FPOptions(getLangOpts()) + : getCurCompoundScope().InitialFPFeatures; + FPOptionsOverride FPDiff = getCurFPFeatures().getChangesFrom(FPO); + + return CompoundStmt::Create(Context, Elts, FPDiff, L, R); } ExprResult @@ -543,7 +561,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, } ReservedIdentifierStatus Status = TheDecl->isReserved(getLangOpts()); - if (Status != ReservedIdentifierStatus::NotReserved && + if (isReservedInAllContexts(Status) && !Context.getSourceManager().isInSystemHeader(IdentLoc)) Diag(IdentLoc, diag::warn_reserved_extern_symbol) << TheDecl << static_cast<int>(Status); @@ -579,7 +597,7 @@ StmtResult Sema::BuildAttributedStmt(SourceLocation AttrsLoc, return AttributedStmt::Create(Context, AttrsLoc, Attrs, SubStmt); } -StmtResult Sema::ActOnAttributedStmt(const ParsedAttributesWithRange &Attrs, +StmtResult Sema::ActOnAttributedStmt(const ParsedAttributes &Attrs, Stmt *SubStmt) { SmallVector<const Attr *, 1> SemanticAttrs; ProcessStmtAttributes(SubStmt, Attrs, SemanticAttrs); @@ -671,7 +689,7 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { if (CMD->isStatic()) Type.MemberType = FuncType::ft_static_member; else { - Type.This = CMD->getThisType()->getPointeeType(); + Type.This = CMD->getFunctionObjectParameterType(); Type.MemberType = FuncType::ft_non_static_member; } Type.Func = CMD->getType()->castAs<FunctionProtoType>(); @@ -768,6 +786,12 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { return false; } + const auto *CalleeDecl = CE->getCalleeDecl(); + if (CalleeDecl && CalleeDecl->hasAttr<CXX11NoReturnAttr>()) { + Diag(St->getBeginLoc(), diag::err_musttail_no_return) << &MTA; + return false; + } + // Caller and callee must match in whether they have a "this" parameter. if (CallerType.This.isNull() != CalleeType.This.isNull()) { if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) { @@ -858,38 +882,44 @@ public: }; } -StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, +StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, + IfStatementKind StatementKind, SourceLocation LParenLoc, Stmt *InitStmt, ConditionResult Cond, SourceLocation RParenLoc, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { if (Cond.isInvalid()) - Cond = ConditionResult( - *this, nullptr, - MakeFullExpr(new (Context) OpaqueValueExpr(SourceLocation(), - Context.BoolTy, VK_PRValue), - IfLoc), - false); + return StmtError(); + + bool ConstevalOrNegatedConsteval = + StatementKind == IfStatementKind::ConstevalNonNegated || + StatementKind == IfStatementKind::ConstevalNegated; Expr *CondExpr = Cond.get().second; + assert((CondExpr || ConstevalOrNegatedConsteval) && + "If statement: missing condition"); // Only call the CommaVisitor when not C89 due to differences in scope flags. - if ((getLangOpts().C99 || getLangOpts().CPlusPlus) && + if (CondExpr && (getLangOpts().C99 || getLangOpts().CPlusPlus) && !Diags.isIgnored(diag::warn_comma_operator, CondExpr->getExprLoc())) CommaVisitor(*this).Visit(CondExpr); - if (!elseStmt) - DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, - diag::warn_empty_if_body); + if (!ConstevalOrNegatedConsteval && !elseStmt) + DiagnoseEmptyStmtBody(RParenLoc, thenStmt, diag::warn_empty_if_body); - if (IsConstexpr) { + if (ConstevalOrNegatedConsteval || + StatementKind == IfStatementKind::Constexpr) { auto DiagnoseLikelihood = [&](const Stmt *S) { if (const Attr *A = Stmt::getLikelihoodAttr(S)) { Diags.Report(A->getLocation(), - diag::warn_attribute_has_no_effect_on_if_constexpr) - << A << A->getRange(); + diag::warn_attribute_has_no_effect_on_compile_time_if) + << A << ConstevalOrNegatedConsteval << A->getRange(); Diags.Report(IfLoc, - diag::note_attribute_has_no_effect_on_if_constexpr_here) - << SourceRange(IfLoc, LParenLoc.getLocWithOffset(-1)); + diag::note_attribute_has_no_effect_on_compile_time_if_here) + << ConstevalOrNegatedConsteval + << SourceRange(IfLoc, (ConstevalOrNegatedConsteval + ? thenStmt->getBeginLoc() + : LParenLoc) + .getLocWithOffset(-1)); } }; DiagnoseLikelihood(thenStmt); @@ -908,11 +938,25 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, } } - return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc, + if (ConstevalOrNegatedConsteval) { + bool Immediate = ExprEvalContexts.back().Context == + ExpressionEvaluationContext::ImmediateFunctionContext; + if (CurContext->isFunctionOrMethod()) { + const auto *FD = + dyn_cast<FunctionDecl>(Decl::castFromDeclContext(CurContext)); + if (FD && FD->isImmediateFunction()) + Immediate = true; + } + if (isUnevaluatedContext() || Immediate) + Diags.Report(IfLoc, diag::warn_consteval_if_always_true) << Immediate; + } + + return BuildIfStmt(IfLoc, StatementKind, LParenLoc, InitStmt, Cond, RParenLoc, thenStmt, ElseLoc, elseStmt); } -StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, +StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, + IfStatementKind StatementKind, SourceLocation LParenLoc, Stmt *InitStmt, ConditionResult Cond, SourceLocation RParenLoc, Stmt *thenStmt, SourceLocation ElseLoc, @@ -920,12 +964,13 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, if (Cond.isInvalid()) return StmtError(); - if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second)) + if (StatementKind != IfStatementKind::Ordinary || + isa<ObjCAvailabilityCheckExpr>(Cond.get().second)) setFunctionHasBranchProtectedScope(); - return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, - Cond.get().second, LParenLoc, RParenLoc, thenStmt, - ElseLoc, elseStmt); + return IfStmt::Create(Context, IfLoc, StatementKind, InitStmt, + Cond.get().first, Cond.get().second, LParenLoc, + RParenLoc, thenStmt, ElseLoc, elseStmt); } namespace { @@ -1232,6 +1277,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, bool CaseListIsErroneous = false; + // FIXME: We'd better diagnose missing or duplicate default labels even + // in the dependent case. Because default labels themselves are never + // dependent. for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue; SC = SC->getNextSwitchCase()) { @@ -1302,6 +1350,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, assert(!HasConstantCond || (ConstantCondValue.getBitWidth() == CondWidth && ConstantCondValue.isSigned() == CondIsSigned)); + Diag(SwitchLoc, diag::warn_switch_default); } bool ShouldCheckConstantCond = HasConstantCond; @@ -1462,7 +1511,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If switch has default case, then ignore it. if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond && ET && ET->getDecl()->isCompleteDefinition() && - !empty(ET->getDecl()->enumerators())) { + !ET->getDecl()->enumerators().empty()) { const EnumDecl *ED = ET->getDecl(); EnumValsTy EnumVals; @@ -1563,7 +1612,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, auto DB = Diag(CondExpr->getExprLoc(), TheDefaultStmt ? diag::warn_def_missing_case : diag::warn_missing_case) - << (int)UnhandledNames.size(); + << CondExpr->getSourceRange() << (int)UnhandledNames.size(); for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3); I != E; ++I) @@ -1691,9 +1740,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, namespace { // Use SetVector since the diagnostic cares about the ordering of the Decl's. - using DeclSetVector = - llvm::SetVector<VarDecl *, llvm::SmallVector<VarDecl *, 8>, - llvm::SmallPtrSet<VarDecl *, 8>>; + using DeclSetVector = llvm::SmallSetVector<VarDecl *, 8>; // This visitor will traverse a conditional statement and store all // the evaluated decls into a vector. Simple is set to true if none @@ -2271,11 +2318,14 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, // If the type contained 'auto', deduce the 'auto' to 'id'. if (FirstType->getContainedAutoType()) { - OpaqueValueExpr OpaqueId(D->getLocation(), Context.getObjCIdType(), - VK_PRValue); + SourceLocation Loc = D->getLocation(); + OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue); Expr *DeducedInit = &OpaqueId; - if (DeduceAutoType(D->getTypeSourceInfo(), DeducedInit, FirstType) == - DAR_Failed) + TemplateDeductionInfo Info(Loc); + FirstType = QualType(); + TemplateDeductionResult Result = DeduceAutoType( + D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); + if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) DiagnoseAutoDeductionFailure(D, DeducedInit); if (FirstType.isNull()) { D->setInvalidDecl(); @@ -2339,10 +2389,16 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, // Deduce the type for the iterator variable now rather than leaving it to // AddInitializerToDecl, so we can produce a more suitable diagnostic. QualType InitType; - if ((!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) || - SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitType) == - Sema::DAR_Failed) + if (!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) { SemaRef.Diag(Loc, DiagID) << Init->getType(); + } else { + TemplateDeductionInfo Info(Init->getExprLoc()); + Sema::TemplateDeductionResult Result = SemaRef.DeduceAutoType( + Decl->getTypeSourceInfo()->getTypeLoc(), Init, InitType, Info); + if (Result != Sema::TDK_Success && Result != Sema::TDK_AlreadyDiagnosed) + SemaRef.Diag(Loc, DiagID) << Init->getType(); + } + if (InitType.isNull()) { Decl->setInvalidDecl(); return true; @@ -2438,6 +2494,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, BuildForRangeKind Kind) { + // FIXME: recover in order to allow the body to be parsed. if (!First) return StmtError(); @@ -2622,7 +2679,7 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, SemaRef.PDiag(diag::err_for_range_invalid) << BeginRange->getType() << BEFFound), SemaRef, OCD_AllCandidates, BeginRange); - LLVM_FALLTHROUGH; + [[fallthrough]]; case Sema::FRS_DiagnosticIssued: for (NamedDecl *D : OldFound) { @@ -2729,7 +2786,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, if (auto *DD = dyn_cast<DecompositionDecl>(LoopVar)) for (auto *Binding : DD->bindings()) Binding->setType(Context.DependentTy); - LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy)); + LoopVar->setType(SubstAutoTypeDependent(LoopVar->getType())); } } else if (!BeginDeclStmt.get()) { SourceLocation RangeLoc = RangeVar->getLocation(); @@ -3149,7 +3206,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, // (The function `getTypeSize` returns the size in bits.) ASTContext &Ctx = SemaRef.Context; if (Ctx.getTypeSize(VariableType) <= 64 * 8 && - (VariableType.isTriviallyCopyableType(Ctx) || + (VariableType.isTriviallyCopyConstructibleType(Ctx) || hasTrivialABIAttr(VariableType))) return; @@ -3282,7 +3339,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { // C99 6.8.6.2p1: A break shall appear only in or as a loop body. return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop)); } - if (S->getFlags() & Scope::ConditionVarScope) { + if (S->isConditionVarScope()) { // We cannot 'continue;' from within a statement expression in the // initializer of a condition variable because we would jump past the // initialization of that variable. @@ -3316,8 +3373,8 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { /// being thrown, or being co_returned from a coroutine. This expression /// might be modified by the implementation. /// -/// \param ForceCXX2b Overrides detection of current language mode -/// and uses the rules for C++2b. +/// \param Mode Overrides detection of current language mode +/// and uses the rules for C++23. /// /// \returns An aggregate which contains the Candidate and isMoveEligible /// and isCopyElidable methods. If Candidate is non-null, it means @@ -3338,7 +3395,7 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, if (Res.Candidate && !E->isXValue() && (Mode == SimplerImplicitMoveMode::ForceOn || (Mode != SimplerImplicitMoveMode::ForceOff && - getLangOpts().CPlusPlus2b))) { + getLangOpts().CPlusPlus23))) { E = ImplicitCastExpr::Create(Context, VD->getType().getNonReferenceType(), CK_NoOp, E, nullptr, VK_XValue, FPOptionsOverride()); @@ -3453,7 +3510,7 @@ const VarDecl *Sema::getCopyElisionCandidate(NamedReturnInfo &Info, /// Verify that the initialization sequence that was picked for the /// first overload resolution is permissible under C++98. /// -/// Reject (possibly converting) contructors not taking an rvalue reference, +/// Reject (possibly converting) constructors not taking an rvalue reference, /// or user conversion operators which are not ref-qualified. static bool VerifyInitializationSequenceCXX98(const Sema &S, @@ -3482,7 +3539,7 @@ ExprResult Sema::PerformMoveOrCopyInitialization( const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value, bool SupressSimplerImplicitMoves) { if (getLangOpts().CPlusPlus && - (!getLangOpts().CPlusPlus2b || SupressSimplerImplicitMoves) && + (!getLangOpts().CPlusPlus23 || SupressSimplerImplicitMoves) && NRInfo.isMoveEligible()) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), CK_NoOp, Value, VK_XValue, FPOptionsOverride()); @@ -3530,11 +3587,12 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction()); QualType FnRetType = CurCap->ReturnType; LambdaScopeInfo *CurLambda = dyn_cast<LambdaScopeInfo>(CurCap); + if (CurLambda && CurLambda->CallOperator->getType().isNull()) + return StmtError(); bool HasDeducedReturnType = CurLambda && hasDeducedReturnType(CurLambda->CallOperator); - if (ExprEvalContexts.back().Context == - ExpressionEvaluationContext::DiscardedStatement && + if (ExprEvalContexts.back().isDiscardedStatementContext() && (HasDeducedReturnType || CurCap->HasImplicitReturnType)) { if (RetValExp) { ExprResult ER = @@ -3684,6 +3742,11 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, if (FunctionScopes.back()->FirstReturnLoc.isInvalid()) FunctionScopes.back()->FirstReturnLoc = ReturnLoc; + if (auto *CurBlock = dyn_cast<BlockScopeInfo>(CurCap); + CurBlock && CurCap->HasImplicitReturnType && RetValExp && + RetValExp->containsErrors()) + CurBlock->TheDecl->setInvalidDecl(); + return Result; } @@ -3732,17 +3795,13 @@ TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const { /// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, - Expr *&RetExpr, - AutoType *AT) { - // If this is the conversion function for a lambda, we choose to deduce it + Expr *RetExpr, const AutoType *AT) { + // If this is the conversion function for a lambda, we choose to deduce its // type from the corresponding call operator, not from the synthesized return // statement within it. See Sema::DeduceReturnType. if (isLambdaConversionOperator(FD)) return false; - TypeLoc OrigResultType = getReturnTypeLoc(FD); - QualType Deduced; - if (RetExpr && isa<InitListExpr>(RetExpr)) { // If the deduction is for a return statement and the initializer is // a braced-init-list, the program is ill-formed. @@ -3762,80 +3821,84 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, return false; } - if (RetExpr) { - // Otherwise, [...] deduce a value for U using the rules of template - // argument deduction. - DeduceAutoResult DAR = DeduceAutoType(OrigResultType, RetExpr, Deduced); - - if (DAR == DAR_Failed && !FD->isInvalidDecl()) - Diag(RetExpr->getExprLoc(), diag::err_auto_fn_deduction_failure) - << OrigResultType.getType() << RetExpr->getType(); - - if (DAR != DAR_Succeeded) - return true; - - // If a local type is part of the returned type, mark its fields as - // referenced. - LocalTypedefNameReferencer Referencer(*this); - Referencer.TraverseType(RetExpr->getType()); - } else { - // In the case of a return with no operand, the initializer is considered - // to be void(). - // - // Deduction here can only succeed if the return type is exactly 'cv auto' - // or 'decltype(auto)', so just check for that case directly. + TypeLoc OrigResultType = getReturnTypeLoc(FD); + // In the case of a return with no operand, the initializer is considered + // to be void(). + CXXScalarValueInitExpr VoidVal(Context.VoidTy, nullptr, SourceLocation()); + if (!RetExpr) { + // For a function with a deduced result type to return with omitted + // expression, the result type as written must be 'auto' or + // 'decltype(auto)', possibly cv-qualified or constrained, but not + // ref-qualified. if (!OrigResultType.getType()->getAs<AutoType>()) { Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto) - << OrigResultType.getType(); + << OrigResultType.getType(); return true; } - // We always deduce U = void in this case. - Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy); - if (Deduced.isNull()) - return true; + RetExpr = &VoidVal; } - // CUDA: Kernel function must have 'void' return type. - if (getLangOpts().CUDA) - if (FD->hasAttr<CUDAGlobalAttr>() && !Deduced->isVoidType()) { - Diag(FD->getLocation(), diag::err_kern_type_not_void_return) - << FD->getType() << FD->getSourceRange(); - return true; + QualType Deduced = AT->getDeducedType(); + { + // Otherwise, [...] deduce a value for U using the rules of template + // argument deduction. + auto RetExprLoc = RetExpr->getExprLoc(); + TemplateDeductionInfo Info(RetExprLoc); + SourceLocation TemplateSpecLoc; + if (RetExpr->getType() == Context.OverloadTy) { + auto FindResult = OverloadExpr::find(RetExpr); + if (FindResult.Expression) + TemplateSpecLoc = FindResult.Expression->getNameLoc(); } - - // If a function with a declared return type that contains a placeholder type - // has multiple return statements, the return type is deduced for each return - // statement. [...] if the type deduced is not the same in each deduction, - // the program is ill-formed. - QualType DeducedT = AT->getDeducedType(); - if (!DeducedT.isNull() && !FD->isInvalidDecl()) { - AutoType *NewAT = Deduced->getContainedAutoType(); - // It is possible that NewAT->getDeducedType() is null. When that happens, - // we should not crash, instead we ignore this deduction. - if (NewAT->getDeducedType().isNull()) - return false; - - CanQualType OldDeducedType = Context.getCanonicalFunctionResultType( - DeducedT); - CanQualType NewDeducedType = Context.getCanonicalFunctionResultType( - NewAT->getDeducedType()); - if (!FD->isDependentContext() && OldDeducedType != NewDeducedType) { + TemplateSpecCandidateSet FailedTSC(TemplateSpecLoc); + TemplateDeductionResult Res = DeduceAutoType( + OrigResultType, RetExpr, Deduced, Info, /*DependentDeduction=*/false, + /*IgnoreConstraints=*/false, &FailedTSC); + if (Res != TDK_Success && FD->isInvalidDecl()) + return true; + switch (Res) { + case TDK_Success: + break; + case TDK_AlreadyDiagnosed: + return true; + case TDK_Inconsistent: { + // If a function with a declared return type that contains a placeholder + // type has multiple return statements, the return type is deduced for + // each return statement. [...] if the type deduced is not the same in + // each deduction, the program is ill-formed. const LambdaScopeInfo *LambdaSI = getCurLambda(); - if (LambdaSI && LambdaSI->HasImplicitReturnType) { + if (LambdaSI && LambdaSI->HasImplicitReturnType) Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) - << NewAT->getDeducedType() << DeducedT - << true /*IsLambda*/; - } else { + << Info.SecondArg << Info.FirstArg << true /*IsLambda*/; + else Diag(ReturnLoc, diag::err_auto_fn_different_deductions) - << (AT->isDecltypeAuto() ? 1 : 0) - << NewAT->getDeducedType() << DeducedT; - } + << (AT->isDecltypeAuto() ? 1 : 0) << Info.SecondArg + << Info.FirstArg; + return true; + } + default: + Diag(RetExpr->getExprLoc(), diag::err_auto_fn_deduction_failure) + << OrigResultType.getType() << RetExpr->getType(); + FailedTSC.NoteCandidates(*this, RetExprLoc); return true; } - } else if (!FD->isInvalidDecl()) { + } + + // If a local type is part of the returned type, mark its fields as + // referenced. + LocalTypedefNameReferencer(*this).TraverseType(RetExpr->getType()); + + // CUDA: Kernel function must have 'void' return type. + if (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>() && + !Deduced->isVoidType()) { + Diag(FD->getLocation(), diag::err_kern_type_not_void_return) + << FD->getType() << FD->getSourceRange(); + return true; + } + + if (!FD->isInvalidDecl() && AT->getDeducedType() != Deduced) // Update all declarations of the function to have the deduced return type. Context.adjustDeducedFunctionResultType(FD, Deduced); - } return false; } @@ -3849,17 +3912,15 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true); if (RetVal.isInvalid()) return StmtError(); - StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get()); - if (R.isInvalid() || ExprEvalContexts.back().Context == - ExpressionEvaluationContext::DiscardedStatement) + StmtResult R = + BuildReturnStmt(ReturnLoc, RetVal.get(), /*AllowRecovery=*/true); + if (R.isInvalid() || ExprEvalContexts.back().isDiscardedStatementContext()) return R; - if (VarDecl *VD = - const_cast<VarDecl*>(cast<ReturnStmt>(R.get())->getNRVOCandidate())) { - CurScope->addNRVOCandidate(VD); - } else { - CurScope->setNoNRVO(); - } + VarDecl *VD = + const_cast<VarDecl *>(cast<ReturnStmt>(R.get())->getNRVOCandidate()); + + CurScope->updateNRVOCandidate(VD); CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); @@ -3868,7 +3929,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, static bool CheckSimplerImplicitMovesMSVCWorkaround(const Sema &S, const Expr *E) { - if (!E || !S.getLangOpts().CPlusPlus2b || !S.getLangOpts().MSVCCompat) + if (!E || !S.getLangOpts().CPlusPlus23 || !S.getLangOpts().MSVCCompat) return false; const Decl *D = E->getReferencedDeclOfCallee(); if (!D || !S.SourceMgr.isInSystemHeader(D->getLocation())) @@ -3880,12 +3941,13 @@ static bool CheckSimplerImplicitMovesMSVCWorkaround(const Sema &S, return false; } -StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { +StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, + bool AllowRecovery) { // Check for unexpanded parameter packs. if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); - // HACK: We supress simpler implicit move here in msvc compatibility mode + // HACK: We suppress simpler implicit move here in msvc compatibility mode // just as a temporary work around, as the MSVC STL has issues with // this change. bool SupressSimplerImplicitMoves = @@ -3934,10 +3996,17 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else // If we don't have a function/method context, bail. return StmtError(); + if (RetValExp) { + const auto *ATy = dyn_cast<ArrayType>(RetValExp->getType()); + if (ATy && ATy->getElementType().isWebAssemblyReferenceType()) { + Diag(ReturnLoc, diag::err_wasm_table_art) << 1; + return StmtError(); + } + } + // C++1z: discarded return statements are not considered when deducing a // return type. - if (ExprEvalContexts.back().Context == - ExpressionEvaluationContext::DiscardedStatement && + if (ExprEvalContexts.back().isDiscardedStatementContext() && FnRetType->getContainedAutoType()) { if (RetValExp) { ExprResult ER = @@ -3958,11 +4027,25 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If we've already decided this function is invalid, e.g. because // we saw a `return` whose expression had an error, don't keep // trying to deduce its return type. - if (FD->isInvalidDecl()) - return StmtError(); - if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { + // (Some return values may be needlessly wrapped in RecoveryExpr). + if (FD->isInvalidDecl() || + DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); - return StmtError(); + if (!AllowRecovery) + return StmtError(); + // The deduction failure is diagnosed and marked, try to recover. + if (RetValExp) { + // Wrap return value with a recovery expression of the previous type. + // If no deduction yet, use DependentTy. + auto Recovery = CreateRecoveryExpr( + RetValExp->getBeginLoc(), RetValExp->getEndLoc(), RetValExp, + AT->isDeduced() ? FnRetType : QualType()); + if (Recovery.isInvalid()) + return StmtError(); + RetValExp = Recovery.get(); + } else { + // Nothing to do: a ReturnStmt with no value is fine recovery. + } } else { FnRetType = FD->getReturnType(); } @@ -3975,7 +4058,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ReturnStmt *Result = nullptr; if (FnRetType->isVoidType()) { if (RetValExp) { - if (isa<InitListExpr>(RetValExp)) { + if (auto *ILE = dyn_cast<InitListExpr>(RetValExp)) { // We simply never allow init lists as the return value of void // functions. This is compatible because this was never allowed before, // so there's no legacy code to deal with. @@ -3991,8 +4074,12 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Diag(ReturnLoc, diag::err_return_init_list) << CurDecl << FunctionKind << RetValExp->getSourceRange(); - // Drop the expression. - RetValExp = nullptr; + // Preserve the initializers in the AST. + RetValExp = AllowRecovery + ? CreateRecoveryExpr(ILE->getLBraceLoc(), + ILE->getRBraceLoc(), ILE->inits()) + .get() + : nullptr; } else if (!RetValExp->isTypeDependent()) { // C99 6.8.6.4p1 (ext_ since GCC warns) unsigned D = diag::ext_return_has_expr; @@ -4051,7 +4138,9 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); - if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { + if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) { + // The intended return type might have been "void", so don't warn. + } else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { // C++11 [stmt.return]p2 Diag(ReturnLoc, diag::err_constexpr_return_missing_expr) << FD << FD->isConsteval(); @@ -4089,6 +4178,9 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { InitializedEntity::InitializeResult(ReturnLoc, RetType); ExprResult Res = PerformMoveOrCopyInitialization( Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves); + if (Res.isInvalid() && AllowRecovery) + Res = CreateRecoveryExpr(RetValExp->getBeginLoc(), + RetValExp->getEndLoc(), RetValExp, RetType); if (Res.isInvalid()) { // FIXME: Clean up temporaries here anyway? return StmtError(); @@ -4157,7 +4249,14 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, if (!getLangOpts().ObjCExceptions) Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; - setFunctionHasBranchProtectedScope(); + // Objective-C try is incompatible with SEH __try. + sema::FunctionScopeInfo *FSI = getCurFunction(); + if (FSI->FirstSEHTryLoc.isValid()) { + Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1; + Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; + } + + FSI->setHasObjCTry(AtLoc); unsigned NumCatchStmts = CatchStmts.size(); return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), NumCatchStmts, Finally); @@ -4287,9 +4386,9 @@ public: if (QT->isPointerType()) IsPointer = true; + QT = QT.getUnqualifiedType(); if (IsPointer || QT->isReferenceType()) QT = QT->getPointeeType(); - QT = QT.getUnqualifiedType(); } /// Used when creating a CatchHandlerType from a base class type; pretends the @@ -4337,32 +4436,42 @@ template <> struct DenseMapInfo<CatchHandlerType> { namespace { class CatchTypePublicBases { - ASTContext &Ctx; - const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &TypesToCheck; - const bool CheckAgainstPointer; + const llvm::DenseMap<QualType, CXXCatchStmt *> &TypesToCheck; CXXCatchStmt *FoundHandler; - CanQualType FoundHandlerType; + QualType FoundHandlerType; + QualType TestAgainstType; public: - CatchTypePublicBases( - ASTContext &Ctx, - const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &T, bool C) - : Ctx(Ctx), TypesToCheck(T), CheckAgainstPointer(C), - FoundHandler(nullptr) {} + CatchTypePublicBases(const llvm::DenseMap<QualType, CXXCatchStmt *> &T, + QualType QT) + : TypesToCheck(T), FoundHandler(nullptr), TestAgainstType(QT) {} CXXCatchStmt *getFoundHandler() const { return FoundHandler; } - CanQualType getFoundHandlerType() const { return FoundHandlerType; } + QualType getFoundHandlerType() const { return FoundHandlerType; } bool operator()(const CXXBaseSpecifier *S, CXXBasePath &) { if (S->getAccessSpecifier() == AccessSpecifier::AS_public) { - CatchHandlerType Check(S->getType(), CheckAgainstPointer); + QualType Check = S->getType().getCanonicalType(); const auto &M = TypesToCheck; auto I = M.find(Check); if (I != M.end()) { - FoundHandler = I->second; - FoundHandlerType = Ctx.getCanonicalType(S->getType()); - return true; + // We're pretty sure we found what we need to find. However, we still + // need to make sure that we properly compare for pointers and + // references, to handle cases like: + // + // } catch (Base *b) { + // } catch (Derived &d) { + // } + // + // where there is a qualification mismatch that disqualifies this + // handler as a potential problem. + if (I->second->getCaughtType()->isPointerType() == + TestAgainstType->isPointerType()) { + FoundHandler = I->second; + FoundHandlerType = Check; + return true; + } } } return false; @@ -4374,13 +4483,22 @@ public: /// handlers and creates a try statement from them. StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, ArrayRef<Stmt *> Handlers) { - // Don't report an error if 'try' is used in system headers. - if (!getLangOpts().CXXExceptions && + const llvm::Triple &T = Context.getTargetInfo().getTriple(); + const bool IsOpenMPGPUTarget = + getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN()); + // Don't report an error if 'try' is used in system headers or in an OpenMP + // target region compiled for a GPU architecture. + if (!IsOpenMPGPUTarget && !getLangOpts().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc) && !getLangOpts().CUDA) { // Delay error emission for the OpenMP device code. targetDiag(TryLoc, diag::err_exceptions_disabled) << "try"; } + // In OpenMP target regions, we assume that catch is never reached on GPU + // targets. + if (IsOpenMPGPUTarget) + targetDiag(TryLoc, diag::warn_try_not_valid_on_target) << T.str(); + // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) @@ -4393,7 +4511,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // C++ try is incompatible with SEH __try. if (!getLangOpts().Borland && FSI->FirstSEHTryLoc.isValid()) { - Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); + Diag(TryLoc, diag::err_mixing_cxx_try_seh_try) << 0; Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; } @@ -4401,6 +4519,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, assert(!Handlers.empty() && "The parser shouldn't call this if there are no handlers."); + llvm::DenseMap<QualType, CXXCatchStmt *> HandledBaseTypes; llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> HandledTypes; for (unsigned i = 0; i < NumHandlers; ++i) { CXXCatchStmt *H = cast<CXXCatchStmt>(Handlers[i]); @@ -4418,8 +4537,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Walk the type hierarchy to diagnose when this type has already been // handled (duplication), or cannot be handled (derivation inversion). We // ignore top-level cv-qualifiers, per [except.handle]p3 - CatchHandlerType HandlerCHT = - (QualType)Context.getCanonicalType(H->getCaughtType()); + CatchHandlerType HandlerCHT = H->getCaughtType().getCanonicalType(); // We can ignore whether the type is a reference or a pointer; we need the // underlying declaration type in order to get at the underlying record @@ -4435,10 +4553,12 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // as the original type. CXXBasePaths Paths; Paths.setOrigin(RD); - CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer()); + CatchTypePublicBases CTPB(HandledBaseTypes, + H->getCaughtType().getCanonicalType()); if (RD->lookupInBases(CTPB, Paths)) { const CXXCatchStmt *Problem = CTPB.getFoundHandler(); - if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) { + if (!Paths.isAmbiguous( + CanQualType::CreateUnsafe(CTPB.getFoundHandlerType()))) { Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), diag::warn_exception_caught_by_earlier_handler) << H->getCaughtType(); @@ -4447,11 +4567,16 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, << Problem->getCaughtType(); } } + // Strip the qualifiers here because we're going to be comparing this + // type to the base type specifiers of a class, which are ignored in a + // base specifier per [class.derived.general]p2. + HandledBaseTypes[Underlying.getUnqualifiedType()] = H; } // Add the type the list of ones we have handled; diagnose if we've already // handled it. - auto R = HandledTypes.insert(std::make_pair(H->getCaughtType(), H)); + auto R = HandledTypes.insert( + std::make_pair(H->getCaughtType().getCanonicalType(), H)); if (!R.second) { const CXXCatchStmt *Problem = R.first->second; Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), @@ -4465,7 +4590,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, FSI->setHasCXXTry(TryLoc); - return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers); + return CXXTryStmt::Create(Context, TryLoc, cast<CompoundStmt>(TryBlock), + Handlers); } StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, @@ -4477,9 +4603,12 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, // SEH __try is incompatible with C++ try. Borland appears to support this, // however. if (!getLangOpts().Borland) { - if (FSI->FirstCXXTryLoc.isValid()) { - Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); - Diag(FSI->FirstCXXTryLoc, diag::note_conflicting_try_here) << "'try'"; + if (FSI->FirstCXXOrObjCTryLoc.isValid()) { + Diag(TryLoc, diag::err_mixing_cxx_try_seh_try) << FSI->FirstTryType; + Diag(FSI->FirstCXXOrObjCTryLoc, diag::note_conflicting_try_here) + << (FSI->FirstTryType == sema::FunctionScopeInfo::TryLocIsCXX + ? "'try'" + : "'@try'"); } } @@ -4573,10 +4702,11 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, RecordDecl *RD = nullptr; if (getLangOpts().CPlusPlus) - RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, + RD = CXXRecordDecl::Create(Context, TagTypeKind::Struct, DC, Loc, Loc, /*Id=*/nullptr); else - RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr); + RD = RecordDecl::Create(Context, TagTypeKind::Struct, DC, Loc, Loc, + /*Id=*/nullptr); RD->setCapturedRecord(); DC->addDecl(RD); @@ -4620,11 +4750,11 @@ buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI, if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) S.setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel); - Captures.push_back(CapturedStmt::Capture(Cap.getLocation(), - Cap.isReferenceCapture() - ? CapturedStmt::VCK_ByRef - : CapturedStmt::VCK_ByCopy, - Cap.getVariable())); + Captures.push_back(CapturedStmt::Capture( + Cap.getLocation(), + Cap.isReferenceCapture() ? CapturedStmt::VCK_ByRef + : CapturedStmt::VCK_ByCopy, + cast<VarDecl>(Cap.getVariable()))); } CaptureInits.push_back(Init.get()); } @@ -4643,7 +4773,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, - ImplicitParamDecl::CapturedContext); + ImplicitParamKind::CapturedContext); DC->addDecl(Param); CD->setContextParam(0, Param); @@ -4658,6 +4788,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, PushExpressionEvaluationContext( ExpressionEvaluationContext::PotentiallyEvaluated); + ExprEvalContexts.back().InImmediateEscalatingFunctionContext = false; } void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, @@ -4683,7 +4814,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, .withRestrict(); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, - ImplicitParamDecl::CapturedContext); + ImplicitParamKind::CapturedContext); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); ContextIsFound = true; @@ -4691,7 +4822,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, IdentifierInfo *ParamName = &Context.Idents.get(I->first); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second, - ImplicitParamDecl::CapturedContext); + ImplicitParamKind::CapturedContext); DC->addDecl(Param); CD->setParam(ParamNum, Param); } @@ -4703,7 +4834,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, - ImplicitParamDecl::CapturedContext); + ImplicitParamKind::CapturedContext); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); } |