[clang] 880fa7f - Revert "[clang][SemaCXX] Diagnose tautological uses of consteval if and is_constant_evaluated"
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 27 09:58:13 PDT 2023
Author: Sam McCall
Date: 2023-09-27T18:58:01+02:00
New Revision: 880fa7faa97bad63e403c924263b01fb81783227
URL: https://github.com/llvm/llvm-project/commit/880fa7faa97bad63e403c924263b01fb81783227
DIFF: https://github.com/llvm/llvm-project/commit/880fa7faa97bad63e403c924263b01fb81783227.diff
LOG: Revert "[clang][SemaCXX] Diagnose tautological uses of consteval if and is_constant_evaluated"
This reverts commit 491b2810fb7fe5f080fa9c4f5945ed0a6909dc92.
This change broke valid code and generated incorrect diagnostics, see
https://reviews.llvm.org/D155064
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticASTKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ExprConstant.cpp
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Parse/ParseStmt.cpp
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaLambda.cpp
clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/AST/Interp/builtins.cpp
clang/test/AST/Interp/if.cpp
clang/test/AST/Interp/literals.cpp
clang/test/CXX/expr/expr.const/p2-0x.cpp
clang/test/CXX/expr/expr.const/p6-2a.cpp
clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp
clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p4.cpp
clang/test/Parser/pragma-fenv_access.c
clang/test/SemaCXX/constant-conversion.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp
clang/test/SemaCXX/cxx2a-consteval.cpp
clang/test/SemaCXX/cxx2b-consteval-if.cpp
clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
clang/test/SemaCXX/vartemplate-lambda.cpp
clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp
clang/test/SemaTemplate/concepts.cpp
clang/unittests/Support/TimeProfilerTest.cpp
libcxx/include/__type_traits/is_constant_evaluated.h
libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp
libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.verify.cpp
Removed:
clang/test/SemaCXX/fixit-tautological-meta-constant.cpp
clang/test/SemaCXX/warn-tautological-meta-constant.cpp
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fb52b90ae4a3cb9..68172d5317a13ba 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: <https://github.com/llvm/llvm-project/issues/54678>`_).
-- Clang now diagnoses wider cases of tautological use of consteval if or
- ``std::is_constant_evaluated``. This also suppresses some false positives.
- (`#43760: <https://github.com/llvm/llvm-project/issues/43760>`_)
- (`#51567: <https://github.com/llvm/llvm-project/issues/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 1abb0b89af9f1c1..d2656310e79c9b8 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<DiagGroup<"constant-evaluated">>;
+
// 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 3f30681a378e24f..f4eb02fd9570c2f 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<DiagGroup<"redundant-consteval-if">>;
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<PotentiallyEvaluatedExpression>;
-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<DiagGroup<"constant-evaluated">>;
def warn_unused_result : Warning<
"ignoring return value of function declared with %0 attribute">,
InGroup<UnusedResult>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index ae3c265f40a2c76..f599b8b98d031fb 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 e4366170005a044..712db0a3dd895d5 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<ExpressionEvaluationContextRecord, 8> 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<ConstantExpr *, 4> FailedImmediateInvocations;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 310debe327017cd..fea06b97259fe31 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 f5b4107cc32c1f0..748b9d53c9f5b33 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<VarDecl>(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<VarDecl>(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 e5a278c598cfb63..5a6b5efbf6c1223 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<FieldDecl>(D);
- bool IsConstexpr = false;
- if (const auto *VD = dyn_cast_if_present<VarDecl>(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 0e69be6bcb3ce4e..74664c34abdbd89 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 d20d400e3076e9f..99b4931004546c1 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 75c689f21efa2b1..2531147c23196ae 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 4d4bedf75963ac7..6a3b5fa61d59456 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<VarDecl>(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<UnaryOperator>(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 30e4af16944ab5f..7d92e93188610c0 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 3d5ecfc2eb2562a..0091e0ecf6f3986 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<VarDecl>(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 305b43743774788..92496b03ecabe54 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<CallExpr>(Call.get())) {
+ if (const auto *CE = dyn_cast<CallExpr>(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<VarDecl>(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 bd2c3c2f45d4c0c..1702ddb3ee0fbf0 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 c20d0c50b09e1fe..10adfbc406dfbb5 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<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,
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c4f1c4e06ac83b3..fa839e9b71a3cf9 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 90bd290f1d6a4ba..5e2ffe50f374057 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 3d1ed7b7ffe7623..86ae8de6f73ebb7 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 67de4ef6dae2afa..aabc909b3328e48 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 596df90243b1e20..e3cd057baba75f5 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 7bcf6fdc3d99790..a937474d53b221c 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 8b30b5eefd85fc2..db40bd5d1420ef3 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 at -2 {{constexpr variable cannot have non-literal type}}
// expected-note at -3 {{lambda closure types are non-literal types before C++17}}
-// expected-error at -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 fd2deee249016c2..8d43be6fc904781 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 a626453344ee6e8..76256cff1b49b54 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 at +2{{implicit conversion from 'const int' to 'const float' changes value from 2147483632 to 2147483648}}
+//expected-warning at +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 884166c419764b7..9be8b139e79e228 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 N>
-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 <int a, int b>
-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 8e6af7811a30b39..89d1b3ea6de05ea 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 823778f25e16720..a091fadfa3094bd 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 <class A>
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 21413e58169b665..72ba58b676247f8 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 2daab2c75322c40..531a62622873357 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 at -1 {{undefined function 'invalid' cannot be used in a constant expression}}
+ // expected-note at -1 {{'escalating<int>' 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 at -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 at -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 at -1 {{call to immediate function 'GH65985::escalating<int>' is not a constant expression}}
+ // expected-error at -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 104dd2e75d25ab4..000000000000000
--- 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 ab187b2c2e7a2b3..d2b53b53dcd4922 100644
--- a/clang/test/SemaCXX/vartemplate-lambda.cpp
+++ b/clang/test/SemaCXX/vartemplate-lambda.cpp
@@ -12,7 +12,7 @@ template<typename T> auto v1 = [](int a = T()) { return a; }();
struct S {
template<class T>
- 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<int>' must be initialized by a constant expression}} expected-note{{cannot be used in a constant expression}}
};
template <typename X>
@@ -21,7 +21,7 @@ int foo2() {
fn1<char>(a);
(void)v1<int>;
(void)v1<int *>; // expected-note{{in instantiation of variable template specialization 'v1' requested here}}
- (void)S::t<int>;
+ (void)S::t<int>; // expected-note{{in instantiation of static data member 'S::t<int>' 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 6ee5f86998eb606..35dc69cccb3a2e2 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 eef944effd8eb8c..000000000000000
--- 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 <bool b>
-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<std::is_constant_evaluated()>() { // 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<false>();
-}
-
-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 <bool c = std::is_constant_evaluated()> // expected-warning {{always evaluate to true}}
-void vvv() {
- return;
-}
-
-template<> void vvv<true>() {}
-template<> void vvv<false>() {}
-
-template<typename T> 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 c90339e778bc182..e98ebcc9203a430 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<typename T> concept C = __builtin_is_constant_evaluated(); // expected-warning {{always evaluate to true}}
+ template<typename T> concept C = __builtin_is_constant_evaluated(); // expected-warning {{always}}
static_assert(C<int>);
- template<typename T> concept D = __builtin_is_constant_evaluated() == true; // expected-warning {{always evaluate to true}}
+ template<typename T> concept D = __builtin_is_constant_evaluated() == true; // expected-warning {{always}}
static_assert(D<int>);
- template<typename T> concept E = __builtin_is_constant_evaluated() == true && // expected-warning {{always evaluate to true}}
+ template<typename T> concept E = __builtin_is_constant_evaluated() == true && // expected-warning {{always}}
false; // expected-note {{'false' evaluated to false}}
static_assert(E<int>); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'E'}}
- template<typename T> concept F = __builtin_is_constant_evaluated() == false; // expected-warning {{always evaluate to true}}
+ template<typename T> concept F = __builtin_is_constant_evaluated() == false; // expected-warning {{always}}
// expected-note at -1 {{'__builtin_is_constant_evaluated() == false' (1 == 0)}}
static_assert(F<int>); // expected-error {{failed}} expected-note {{because 'int' does not satisfy 'F'}}
- template<typename T> concept G = __builtin_is_constant_evaluated() && // expected-warning {{always evaluate to true}}
+ template<typename T> concept G = __builtin_is_constant_evaluated() && // expected-warning {{always}}
false; // expected-note {{'false' evaluated to false}}
static_assert(G<int>); // 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 85173b23fc6497e..fdfbbfe4e3a9dff 100644
--- a/clang/unittests/Support/TimeProfilerTest.cpp
+++ b/clang/unittests/Support/TimeProfilerTest.cpp
@@ -188,6 +188,7 @@ Frontend
| EvaluateAsBooleanCondition (<test.cc:8:21, col:25>)
| | EvaluateAsRValue (<test.cc:8:21, col:25>)
| EvaluateAsInitializer (slow_value)
+| EvaluateAsConstantExpr (<test.cc:17:33, col:59>)
| EvaluateAsConstantExpr (<test.cc:18:11, col:37>)
| EvaluateAsRValue (<test.cc:22:14, line:23:58>)
| 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 1649762ed6dc598..d7af462486e1316 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 abb9157df9abbbb..9291c0aa1f43404 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<int>, std::deque<int>>();
- test_containers<std::deque<int>, std::vector<int>>();
- test_containers<std::vector<int>, std::deque<int>>();
- test_containers<std::vector<int>, std::vector<int>>();
+ if (!std::is_constant_evaluated()) {
+ test_containers<std::deque<int>, std::deque<int>>();
+ test_containers<std::deque<int>, std::vector<int>>();
+ test_containers<std::vector<int>, std::deque<int>>();
+ test_containers<std::vector<int>, std::vector<int>>();
+ }
types::for_each(types::forward_iterator_list<int*>{}, []<class Iter> {
test_join_view<Iter, Iter>();
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 ef6e6f18ba6b5ca..f4865ff368079be 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 at +1 {{{{(static_assert|static assertion)}} failed}}
static_assert(!std::is_constant_evaluated(), "");
- // expected-warning-re at -1 0-1 {{'std::is_constant_evaluated' will always evaluate to {{('true' in a manifestly constant-evaluated expression|true in this context)}}}}
+ // expected-warning at -1 0-1 {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}}
#endif
return 0;
}
More information about the cfe-commits
mailing list