diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fb52b90ae4a3c..68172d5317a13 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -206,12 +206,6 @@ Improvements to Clang's diagnostics - Clang no longer emits irrelevant notes about unsatisfied constraint expressions on the left-hand side of ``||`` when the right-hand side constraint is satisfied. (`#54678: `_). -- Clang now diagnoses wider cases of tautological use of consteval if or - ``std::is_constant_evaluated``. This also suppresses some false positives. - (`#43760: `_) - (`#51567: `_) -- Clang now diagnoses narrowing implicit conversions on variable initializers in immediate - function context and on constexpr variable template initializers. - Clang now prints its 'note' diagnostic in cyan instead of black, to be more compatible with terminals with dark background colors. This is also more consistent with GCC. diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 1abb0b89af9f1..d2656310e79c9 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -413,6 +413,10 @@ def warn_constexpr_unscoped_enum_out_of_range : Warning< def note_unimplemented_constexpr_lambda_feature_ast : Note< "unimplemented constexpr lambda feature: %0 (coming soon!)">; +def warn_is_constant_evaluated_always_true_constexpr : Warning< + "'%0' will always evaluate to 'true' in a manifestly constant-evaluated expression">, + InGroup>; + // inline asm related. let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_escape : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3f30681a378e2..f4eb02fd9570c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1591,8 +1591,8 @@ def err_static_assert_message_constexpr : Error< "the message in a static assertion must be produced by a " "constant expression">; -def warn_tautological_consteval_if : Warning< - "consteval if is always %select{true|false}0 in this context">, +def warn_consteval_if_always_true : Warning< + "consteval if is always true in an %select{unevaluated|immediate}0 context">, InGroup>; def ext_inline_variable : ExtWarn< @@ -8897,9 +8897,6 @@ def warn_side_effects_unevaluated_context : Warning< def warn_side_effects_typeid : Warning< "expression with side effects will be evaluated despite being used as an " "operand to 'typeid'">, InGroup; -def warn_tautological_is_constant_evaluated : Warning< - "'%select{std::is_constant_evaluated|__builtin_is_constant_evaluated}0' will always evaluate to %select{false|true}1 in this context">, - InGroup>; def warn_unused_result : Warning< "ignoring return value of function declared with %0 attribute">, InGroup; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ae3c265f40a2c..f599b8b98d031 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2003,10 +2003,12 @@ class Parser : public CodeCompletionHandler { //===--------------------------------------------------------------------===// // C++ if/switch/while/for condition expression. struct ForRangeInfo; - Sema::ConditionResult ParseCXXCondition( - StmtResult *InitStmt, SourceLocation Loc, Sema::ConditionKind CK, - bool MissingOK, ForRangeInfo *FRI = nullptr, - bool EnterForConditionScope = false, SourceLocation ConstexprLoc = {}); + Sema::ConditionResult ParseCXXCondition(StmtResult *InitStmt, + SourceLocation Loc, + Sema::ConditionKind CK, + bool MissingOK, + ForRangeInfo *FRI = nullptr, + bool EnterForConditionScope = false); DeclGroupPtrTy ParseAliasDeclarationInInitStatement(DeclaratorContext Context, ParsedAttributes &Attrs); @@ -2104,8 +2106,7 @@ class Parser : public CodeCompletionHandler { Sema::ConditionResult &CondResult, SourceLocation Loc, Sema::ConditionKind CK, SourceLocation &LParenLoc, - SourceLocation &RParenLoc, - SourceLocation ConstexprLoc = {}); + SourceLocation &RParenLoc); StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc); StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc); StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e4366170005a0..712db0a3dd895 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1358,9 +1358,6 @@ class Sema final { bool InDiscardedStatement; bool InImmediateFunctionContext; bool InImmediateEscalatingFunctionContext; - // The immediate occurances of consteval if or std::is_constant_evaluated() - // are tautologically false - bool IsRuntimeEvaluated; bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false; @@ -1390,8 +1387,7 @@ class Sema final { NumCleanupObjects(NumCleanupObjects), NumTypos(0), ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext), InDiscardedStatement(false), InImmediateFunctionContext(false), - InImmediateEscalatingFunctionContext(false), - IsRuntimeEvaluated(false) {} + InImmediateEscalatingFunctionContext(false) {} bool isUnevaluated() const { return Context == ExpressionEvaluationContext::Unevaluated || @@ -1430,10 +1426,6 @@ class Sema final { /// A stack of expression evaluation contexts. SmallVector ExprEvalContexts; - /// Source location of the start of `constexpr` in constexpr-if - /// used for diagnostics - SourceLocation ConstexprIfLoc; - // Set of failed immediate invocations to avoid double diagnosing. llvm::SmallPtrSet FailedImmediateInvocations; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 310debe327017..fea06b97259fe 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12178,6 +12178,22 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, } case Builtin::BI__builtin_is_constant_evaluated: { + const auto *Callee = Info.CurrentCall->getCallee(); + if (Info.InConstantContext && !Info.CheckingPotentialConstantExpression && + (Info.CallStackDepth == 1 || + (Info.CallStackDepth == 2 && Callee->isInStdNamespace() && + Callee->getIdentifier() && + Callee->getIdentifier()->isStr("is_constant_evaluated")))) { + // FIXME: Find a better way to avoid duplicated diagnostics. + if (Info.EvalStatus.Diag) + Info.report((Info.CallStackDepth == 1) + ? E->getExprLoc() + : Info.CurrentCall->getCallRange().getBegin(), + diag::warn_is_constant_evaluated_always_true_constexpr) + << (Info.CallStackDepth == 1 ? "__builtin_is_constant_evaluated" + : "std::is_constant_evaluated"); + } + return Success(Info.InConstantContext, E); } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f5b4107cc32c1..748b9d53c9f5b 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2461,15 +2461,6 @@ Decl *Parser::ParseDeclarationAfterDeclarator( return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); } -/// Determine whether the given declaration is a global variable or -/// static data member. -static bool isNonlocalVariable(const Decl *D) { - if (const VarDecl *Var = dyn_cast_or_null(D)) - return Var->hasGlobalStorage(); - - return false; -} - Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) { // RAII type used to track whether we're inside an initializer. @@ -2502,36 +2493,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( ThisDecl = nullptr; } }; - struct EnterInitializerExpressionEvaluationContext { - Sema &S; - bool Entered; - - EnterInitializerExpressionEvaluationContext(Sema &S, Declarator &D, - Decl *ThisDecl) - : S(S), Entered(false) { - if (ThisDecl && S.getLangOpts().CPlusPlus && !ThisDecl->isInvalidDecl()) { - Entered = true; - bool RuntimeEvaluated = S.ExprEvalContexts.back().IsRuntimeEvaluated; - Sema::ExpressionEvaluationContext NewEEC = - S.ExprEvalContexts.back().Context; - if ((D.getDeclSpec().getTypeQualifiers() == DeclSpec::TQ_const || - isNonlocalVariable(ThisDecl)) && - S.ExprEvalContexts.back().IsRuntimeEvaluated) { - RuntimeEvaluated = false; - } - if (D.getDeclSpec().hasConstexprSpecifier()) { - NewEEC = Sema::ExpressionEvaluationContext::ConstantEvaluated; - RuntimeEvaluated = false; - } - S.PushExpressionEvaluationContext(NewEEC, ThisDecl); - S.ExprEvalContexts.back().IsRuntimeEvaluated = RuntimeEvaluated; - } - } - ~EnterInitializerExpressionEvaluationContext() { - if (Entered) - S.PopExpressionEvaluationContext(); - } - }; enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced }; InitKind TheInitKind; @@ -2631,7 +2592,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( << getLangOpts().CPlusPlus20; } else { InitializerScopeRAII InitScope(*this, D, ThisDecl); - EnterInitializerExpressionEvaluationContext InitEC(Actions, D, ThisDecl); if (Tok.is(tok::code_completion)) { cutOffParsing(); @@ -2679,7 +2639,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( ExprVector Exprs; InitializerScopeRAII InitScope(*this, D, ThisDecl); - EnterInitializerExpressionEvaluationContext InitEC(Actions, D, ThisDecl); auto ThisVarDecl = dyn_cast_or_null(ThisDecl); auto RunSignatureHelp = [&]() { @@ -2730,7 +2689,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); InitializerScopeRAII InitScope(*this, D, ThisDecl); - EnterInitializerExpressionEvaluationContext InitEC(Actions, D, ThisDecl); PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl); ExprResult Init(ParseBraceInitializer()); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index e5a278c598cfb..5a6b5efbf6c12 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3234,14 +3234,9 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, bool IsFieldInitialization = isa_and_present(D); - bool IsConstexpr = false; - if (const auto *VD = dyn_cast_if_present(D)) - IsConstexpr = VD->isConstexpr(); - EnterExpressionEvaluationContext Context( Actions, - IsConstexpr ? Sema::ExpressionEvaluationContext::ConstantEvaluated - : IsFieldInitialization + IsFieldInitialization ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed : Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 0e69be6bcb3ce..74664c34abdbd 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2093,13 +2093,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { }; if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { - // FIXME: arguments in consteval functions are constant expression - // regardless of the evaluation context of callsite. However, we - // cannot know whether the called function is constevasl before the - // declaration is resolved. - bool IsRuntimeEvaluated = - Actions.ExprEvalContexts.back().IsRuntimeEvaluated; - Actions.ExprEvalContexts.back().IsRuntimeEvaluated = false; if (ParseExpressionList(ArgExprs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); @@ -2116,8 +2109,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { for (auto &E : ArgExprs) Actions.CorrectDelayedTyposInExpr(E); } - Actions.ExprEvalContexts.back().IsRuntimeEvaluated = - IsRuntimeEvaluated; } } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index d20d400e3076e..99b4931004546 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -2041,8 +2041,7 @@ Parser::ParseAliasDeclarationInInitStatement(DeclaratorContext Context, Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, Sema::ConditionKind CK, bool MissingOK, - ForRangeInfo *FRI, bool EnterForConditionScope, - SourceLocation ConstexprLoc) { + ForRangeInfo *FRI, bool EnterForConditionScope) { // Helper to ensure we always enter a continue/break scope if requested. struct ForConditionScopeRAII { Scope *S; @@ -2099,28 +2098,9 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, *InitStmt = Actions.ActOnNullStmt(SemiLoc); return ParseCXXCondition(nullptr, Loc, CK, MissingOK); } - bool InitStmtIsExprStmt = false; - if (InitStmt) { - RevertingTentativeParsingAction PA(*this); - SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch); - InitStmtIsExprStmt = Tok.is(tok::semi); - } - ExprResult Expr; // expression - { - EnterExpressionEvaluationContext Consteval( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, - Sema::ExpressionEvaluationContextRecord::EK_Other, - /*ShouldEnter=*/CK == Sema::ConditionKind::ConstexprIf && - !InitStmtIsExprStmt); - SourceLocation OuterConstexprIfLoc = Actions.ConstexprIfLoc; - Actions.ConstexprIfLoc = ConstexprLoc; - - // Parse the expression. - Expr = ParseExpression(); // expression - Actions.ConstexprIfLoc = OuterConstexprIfLoc; - } + // Parse the expression. + ExprResult Expr = ParseExpression(); // expression if (Expr.isInvalid()) return Sema::ConditionError(); @@ -2208,21 +2188,6 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, if (CopyInitialization) ConsumeToken(); - Sema::ExpressionEvaluationContext NewEEC = - Actions.ExprEvalContexts.back().Context; - bool RuntimeEvaluated = Actions.ExprEvalContexts.back().IsRuntimeEvaluated; - if (DS.getTypeQualifiers() == DeclSpec::TQ_const) - RuntimeEvaluated = false; - - if (CK == Sema::ConditionKind::ConstexprIf || DS.hasConstexprSpecifier()) { - RuntimeEvaluated = false; - NewEEC = Sema::ExpressionEvaluationContext::ConstantEvaluated; - } - EnterExpressionEvaluationContext Initializer(Actions, NewEEC, DeclOut); - Actions.ExprEvalContexts.back().IsRuntimeEvaluated = RuntimeEvaluated; - SourceLocation OuterConstexprIfLoc = Actions.ConstexprIfLoc; - Actions.ConstexprIfLoc = ConstexprLoc; - ExprResult InitExpr = ExprError(); if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok.getLocation(), @@ -2249,7 +2214,6 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, Actions.ActOnInitializerError(DeclOut); Actions.FinalizeDeclaration(DeclOut); - Actions.ConstexprIfLoc = OuterConstexprIfLoc; return Actions.ActOnConditionVariable(DeclOut, Loc, CK); } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 75c689f21efa2..2531147c23196 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1293,17 +1293,18 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { /// errors in the condition. /// Additionally, it will assign the location of the outer-most '(' and ')', /// to LParenLoc and RParenLoc, respectively. -bool Parser::ParseParenExprOrCondition( - StmtResult *InitStmt, Sema::ConditionResult &Cond, SourceLocation Loc, - Sema::ConditionKind CK, SourceLocation &LParenLoc, - SourceLocation &RParenLoc, SourceLocation ConstexprLoc) { +bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt, + Sema::ConditionResult &Cond, + SourceLocation Loc, + Sema::ConditionKind CK, + SourceLocation &LParenLoc, + SourceLocation &RParenLoc) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); SourceLocation Start = Tok.getLocation(); if (getLangOpts().CPlusPlus) { - Cond = ParseCXXCondition(InitStmt, Loc, CK, false, nullptr, false, - ConstexprLoc); + Cond = ParseCXXCondition(InitStmt, Loc, CK, false); } else { ExprResult CondExpr = ParseExpression(); @@ -1463,13 +1464,12 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { bool IsConsteval = false; SourceLocation NotLocation; SourceLocation ConstevalLoc; - SourceLocation ConstexprLoc; if (Tok.is(tok::kw_constexpr)) { Diag(Tok, getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_constexpr_if : diag::ext_constexpr_if); IsConstexpr = true; - ConstexprLoc = ConsumeToken(); + ConsumeToken(); } else { if (Tok.is(tok::exclaim)) { NotLocation = ConsumeToken(); @@ -1515,7 +1515,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc, IsConstexpr ? Sema::ConditionKind::ConstexprIf : Sema::ConditionKind::Boolean, - LParen, RParen, ConstexprLoc)) + LParen, RParen)) return StmtError(); if (IsConstexpr) @@ -1558,16 +1558,11 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { if (NotLocation.isInvalid() && IsConsteval) { Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext; ShouldEnter = true; - } else if (NotLocation.isValid() && IsConsteval) { - Context = Actions.ExprEvalContexts.back().Context; - ShouldEnter = true; } EnterExpressionEvaluationContext PotentiallyDiscarded( Actions, Context, nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter); - if (NotLocation.isValid() && IsConsteval) - Actions.ExprEvalContexts.back().IsRuntimeEvaluated = true; ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc); } @@ -1608,16 +1603,11 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { if (NotLocation.isValid() && IsConsteval) { Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext; ShouldEnter = true; - } else if (NotLocation.isInvalid() && IsConsteval) { - Context = Actions.ExprEvalContexts.back().Context; - ShouldEnter = true; } EnterExpressionEvaluationContext PotentiallyDiscarded( Actions, Context, nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter); - if (NotLocation.isInvalid() && IsConsteval) - Actions.ExprEvalContexts.back().IsRuntimeEvaluated = true; ElseStmt = ParseStatement(); if (ElseStmt.isUsable()) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 4d4bedf75963a..6a3b5fa61d594 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -14836,8 +14836,7 @@ static void DiagnoseIntInBoolContext(Sema &S, Expr *E) { static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = nullptr, - bool IsListInit = false, - bool IsConstexprInit = false) { + bool IsListInit = false) { if (E->isTypeDependent() || E->isValueDependent()) return; const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); @@ -15146,14 +15145,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SmallString<32> PrettyTargetValue; TargetFloatValue.toString(PrettyTargetValue, TargetPrecision); - PartialDiagnostic PD = + S.DiagRuntimeBehavior( + E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_float_precision_constant) - << PrettySourceValue << PrettyTargetValue << E->getType() << T - << E->getSourceRange() << clang::SourceRange(CC); - if (IsConstexprInit) - S.Diag(E->getExprLoc(), PD); - else - S.DiagRuntimeBehavior(E->getExprLoc(), E, PD); + << PrettySourceValue << PrettyTargetValue << E->getType() << T + << E->getSourceRange() << clang::SourceRange(CC)); } } else { // Otherwise, the implicit conversion may lose precision. @@ -15207,14 +15203,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, std::string PrettySourceValue = toString(Value, 10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - PartialDiagnostic PD = + S.DiagRuntimeBehavior( + E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_precision_constant) - << PrettySourceValue << PrettyTargetValue << E->getType() << T - << E->getSourceRange() << SourceRange(CC); - if (IsConstexprInit) - S.Diag(E->getExprLoc(), PD); - else - S.DiagRuntimeBehavior(E->getExprLoc(), E, PD); + << PrettySourceValue << PrettyTargetValue << E->getType() << T + << E->getSourceRange() << SourceRange(CC)); return; } @@ -15256,14 +15249,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, std::string PrettySourceValue = toString(Value, 10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - PartialDiagnostic PD = + S.DiagRuntimeBehavior( + E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_precision_constant) - << PrettySourceValue << PrettyTargetValue << E->getType() << T - << E->getSourceRange() << SourceRange(CC); - if (IsConstexprInit) - S.Diag(E->getExprLoc(), PD); - else - S.DiagRuntimeBehavior(E->getExprLoc(), E, PD); + << PrettySourceValue << PrettyTargetValue << E->getType() << T + << E->getSourceRange() << SourceRange(CC)); return; } } @@ -15425,17 +15415,6 @@ static void AnalyzeImplicitConversions( if (auto *Src = OVE->getSourceExpr()) SourceExpr = Src; - bool IsConstexprInit = - S.isConstantEvaluated() && - isa_and_present(S.ExprEvalContexts.back().ManglingContextDecl); - // Constant-evaluated initializers are not diagnosed by DiagRuntimeBehavior, - // but narrowings from the evaluated result to the variable type should be - // diagnosed. - if (IsConstexprInit && SourceExpr->getType() != T) { - CheckImplicitConversion(S, SourceExpr, T, CC, nullptr, IsListInit, - /*IsConstexprInit=*/true); - } - if (const auto *UO = dyn_cast(SourceExpr)) if (UO->getOpcode() == UO_Not && UO->getSubExpr()->isKnownToHaveBooleanValue()) @@ -15471,7 +15450,7 @@ static void AnalyzeImplicitConversions( // Go ahead and check any implicit conversions we might have skipped. // The non-canonical typecheck is just an optimization; // CheckImplicitConversion will filter out dead implicit conversions. - if (!IsConstexprInit && SourceExpr->getType() != T) + if (SourceExpr->getType() != T) CheckImplicitConversion(S, SourceExpr, T, CC, nullptr, IsListInit); // Now continue drilling into this expression. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 30e4af16944ab..7d92e93188610 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15443,7 +15443,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, // Do not push if it is a lambda because one is already pushed when building // the lambda in ActOnStartOfLambdaDefinition(). - if (!isLambdaCallOperator(FD)) { + if (!isLambdaCallOperator(FD)) // [expr.const]/p14.1 // An expression or conversion is in an immediate function context if it is // potentially evaluated and either: its innermost enclosing non-block scope @@ -15451,9 +15451,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, PushExpressionEvaluationContext( FD->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext : ExprEvalContexts.back().Context); - if (!FD->isConsteval() && !FD->isConstexpr()) - ExprEvalContexts.back().IsRuntimeEvaluated = true; - } // Each ExpressionEvaluationContextRecord also keeps track of whether the // context is nested in an immediate function context, so smaller contexts diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3d5ecfc2eb256..0091e0ecf6f39 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -18241,6 +18241,15 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) { Diag(D->getLocation(), diag::err_illegal_initializer); } +/// Determine whether the given declaration is a global variable or +/// static data member. +static bool isNonlocalVariable(const Decl *D) { + if (const VarDecl *Var = dyn_cast_or_null(D)) + return Var->hasGlobalStorage(); + + return false; +} + /// Invoked when we are about to parse an initializer for the declaration /// 'Dcl'. /// @@ -18263,6 +18272,9 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // If we are parsing the initializer for a static data member, push a // new expression evaluation context that is associated with this static // data member. + if (isNonlocalVariable(D)) + PushExpressionEvaluationContext( + ExpressionEvaluationContext::PotentiallyEvaluated, D); } /// Invoked after we are finished parsing an initializer for the declaration D. @@ -18271,6 +18283,9 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { if (!D || D->isInvalidDecl()) return; + if (isNonlocalVariable(D)) + PopExpressionEvaluationContext(); + if (S && D->isOutOfLine()) ExitDeclaratorContext(S); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 305b437437747..92496b03ecabe 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7091,32 +7091,6 @@ static void DiagnosedUnqualifiedCallsToStdFunctions(Sema &S, << FixItHint::CreateInsertion(DRE->getLocation(), "std::"); } -// Diagnose uses of std::is_constant_evaluated or -// __builtin_is_constant_evaluated in contexts where the result is known at -// compile time. -static void DiagnoseTautologicalCallToIsConstantEvaluated(Sema &S, - const CallExpr *CE) { - if (S.inTemplateInstantiation() || CE->getBeginLoc().isMacroID()) - return; - if (const FunctionDecl *FD = CE->getDirectCallee()) { - bool IsBuiltin = - FD->getBuiltinID() == Builtin::BI__builtin_is_constant_evaluated; - SourceLocation ConstexprIfLoc = S.ConstexprIfLoc; - - if ((FD->isInStdNamespace() && - FD->getNameAsString() == "is_constant_evaluated") || - IsBuiltin) { - bool AlwaysTrue = S.ExprEvalContexts.back().isConstantEvaluated() || - S.ExprEvalContexts.back().isUnevaluated(); - bool AlwaysFalse = S.ExprEvalContexts.back().IsRuntimeEvaluated; - if (AlwaysTrue || AlwaysFalse) - S.Diag(CE->getBeginLoc(), diag::warn_tautological_is_constant_evaluated) - << IsBuiltin << AlwaysTrue - << FixItHint::CreateRemoval(ConstexprIfLoc); - } - } -} - ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig) { @@ -7141,10 +7115,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, Call = ActOnOpenMPCall(Call, Scope, LParenLoc, ArgExprs, RParenLoc, ExecConfig); if (LangOpts.CPlusPlus) { - if (const auto *CE = dyn_cast(Call.get())) { + if (const auto *CE = dyn_cast(Call.get())) DiagnosedUnqualifiedCallsToStdFunctions(*this, CE); - DiagnoseTautologicalCallToIsConstantEvaluated(*this, CE); - } } return Call; } @@ -18636,8 +18608,6 @@ void Sema::PopExpressionEvaluationContext() { } else llvm_unreachable("Couldn't infer lambda error message."); - if (auto *VD = dyn_cast_if_present(Rec.ManglingContextDecl)) - VD->setInvalidDecl(); for (const auto *L : Rec.Lambdas) Diag(L->getBeginLoc(), D); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index bd2c3c2f45d4c..1702ddb3ee0fb 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1444,13 +1444,12 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. - bool InImmediateFunctionContext = isImmediateFunctionContext(); PushExpressionEvaluationContext( - LSI->CallOperator->isConsteval() || InImmediateFunctionContext + LSI->CallOperator->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext : ExpressionEvaluationContext::PotentiallyEvaluated); ExprEvalContexts.back().InImmediateFunctionContext = - LSI->CallOperator->isConsteval() || InImmediateFunctionContext; + LSI->CallOperator->isConsteval(); ExprEvalContexts.back().InImmediateEscalatingFunctionContext = getLangOpts().CPlusPlus20 && LSI->CallOperator->isImmediateEscalating(); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index c20d0c50b09e1..10adfbc406dfb 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -933,14 +933,16 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, } if (ConstevalOrNegatedConsteval) { - bool AlwaysTrue = ExprEvalContexts.back().isConstantEvaluated() || - ExprEvalContexts.back().isUnevaluated(); - bool AlwaysFalse = ExprEvalContexts.back().IsRuntimeEvaluated; - if (AlwaysTrue || AlwaysFalse) - Diags.Report(IfLoc, diag::warn_tautological_consteval_if) - << (AlwaysTrue - ? StatementKind == IfStatementKind::ConstevalNegated - : StatementKind == IfStatementKind::ConstevalNonNegated); + bool Immediate = ExprEvalContexts.back().Context == + ExpressionEvaluationContext::ImmediateFunctionContext; + if (CurContext->isFunctionOrMethod()) { + const auto *FD = + dyn_cast(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, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index c4f1c4e06ac83..fa839e9b71a3c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5378,11 +5378,8 @@ void Sema::InstantiateVariableInitializer( Var->setImplicitlyInline(); if (OldVar->getInit()) { - Sema::ExpressionEvaluationContext InitEvalContext = - Var->isConstexpr() - ? Sema::ExpressionEvaluationContext::ConstantEvaluated - : Sema::ExpressionEvaluationContext::PotentiallyEvaluated; - EnterExpressionEvaluationContext Evaluated(*this, InitEvalContext, Var); + EnterExpressionEvaluationContext Evaluated( + *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); // Instantiate the initializer. ExprResult Init; diff --git a/clang/test/AST/Interp/builtins.cpp b/clang/test/AST/Interp/builtins.cpp index 90bd290f1d6a4..5e2ffe50f3740 100644 --- a/clang/test/AST/Interp/builtins.cpp +++ b/clang/test/AST/Interp/builtins.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -Wno-constant-evaluated -verify -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -Wno-constant-evaluated -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -S -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated %s -S -emit-llvm -o - | FileCheck %s diff --git a/clang/test/AST/Interp/if.cpp b/clang/test/AST/Interp/if.cpp index 3d1ed7b7ffe76..86ae8de6f73eb 100644 --- a/clang/test/AST/Interp/if.cpp +++ b/clang/test/AST/Interp/if.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fexperimental-new-constant-interpreter -Wno-redundant-consteval-if %s -verify -// RUN: %clang_cc1 -std=c++23 -fsyntax-only -Wno-redundant-consteval-if %s -verify=ref +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify +// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify=ref // expected-no-diagnostics // ref-no-diagnostics diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 67de4ef6dae2a..aabc909b3328e 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -225,11 +225,15 @@ namespace SizeOf { #if __cplusplus >= 202002L /// FIXME: The following code should be accepted. consteval int foo(int n) { // ref-error {{consteval function never produces a constant expression}} - return sizeof(int[n]); // ref-note 2 {{not valid in a constant expression}} + return sizeof(int[n]); // ref-note 3{{not valid in a constant expression}} \ + // expected-note {{not valid in a constant expression}} } - constinit int var = foo(5); // ref-note {{in call to}} \ + constinit int var = foo(5); // ref-error {{not a constant expression}} \ + // ref-note 2{{in call to}} \ // ref-error {{does not have a constant initializer}} \ // ref-note {{required by 'constinit' specifier}} \ + // expected-error {{is not a constant expression}} \ + // expected-note {{in call to}} \ // expected-error {{does not have a constant initializer}} \ // expected-note {{required by 'constinit' specifier}} \ diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index 596df90243b1e..e3cd057baba75 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -244,8 +244,8 @@ namespace UndefinedBehavior { constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }} constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }} constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }} - constexpr signed char c1 = 100 * 2; // ok expected-warning {{changes value from 200 to -56}} - constexpr signed char c2 = '\x64' * '\2'; // also ok expected-warning {{changes value from 200 to -56}} + constexpr signed char c1 = 100 * 2; // ok expected-warning{{changes value}} + constexpr signed char c2 = '\x64' * '\2'; // also ok expected-warning{{changes value}} constexpr long long ll1 = 0x7fffffffffffffff; // ok constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }} constexpr long long ll3 = -ll1 - 1; // ok diff --git a/clang/test/CXX/expr/expr.const/p6-2a.cpp b/clang/test/CXX/expr/expr.const/p6-2a.cpp index 7bcf6fdc3d997..a937474d53b22 100644 --- a/clang/test/CXX/expr/expr.const/p6-2a.cpp +++ b/clang/test/CXX/expr/expr.const/p6-2a.cpp @@ -43,11 +43,12 @@ struct Temporary { constexpr Temporary t = {3}; // expected-error {{must have constant destruction}} expected-note {{created here}} expected-note {{in call}} namespace P1073R3 { -consteval int f() { return 42; } // expected-note {{declared here}} +consteval int f() { return 42; } // expected-note 2 {{declared here}} consteval auto g() { return f; } consteval int h(int (*p)() = g()) { return p(); } constexpr int r = h(); -constexpr auto e = g(); // expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \ - expected-note {{pointer to a consteval declaration is not a constant expression}} +constexpr auto e = g(); // expected-error {{call to consteval function 'P1073R3::g' is not a constant expression}} \ + expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \ + expected-note 2 {{pointer to a consteval declaration is not a constant expression}} static_assert(r == 42); } // namespace P1073R3 diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp index 8b30b5eefd85f..db40bd5d1420e 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp @@ -16,5 +16,4 @@ constexpr auto literal = []{}; #if __cplusplus < 201703L // expected-error@-2 {{constexpr variable cannot have non-literal type}} // expected-note@-3 {{lambda closure types are non-literal types before C++17}} -// expected-error@-4 {{a lambda expression may not appear inside of a constant expression}} #endif diff --git a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p4.cpp b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p4.cpp index fd2deee249016..8d43be6fc9047 100644 --- a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p4.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p4.cpp @@ -38,8 +38,7 @@ void test_consteval() { }() == 1); if consteval [[likely]] { // expected-warning {{attribute 'likely' has no effect when annotating an 'if consteval' statement}}\ - // expected-note 2{{annotating the 'if consteval' statement here}} \ - // expected-warning {{consteval if is always false}} + // expected-note 2{{annotating the 'if consteval' statement here}} } @@ -50,8 +49,7 @@ void test_consteval() { } void test_consteval_jumps() { - if consteval { // expected-warning {{consteval if is always false}} \ - // expected-note 4{{jump enters controlled statement of consteval if}} + if consteval { // expected-note 4{{jump enters controlled statement of consteval if}} goto a; goto b; // expected-error {{cannot jump from this goto statement to its label}} a:; @@ -67,16 +65,14 @@ void test_consteval_jumps() { void test_consteval_switch() { int x = 42; switch (x) { - if consteval { // expected-warning {{consteval if is always false}} \ - // expected-note 2{{jump enters controlled statement of consteval if}} + if consteval { // expected-note 2{{jump enters controlled statement of consteval if}} case 1:; // expected-error {{cannot jump from switch statement to this case label}} default:; // expected-error {{cannot jump from switch statement to this case label}} } else { } } switch (x) { - if consteval { // expected-warning {{consteval if is always false}} \ - // expected-note 2{{jump enters controlled statement of consteval if}} + if consteval { // expected-note 2{{jump enters controlled statement of consteval if}} } else { case 2:; // expected-error {{cannot jump from switch statement to this case label}} default:; // expected-error {{cannot jump from switch statement to this case label}} @@ -103,32 +99,32 @@ constexpr int h(int i) { // expected-note {{declared here}} } consteval void warn_in_consteval() { - if consteval { // expected-warning {{consteval if is always true in this context}} - if consteval {} // expected-warning {{consteval if is always true in this context}} + if consteval { // expected-warning {{consteval if is always true in an immediate context}} + if consteval {} // expected-warning {{consteval if is always true in an immediate context}} } } constexpr void warn_in_consteval2() { if consteval { - if consteval {} // expected-warning {{consteval if is always true in this context}} + if consteval {} // expected-warning {{consteval if is always true in an immediate context}} } } auto y = []() consteval { - if consteval { // expected-warning {{consteval if is always true in this context}} - if consteval {} // expected-warning {{consteval if is always true in this context}} + if consteval { // expected-warning {{consteval if is always true in an immediate context}} + if consteval {} // expected-warning {{consteval if is always true in an immediate context}} } }; namespace test_transform { int f(auto n) { - if consteval { // expected-warning {{consteval if is always false}} + if consteval { n.foo; //expected-error {{no member named}} } else { } - if !consteval { // expected-warning {{consteval if is always true}} + if !consteval { n.foo; //expected-error {{no member named}} } else { diff --git a/clang/test/Parser/pragma-fenv_access.c b/clang/test/Parser/pragma-fenv_access.c index a626453344ee6..76256cff1b49b 100644 --- a/clang/test/Parser/pragma-fenv_access.c +++ b/clang/test/Parser/pragma-fenv_access.c @@ -33,7 +33,7 @@ int main(void) { CONST float fnot_too_big = not_too_big; CONST int too_big = 0x7ffffff0; #if defined(CPP) -//expected-warning@+2{{implicit conversion from 'const int' to 'const float' changes value from 2147483632 to 2147483648}} +//expected-warning@+2{{implicit conversion}} #endif CONST float fbig = too_big; // inexact #if !defined(CPP) diff --git a/clang/test/SemaCXX/constant-conversion.cpp b/clang/test/SemaCXX/constant-conversion.cpp index 884166c419764..9be8b139e79e2 100644 --- a/clang/test/SemaCXX/constant-conversion.cpp +++ b/clang/test/SemaCXX/constant-conversion.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify -triple x86_64-apple-darwin %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin %s // This file tests -Wconstant-conversion, a subcategory of -Wconversion // which is on by default. @@ -31,59 +31,3 @@ void test_bitfield() { s.one_bit = 1; // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} s.one_bit = true; // no-warning } - -namespace Initializers { -constexpr char ok = true ? 0 : 200; -constexpr char a = 200; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} -char b = 200; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 200 to -56}} -const char c = 200; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} - -void f() { - constexpr char a = 200; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} - char b = 200; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 200 to -56}} - const char c = 200; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} - static char d = 2 * 100; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 200 to -56}} -} - -constexpr void g() { - constexpr char a = 2 * 100; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} - char b = 2 * 100; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 200 to -56}} - const char c = 2 * 100; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} -} - -consteval void h() { - char ok = true ? 0 : 200; - constexpr char a = 200; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} - char b = 200; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 200 to -56}} - const char c = 200; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} -} - -template -int templ() { - constexpr char a = false ? 129 : N; // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 200 to -56}} \ - // expected-warning {{implicit conversion from 'int' to 'const char' changes value from 345 to 89}} - return 3; -} - -void call_templ() { - int ok = templ<127>(); - int l = templ<3>(); - int m = templ<200>(); // expected-note {{in instantiation of}} - int n = templ<345>(); // expected-note {{in instantiation of}} -} - -template -constexpr signed char diff = a > b ? a - b : b - a; // expected-warning{{changes value from 201 to -55}} \ - // expected-warning{{changes value from 199 to -57}} \ - // expected-warning{{changes value from 299 to 43}} \ - // expected-warning{{changes value from 301 to 45}} - -void test_diff() { - char ok1 = diff<201, 100>; - char ok2 = diff<101, 200>; - char s1 = diff<301, 100>; // expected-note {{in instantiation of}} - char s2 = diff<101, 300>; // expected-note {{in instantiation of}} - char w1 = diff<101, 400>; // expected-note {{in instantiation of}} - char w2 = diff<401, 100>; // expected-note {{in instantiation of}} -} -} diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 8e6af7811a30b..89d1b3ea6de05 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1961,7 +1961,7 @@ namespace ConstexprConstructorRecovery { namespace Lifetime { void f() { - constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} + constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} expected-warning {{not yet bound to a value}} constexpr int m = m; // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}} } diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index 823778f25e167..a091fadfa3094 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -713,7 +713,7 @@ constexpr derp d; struct test { consteval int operator[](int i) const { return {}; } consteval const derp * operator->() const { return &d; } - consteval int f() const { return 12; } // expected-note {{declared here}} + consteval int f() const { return 12; } // expected-note 2{{declared here}} }; constexpr test a; @@ -726,7 +726,8 @@ constexpr int s = a.operator[](1); constexpr int t = a[1]; constexpr int u = a.operator->()->b; constexpr int v = a->b; -constexpr int w = (a.*&test::f)(); +// FIXME: I believe this case should work, but we currently reject. +constexpr int w = (a.*&test::f)(); // expected-error {{cannot take address of consteval function 'f' outside of an immediate invocation}} constexpr int x = a.f(); // Show that we reject when not in an immediate context. @@ -1072,17 +1073,18 @@ struct tester { consteval const char* make_name(const char* name) { return name;} consteval const char* pad(int P) { return "thestring"; } -int bad = 10; // expected-note 5{{declared here}} +int bad = 10; // expected-note 6{{declared here}} tester glob1(make_name("glob1")); tester glob2(make_name("glob2")); constexpr tester cglob(make_name("cglob")); -tester paddedglob(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \ +tester paddedglob(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}} constexpr tester glob3 = { make_name("glob3") }; -constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \ - // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}} +constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \ + // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \ + // expected-note 2{{read of non-const variable 'bad' is not allowed in a constant expression}} auto V = make_name(pad(3)); auto V1 = make_name(pad(bad)); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \ @@ -1092,12 +1094,12 @@ auto V1 = make_name(pad(bad)); // expected-error {{call to consteval function 'G void foo() { static tester loc1(make_name("loc1")); static constexpr tester loc2(make_name("loc2")); - static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \ + static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}} } void bar() { - static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \ + static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}} } } @@ -1131,7 +1133,7 @@ namespace GH65985 { int consteval operator""_foo(unsigned long long V) { return 0; } -int consteval operator""_bar(unsigned long long V); // expected-note 2{{here}} +int consteval operator""_bar(unsigned long long V); // expected-note 3{{here}} int consteval f() { return 0; @@ -1147,7 +1149,10 @@ struct C { // expected-note {{undefined function 'operator""_bar' cannot be used in a constant expression}} \ // expected-error {{in-class initializer for static data member is not a constant expression}} - static constexpr int d = 1_bar; // expected-error {{constexpr variable 'd' must be initialized by a constant expression}} \ + // FIXME: remove duplicate diagnostics + static constexpr int d = 1_bar; // expected-error {{call to consteval function 'GH65985::operator""_bar' is not a constant expression}} \ + // expected-note {{undefined function 'operator""_bar' cannot be used in a constant expression}} \ + // expected-error {{constexpr variable 'd' must be initialized by a constant expression}} \ // expected-note {{undefined function 'operator""_bar' cannot be used in a constant expression}} static const int e = f(); @@ -1162,12 +1167,12 @@ namespace GH66562 { namespace ns { - consteval int foo(int x) { return 1; } + consteval int foo(int x) { return 1; } // expected-note {{declared here}} } template struct T { - static constexpr auto xx = ns::foo(A{}); + static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}} }; } diff --git a/clang/test/SemaCXX/cxx2b-consteval-if.cpp b/clang/test/SemaCXX/cxx2b-consteval-if.cpp index 21413e58169b6..72ba58b676247 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-if.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-if.cpp @@ -18,7 +18,7 @@ constexpr auto h() { constexpr auto i() { if consteval { - if consteval { // expected-warning {{consteval if is always true in this context}} + if consteval { // expected-warning {{consteval if is always true in an immediate context}} return 1; } return 2; diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp index 2daab2c75322c..531a626228733 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp @@ -209,7 +209,7 @@ struct SS { SS::SS(){} // expected-note {{in the default initializer of 'x'}} consteval int f2(int x) { - if (!__builtin_is_constant_evaluated()) side_effect(); // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to true}} + if (!__builtin_is_constant_evaluated()) side_effect(); return x; } struct S2 { @@ -332,14 +332,16 @@ S s(0); // expected-note {{in the default initializer of 'j'}} } namespace GH65985 { -consteval int invalid(); // expected-note {{declared here}} +consteval int invalid(); // expected-note 2{{declared here}} constexpr int escalating(auto) { return invalid(); - // expected-note@-1 {{undefined function 'invalid' cannot be used in a constant expression}} + // expected-note@-1 {{'escalating' is an immediate function because its body contains a call to a consteval function 'invalid' and that call is not a constant expression}} + // expected-note@-2 2{{undefined function 'invalid' cannot be used in a constant expression}} } struct S { - static constexpr int a = escalating(0); // expected-note {{in call to}} - // expected-error@-1 {{constexpr variable 'a' must be initialized by a constant expression}} + static constexpr int a = escalating(0); // expected-note 2{{in call to}} + // expected-error@-1 {{call to immediate function 'GH65985::escalating' is not a constant expression}} + // expected-error@-2 {{constexpr variable 'a' must be initialized by a constant expression}} }; } diff --git a/clang/test/SemaCXX/fixit-tautological-meta-constant.cpp b/clang/test/SemaCXX/fixit-tautological-meta-constant.cpp deleted file mode 100644 index 104dd2e75d25a..0000000000000 --- a/clang/test/SemaCXX/fixit-tautological-meta-constant.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %clang_cc1 -std=c++2b -Wno-unused-value -fdiagnostics-parseable-fixits -fsyntax-only %s 2>&1 | FileCheck %s -namespace std { -constexpr inline bool - is_constant_evaluated() noexcept { - if consteval { return true; } else { return false; } - } -} // namespace std - -constexpr void cexpr() { - if constexpr (std::is_constant_evaluated()) {} - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:16}:"" - // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:6-[[@LINE-2]]:16}:"" - constexpr int a = std::is_constant_evaluated(); - // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}:"" - - if constexpr (const int ce = __builtin_is_constant_evaluated()) {} - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:16}:"" - // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:6-[[@LINE-2]]:16}:"" - constexpr int b = std::is_constant_evaluated(); - // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}:"" -} diff --git a/clang/test/SemaCXX/vartemplate-lambda.cpp b/clang/test/SemaCXX/vartemplate-lambda.cpp index ab187b2c2e7a2..d2b53b53dcd49 100644 --- a/clang/test/SemaCXX/vartemplate-lambda.cpp +++ b/clang/test/SemaCXX/vartemplate-lambda.cpp @@ -12,7 +12,7 @@ template auto v1 = [](int a = T()) { return a; }(); struct S { template - static constexpr T t = [](int f = T(7)){return f;}(); // expected-error{{a lambda expression may not appear inside of a constant expression}} + static constexpr T t = [](int f = T(7)){return f;}(); // expected-error{{constexpr variable 't' must be initialized by a constant expression}} expected-note{{cannot be used in a constant expression}} }; template @@ -21,7 +21,7 @@ int foo2() { fn1(a); (void)v1; (void)v1; // expected-note{{in instantiation of variable template specialization 'v1' requested here}} - (void)S::t; + (void)S::t; // expected-note{{in instantiation of static data member 'S::t' requested here}} return 0; } diff --git a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp index 6ee5f86998eb6..35dc69cccb3a2 100644 --- a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp +++ b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp @@ -7,35 +7,35 @@ constexpr bool is_constant_evaluated() noexcept { } // namespace std constexpr int fn1() { - if constexpr (std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to true in this context}} + if constexpr (std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} return 0; else return 1; } constexpr int fn2() { - if constexpr (!std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to true in this context}} + if constexpr (!std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} return 0; else return 1; } constexpr int fn3() { - if constexpr (std::is_constant_evaluated() == false) // expected-warning {{'std::is_constant_evaluated' will always evaluate to true in this context}} + if constexpr (std::is_constant_evaluated() == false) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} return 0; else return 1; } constexpr int fn4() { - if constexpr (__builtin_is_constant_evaluated() == true) // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to true in this context}} + if constexpr (__builtin_is_constant_evaluated() == true) // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} return 0; else return 1; } constexpr int fn5() { - if constexpr (__builtin_is_constant_evaluated()) // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to true in this context}} + if constexpr (__builtin_is_constant_evaluated()) // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} return 0; else return 1; diff --git a/clang/test/SemaCXX/warn-tautological-meta-constant.cpp b/clang/test/SemaCXX/warn-tautological-meta-constant.cpp deleted file mode 100644 index eef944effd8eb..0000000000000 --- a/clang/test/SemaCXX/warn-tautological-meta-constant.cpp +++ /dev/null @@ -1,262 +0,0 @@ -// RUN: %clang_cc1 -std=c++2b -Wno-unused-value -fsyntax-only -verify %s - -namespace std { -constexpr inline bool - is_constant_evaluated() noexcept { - if consteval { return true; } else { return false; } - } -} // namespace std - -namespace P1938 { - constexpr int f1() { - if constexpr (!std::is_constant_evaluated() && sizeof(int) == 4) { // expected-warning {{always evaluate to true}} - return 0; - } - if (std::is_constant_evaluated()) { - return 42; - } else { - if constexpr (std::is_constant_evaluated()) { // expected-warning {{always evaluate to true}} - return 0; - } - } - return 7; -} - - -consteval int f2() { - if (std::is_constant_evaluated() && f1()) { // expected-warning {{always evaluate to true}} - return 42; - } - return 7; -} - - -int f3() { - if (std::is_constant_evaluated() && f1()) { // expected-warning {{always evaluate to false}} - return 42; - } - return 7; -} -} - -void non_qual() { - int ff = std::is_constant_evaluated(); // expected-warning {{always evaluate to false}} - const int aa = std::is_constant_evaluated(); - constexpr int tt = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - static int bb = std::is_constant_evaluated(); - constexpr int cc = [](){ - if consteval {return 8;} - }(); - auto lamda = []() { - if consteval {return 8;} - else {return 4;} - }; - constexpr auto cexpr_lambda = []() { - if consteval {} - return __builtin_is_constant_evaluated(); - }; - auto lamda_const = []() consteval { - if consteval {return 8;} // expected-warning {{always true}} - else {return 4;} - }; - if consteval { // expected-warning {{always false}} - int b = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - } -} - -constexpr void in_constexpr() { - int aa = std::is_constant_evaluated(); - constexpr int bb = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - const int cc = std::is_constant_evaluated(); - if consteval { - int dd = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - constexpr int ee = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - const int ff = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - } else { - int dd = std::is_constant_evaluated(); // expected-warning {{always evaluate to false}} - constexpr int ee = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - const int ff = std::is_constant_evaluated(); - const int qq = std::is_constant_evaluated() ? dd : 3; - } - - if consteval { - if consteval {} // expected-warning {{always true}} - if !consteval {} // expected-warning {{always false}} - } else { - if consteval {} // expected-warning {{always false}} - if !consteval {} // expected-warning {{always true}} - } - if !consteval { - if consteval {} // expected-warning {{always false}} - if !consteval {} // expected-warning {{always true}} - } else { - if consteval {} // expected-warning {{always true}} - if !consteval {} // expected-warning {{always false}} - } -} - -consteval void in_consteval() { - int aa = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - constexpr int bb = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - const int cc = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - auto lambda = []() { - int a(std::is_constant_evaluated()); // expected-warning {{always evaluate to true}} - constexpr int b = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - const int c = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - }; - if !consteval {} // expected-warning {{always false}} -} - -static_assert(std::is_constant_evaluated()); // expected-warning {{always evaluate to true}} -static_assert(__builtin_is_constant_evaluated()); // expected-warning {{always evaluate to true}} - -template -void templ() { - if constexpr(std::is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - constexpr bool c = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - if consteval {} // expected-warning {{always false}} -} - -template <> void templ() { // expected-warning {{always evaluate to true}} - if constexpr(std::is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - constexpr bool c = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - if consteval {} // expected-warning {{always false}} - templ(); -} - -static_assert([] { - if consteval { - return 0; - } else { - return 1; - } - }() == 0); -constexpr bool b = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}} -constexpr bool c = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} -constinit bool d = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} -int p = __builtin_is_constant_evaluated(); -const int q = __builtin_is_constant_evaluated(); - -template // expected-warning {{always evaluate to true}} -void vvv() { - return; -} - -template<> void vvv() {} -template<> void vvv() {} - -template concept C = __builtin_is_constant_evaluated();// expected-warning {{always evaluate to true}} - -struct Foo { - static constexpr bool ce = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - const static bool nonce = std::is_constant_evaluated(); - bool b = std::is_constant_evaluated(); - - Foo() { - if constexpr(std::is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - bool aa = std::is_constant_evaluated(); // expected-warning {{always evaluate to false}} - static bool bb = std::is_constant_evaluated(); - constexpr bool cc = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - if consteval {} // expected-warning {{always false}} - } - constexpr Foo(int) { - if constexpr(std::is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - bool aa = std::is_constant_evaluated(); - static bool bb = std::is_constant_evaluated(); - constexpr bool cc = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - } - consteval Foo(int *) { - if constexpr(std::is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - bool aa = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - static bool bb = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - constexpr bool cc = std::is_constant_evaluated(); // expected-warning {{always evaluate to true}} - } -}; - -namespace condition { -void f() { - if constexpr (int a = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to false}} - true) {} - if constexpr (const int a = __builtin_is_constant_evaluated(); - true) {} - if constexpr (constexpr int a = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}} - true) {} - if constexpr (;const int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - if constexpr (;constexpr int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - - if (int a = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to false}} - true) {} - if (const int a = __builtin_is_constant_evaluated(); - true) {} - if (constexpr int a = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}} - true) {} - if (;int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to false}} - if (;const int b = __builtin_is_constant_evaluated()) {} - if (;constexpr int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - - if constexpr (__builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - if (__builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to false}} - - if constexpr (__builtin_is_constant_evaluated(); true) {} // expected-warning {{always evaluate to false}} - // False - if constexpr (({__builtin_is_constant_evaluated();2;3;}); true) {} - - if (__builtin_is_constant_evaluated(); true) {} // expected-warning {{always evaluate to false}} - if constexpr (;__builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - if (;__builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to false}} -} - -constexpr void g() { - if constexpr (int a = __builtin_is_constant_evaluated(); - true) {} - if constexpr (const int a = __builtin_is_constant_evaluated(); - true) {} - if constexpr (constexpr int a = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}} - true) {} - if constexpr (;const int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - if constexpr (;constexpr int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - - if (int a = __builtin_is_constant_evaluated(); - true) {} - if (const int a = __builtin_is_constant_evaluated(); - true) {} - if (constexpr int a = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}} - true) {} - if (;int b = __builtin_is_constant_evaluated()) {} - if (;const int b = __builtin_is_constant_evaluated()) {} - if (;constexpr int b = __builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - - if constexpr (__builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - if (__builtin_is_constant_evaluated()) {} - - if constexpr (__builtin_is_constant_evaluated(); true) {} - if constexpr (({__builtin_is_constant_evaluated();2;3;}); true) {} - - if (__builtin_is_constant_evaluated(); true) {} - if constexpr (;__builtin_is_constant_evaluated()) {} // expected-warning {{always evaluate to true}} - if (;__builtin_is_constant_evaluated()) {} -} -} - -namespace Arguments { - int nonc(int n) { return n;} - constexpr int cexpr(int n) { return n;} - consteval int ceval(int n) { return n; } - void f() { - // FIXME: These are tauologically-false; - int a1 = nonc(__builtin_is_constant_evaluated()); - const int b1 = nonc(__builtin_is_constant_evaluated()); - int a2 = cexpr(__builtin_is_constant_evaluated()); - - // ok - const int b2 = cexpr(__builtin_is_constant_evaluated()); - constexpr int c2 = cexpr(__builtin_is_constant_evaluated()); // expected-warning {{always evaluate to true}} - - // FIXME: These are tautologically-true; - int a3 = ceval(__builtin_is_constant_evaluated()); - const int b3 = ceval(__builtin_is_constant_evaluated()); - - // ok - constexpr int c3 = ceval(__builtin_is_constant_evaluated()); // expected-warning {{always evaluate to true}} - } -} diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index c90339e778bc1..e98ebcc9203a4 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -135,21 +135,21 @@ namespace PackInTypeConstraint { namespace BuiltinIsConstantEvaluated { // Check that we do all satisfaction and diagnostic checks in a constant context. - template concept C = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}} + template concept C = __builtin_is_constant_evaluated(); // expected-warning {{always}} static_assert(C); - template concept D = __builtin_is_constant_evaluated() == true; // expected-warning {{always evaluate to true}} + template concept D = __builtin_is_constant_evaluated() == true; // expected-warning {{always}} static_assert(D); - template concept E = __builtin_is_constant_evaluated() == true && // expected-warning {{always evaluate to true}} + template concept E = __builtin_is_constant_evaluated() == true && // expected-warning {{always}} false; // expected-note {{'false' evaluated to false}} static_assert(E); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'E'}} - template concept F = __builtin_is_constant_evaluated() == false; // expected-warning {{always evaluate to true}} + template concept F = __builtin_is_constant_evaluated() == false; // expected-warning {{always}} // expected-note@-1 {{'__builtin_is_constant_evaluated() == false' (1 == 0)}} static_assert(F); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'F'}} - template concept G = __builtin_is_constant_evaluated() && // expected-warning {{always evaluate to true}} + template concept G = __builtin_is_constant_evaluated() && // expected-warning {{always}} false; // expected-note {{'false' evaluated to false}} static_assert(G); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'G'}} } diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp index 85173b23fc649..fdfbbfe4e3a9d 100644 --- a/clang/unittests/Support/TimeProfilerTest.cpp +++ b/clang/unittests/Support/TimeProfilerTest.cpp @@ -188,6 +188,7 @@ Frontend | EvaluateAsBooleanCondition () | | EvaluateAsRValue () | EvaluateAsInitializer (slow_value) +| EvaluateAsConstantExpr () | EvaluateAsConstantExpr () | EvaluateAsRValue () | EvaluateAsInitializer (slow_init_list) diff --git a/libcxx/include/__type_traits/is_constant_evaluated.h b/libcxx/include/__type_traits/is_constant_evaluated.h index 1649762ed6dc5..d7af462486e13 100644 --- a/libcxx/include/__type_traits/is_constant_evaluated.h +++ b/libcxx/include/__type_traits/is_constant_evaluated.h @@ -24,14 +24,7 @@ _LIBCPP_INLINE_VISIBILITY inline constexpr bool is_constant_evaluated() noexcept #endif _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR bool __libcpp_is_constant_evaluated() _NOEXCEPT { -// __builtin_is_constant_evaluated() in this function always evaluates to false in pre-C++11 mode -// because this function is not constexpr-qualified. -// The following macro use clarifies this and avoids warnings from compilers. -#ifndef _LIBCPP_CXX03_LANG return __builtin_is_constant_evaluated(); -#else - return false; -#endif } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp index abb9157df9abb..9291c0aa1f434 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp @@ -93,10 +93,12 @@ constexpr void test_join_view() { } int main(int, char**) { - test_containers, std::deque>(); - test_containers, std::vector>(); - test_containers, std::deque>(); - test_containers, std::vector>(); + if (!std::is_constant_evaluated()) { + test_containers, std::deque>(); + test_containers, std::vector>(); + test_containers, std::deque>(); + test_containers, std::vector>(); + } types::for_each(types::forward_iterator_list{}, [] { test_join_view(); diff --git a/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.verify.cpp b/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.verify.cpp index ef6e6f18ba6b5..f4865ff368079 100644 --- a/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.verify.cpp +++ b/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.verify.cpp @@ -24,7 +24,7 @@ int main(int, char**) #else // expected-error-re@+1 {{{{(static_assert|static assertion)}} failed}} static_assert(!std::is_constant_evaluated(), ""); - // expected-warning-re@-1 0-1 {{'std::is_constant_evaluated' will always evaluate to {{('true' in a manifestly constant-evaluated expression|true in this context)}}}} + // expected-warning@-1 0-1 {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} #endif return 0; }