diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp | 217 |
1 files changed, 141 insertions, 76 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp index 73f3183c163f..b24a8ab110b2 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp @@ -385,6 +385,14 @@ void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) { PushCompoundScope(IsStmtExpr); } +void Sema::ActOnAfterCompoundStatementLeadingPragmas() { + if (getCurFPFeatures().isFPConstrained()) { + FunctionScopeInfo *FSI = getCurFunction(); + assert(FSI); + FSI->setUsesFPIntrin(); + } +} + void Sema::ActOnFinishOfCompoundStmt() { PopCompoundScope(); } @@ -397,11 +405,6 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); - // Mark the current function as usng floating point constrained intrinsics - if (getCurFPFeatures().isFPConstrained()) - if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) - F->setUsesFPIntrin(true); - // 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) { @@ -467,7 +470,7 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) { ExprResult ER = E; if (!E->isValueDependent()) - ER = VerifyIntegerConstantExpression(E); + ER = VerifyIntegerConstantExpression(E, AllowFold); if (!ER.isInvalid()) ER = DefaultLvalueConversion(ER.get()); if (!ER.isInvalid()) @@ -574,11 +577,11 @@ public: }; } -StmtResult -Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, - ConditionResult Cond, - Stmt *thenStmt, SourceLocation ElseLoc, - Stmt *elseStmt) { +StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, SourceLocation RParenLoc, + Stmt *thenStmt, SourceLocation ElseLoc, + Stmt *elseStmt) { if (Cond.isInvalid()) Cond = ConditionResult( *this, nullptr, @@ -597,12 +600,40 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, diag::warn_empty_if_body); - return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, - elseStmt); + if (IsConstexpr) { + 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(); + Diags.Report(IfLoc, + diag::note_attribute_has_no_effect_on_if_constexpr_here) + << SourceRange(IfLoc, LParenLoc.getLocWithOffset(-1)); + } + }; + DiagnoseLikelihood(thenStmt); + DiagnoseLikelihood(elseStmt); + } else { + std::tuple<bool, const Attr *, const Attr *> LHC = + Stmt::determineLikelihoodConflict(thenStmt, elseStmt); + if (std::get<0>(LHC)) { + const Attr *ThenAttr = std::get<1>(LHC); + const Attr *ElseAttr = std::get<2>(LHC); + Diags.Report(ThenAttr->getLocation(), + diag::warn_attributes_likelihood_ifstmt_conflict) + << ThenAttr << ThenAttr->getRange(); + Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute) + << ElseAttr << ElseAttr->getRange(); + } + } + + return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc, + thenStmt, ElseLoc, elseStmt); } StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, - Stmt *InitStmt, ConditionResult Cond, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, SourceLocation RParenLoc, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { if (Cond.isInvalid()) @@ -612,7 +643,8 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, setFunctionHasBranchProtectedScope(); return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, - Cond.get().second, thenStmt, ElseLoc, elseStmt); + Cond.get().second, LParenLoc, RParenLoc, thenStmt, + ElseLoc, elseStmt); } namespace { @@ -640,8 +672,7 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs, return true; if (lhs.first == rhs.first && - lhs.second->getCaseLoc().getRawEncoding() - < rhs.second->getCaseLoc().getRawEncoding()) + lhs.second->getCaseLoc() < rhs.second->getCaseLoc()) return true; return false; } @@ -739,7 +770,9 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) { } StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - Stmt *InitStmt, ConditionResult Cond) { + SourceLocation LParenLoc, + Stmt *InitStmt, ConditionResult Cond, + SourceLocation RParenLoc) { Expr *CondExpr = Cond.get().second; assert((Cond.isInvalid() || CondExpr) && "switch with no condition"); @@ -761,7 +794,8 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, setFunctionHasBranchIntoScope(); - auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr); + auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr, + LParenLoc, RParenLoc); getCurFunction()->SwitchStack.push_back( FunctionScopeInfo::SwitchInfo(SS, false)); return SS; @@ -1244,10 +1278,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // Produce a nice diagnostic if multiple values aren't handled. if (!UnhandledNames.empty()) { - DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(), - TheDefaultStmt ? diag::warn_def_missing_case + auto DB = Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case : diag::warn_missing_case) - << (int)UnhandledNames.size(); + << (int)UnhandledNames.size(); for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3); I != E; ++I) @@ -1787,15 +1821,27 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, // C99 6.8.5p3: The declaration part of a 'for' statement shall only // declare identifiers for objects having storage class 'auto' or // 'register'. + const Decl *NonVarSeen = nullptr; + bool VarDeclSeen = false; for (auto *DI : DS->decls()) { - VarDecl *VD = dyn_cast<VarDecl>(DI); - if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage()) - VD = nullptr; - if (!VD) { - Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); - DI->setInvalidDecl(); + if (VarDecl *VD = dyn_cast<VarDecl>(DI)) { + VarDeclSeen = true; + if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) { + Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); + DI->setInvalidDecl(); + } + } else if (!NonVarSeen) { + // Keep track of the first non-variable declaration we saw so that + // we can diagnose if we don't see any variable declarations. This + // covers a case like declaring a typedef, function, or structure + // type rather than a variable. + NonVarSeen = DI; } } + // Diagnose if we saw a non-variable declaration but no variable + // declarations. + if (NonVarSeen && !VarDeclSeen) + Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for); } } @@ -3039,12 +3085,13 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, // variable will no longer be used. if (VD->hasAttr<BlocksAttr>()) return false; + // ...non-volatile... + if (VD->getType().isVolatileQualified()) + return false; + if (CESK & CES_AllowDifferentTypes) return true; - // ...non-volatile... - if (VD->getType().isVolatileQualified()) return false; - // Variables with higher required alignment than their type's ABI // alignment cannot use NRVO. if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() && @@ -3070,15 +3117,18 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, /// If move-initialization is not possible, such that we must fall back to /// treating the operand as an lvalue, we will leave Res in its original /// invalid state. -static void TryMoveInitialization(Sema& S, - const InitializedEntity &Entity, +/// +/// \returns Whether we need to do the second overload resolution. If the first +/// overload resolution fails, or if the first overload resolution succeeds but +/// the selected constructor/operator doesn't match the additional criteria, we +/// need to do the second overload resolution. +static bool TryMoveInitialization(Sema &S, const InitializedEntity &Entity, const VarDecl *NRVOCandidate, - QualType ResultType, - Expr *&Value, + QualType ResultType, Expr *&Value, bool ConvertingConstructorsOnly, - ExprResult &Res) { + bool IsDiagnosticsCheck, ExprResult &Res) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), - CK_NoOp, Value, VK_XValue); + CK_NoOp, Value, VK_XValue, FPOptionsOverride()); Expr *InitExpr = &AsRvalue; @@ -3087,8 +3137,11 @@ static void TryMoveInitialization(Sema& S, InitializationSequence Seq(S, Entity, Kind, InitExpr); - if (!Seq) - return; + bool NeedSecondOverloadResolution = true; + if (!Seq && + (IsDiagnosticsCheck || Seq.getFailedOverloadResult() != OR_Deleted)) { + return NeedSecondOverloadResolution; + } for (const InitializationSequence::Step &Step : Seq.steps()) { if (Step.Kind != InitializationSequence::SK_ConstructorInitialization && @@ -3131,15 +3184,19 @@ static void TryMoveInitialization(Sema& S, } } + NeedSecondOverloadResolution = false; // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. - Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, - Value, nullptr, VK_XValue); + Value = + ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, Value, + nullptr, VK_XValue, FPOptionsOverride()); // Complete type-checking the initialization of the return type // using the constructor we found. Res = Seq.Perform(S, Entity, Kind, Value); } + + return NeedSecondOverloadResolution; } /// Perform the initialization of a potentially-movable value, which @@ -3164,6 +3221,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // select the constructor for the copy is first performed as if the object // were designated by an rvalue. ExprResult Res = ExprError(); + bool NeedSecondOverloadResolution = true; if (AllowNRVO) { bool AffectedByCWG1579 = false; @@ -3180,15 +3238,14 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, } if (NRVOCandidate) { - TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value, - true, Res); + NeedSecondOverloadResolution = TryMoveInitialization( + *this, Entity, NRVOCandidate, ResultType, Value, true, false, Res); } - if (!Res.isInvalid() && AffectedByCWG1579) { + if (!NeedSecondOverloadResolution && AffectedByCWG1579) { QualType QT = NRVOCandidate->getType(); - if (QT.getNonReferenceType() - .getUnqualifiedType() - .isTriviallyCopyableType(Context)) { + if (QT.getNonReferenceType().getUnqualifiedType().isTriviallyCopyableType( + Context)) { // Adding 'std::move' around a trivially copyable variable is probably // pointless. Don't suggest it. } else { @@ -3202,12 +3259,12 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, Str += NRVOCandidate->getDeclName().getAsString(); Str += ")"; Diag(Value->getExprLoc(), diag::warn_return_std_move_in_cxx11) - << Value->getSourceRange() - << NRVOCandidate->getDeclName() << ResultType << QT; + << Value->getSourceRange() << NRVOCandidate->getDeclName() + << ResultType << QT; Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11) << FixItHint::CreateReplacement(Value->getSourceRange(), Str); } - } else if (Res.isInvalid() && + } else if (NeedSecondOverloadResolution && !getDiagnostics().isIgnored(diag::warn_return_std_move, Value->getExprLoc())) { const VarDecl *FakeNRVOCandidate = @@ -3226,7 +3283,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, ExprResult FakeRes = ExprError(); Expr *FakeValue = Value; TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType, - FakeValue, false, FakeRes); + FakeValue, false, true, FakeRes); if (!FakeRes.isInvalid()) { bool IsThrow = (Entity.getKind() == InitializedEntity::EK_Exception); @@ -3248,7 +3305,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // Either we didn't meet the criteria for treating an lvalue as an rvalue, // above, or overload resolution failed. Either way, we need to try // (again) now with the return value expression as written. - if (Res.isInvalid()) + if (NeedSecondOverloadResolution) Res = PerformCopyInitialization(Entity, SourceLocation(), Value); return Res; @@ -3290,9 +3347,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (HasDeducedReturnType) { + FunctionDecl *FD = CurLambda->CallOperator; + // If we've already decided this lambda 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(); // In C++1y, the return type may involve 'auto'. // FIXME: Blocks might have a return type of 'auto' explicitly specified. - FunctionDecl *FD = CurLambda->CallOperator; if (CurCap->ReturnType.isNull()) CurCap->ReturnType = FD->getReturnType(); @@ -3587,7 +3649,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, Scope *CurScope) { // Correct typos, in case the containing function returns 'auto' and // RetValExp should determine the deduced type. - ExprResult RetVal = CorrectDelayedTyposInExpr(RetValExp); + ExprResult RetVal = CorrectDelayedTyposInExpr( + RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true); if (RetVal.isInvalid()) return StmtError(); StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get()); @@ -3625,12 +3688,11 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (FD->hasAttrs()) Attrs = &FD->getAttrs(); if (FD->isNoReturn()) - Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) - << FD->getDeclName(); + Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD; if (FD->isMain() && RetValExp) if (isa<CXXBoolLiteralExpr>(RetValExp)) Diag(ReturnLoc, diag::warn_main_returns_bool_literal) - << RetValExp->getSourceRange(); + << RetValExp->getSourceRange(); if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) { if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) { if (RT->getDecl()->isOrContainsUnion()) @@ -3673,6 +3735,11 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (getLangOpts().CPlusPlus14) { if (AutoType *AT = FnRetType->getContainedAutoType()) { FunctionDecl *FD = cast<FunctionDecl>(CurContext); + // 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)) { FD->setInvalidDecl(); return StmtError(); @@ -3701,8 +3768,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { FunctionKind = 3; Diag(ReturnLoc, diag::err_return_init_list) - << CurDecl->getDeclName() << FunctionKind - << RetValExp->getSourceRange(); + << CurDecl << FunctionKind << RetValExp->getSourceRange(); // Drop the expression. RetValExp = nullptr; @@ -3729,9 +3795,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // return of void in constructor/destructor is illegal in C++. if (D == diag::err_ctor_dtor_returns_void) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); - Diag(ReturnLoc, D) - << CurDecl->getDeclName() << isa<CXXDestructorDecl>(CurDecl) - << RetValExp->getSourceRange(); + Diag(ReturnLoc, D) << CurDecl << isa<CXXDestructorDecl>(CurDecl) + << RetValExp->getSourceRange(); } // return (some void expression); is legal in C++. else if (D != diag::ext_return_has_void_expr || @@ -3747,8 +3812,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { FunctionKind = 3; Diag(ReturnLoc, D) - << CurDecl->getDeclName() << FunctionKind - << RetValExp->getSourceRange(); + << CurDecl << FunctionKind << RetValExp->getSourceRange(); } } @@ -3766,25 +3830,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); - unsigned DiagID; if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { // C++11 [stmt.return]p2 - DiagID = diag::err_constexpr_return_missing_expr; + Diag(ReturnLoc, diag::err_constexpr_return_missing_expr) + << FD << FD->isConsteval(); FD->setInvalidDecl(); - } else if (getLangOpts().C99) { - // C99 6.8.6.4p1 (ext_ since GCC warns) - DiagID = diag::ext_return_missing_expr; } else { + // C99 6.8.6.4p1 (ext_ since GCC warns) // C90 6.6.6.4p4 - DiagID = diag::warn_return_missing_expr; + unsigned DiagID = getLangOpts().C99 ? diag::ext_return_missing_expr + : diag::warn_return_missing_expr; + // Note that at this point one of getCurFunctionDecl() or + // getCurMethodDecl() must be non-null (see above). + assert((getCurFunctionDecl() || getCurMethodDecl()) && + "Not in a FunctionDecl or ObjCMethodDecl?"); + bool IsMethod = FD == nullptr; + const NamedDecl *ND = + IsMethod ? cast<NamedDecl>(getCurMethodDecl()) : cast<NamedDecl>(FD); + Diag(ReturnLoc, DiagID) << ND << IsMethod; } - if (FD) - Diag(ReturnLoc, DiagID) - << FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval(); - else - Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; - Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr, /* NRVOCandidate=*/nullptr); } else { |