[clang] [clang] Check constexpr int->enum conversions consistently. (PR #143034)
Eli Friedman via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 5 14:00:46 PDT 2025
https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/143034
In 8de51375f12d91675a18d17f262276e65f43fbe0 and related patches, we added some code to avoid triggering -Wenum-constexpr-conversion in some cases. This isn't necessary anymore because -Wenum-constexpr-conversion doesn't exist anymore. And the checks are subtly wrong: they exclude cases where we actually do need to check the conversion. This patch gets rid of the unnecessary checks.
>From 416a1671246edd683da68449c711b89117a4375a Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Wed, 4 Jun 2025 19:40:37 -0700
Subject: [PATCH] [clang] Check constexpr int->enum conversions consistently.
In 8de51375f12d91675a18d17f262276e65f43fbe0 and related patches, we
added some code to avoid triggering -Wenum-constexpr-conversion in some
cases. This isn't necessary anymore because -Wenum-constexpr-conversion
doesn't exist anymore. And the checks are subtly wrong: they exclude
cases where we actually do need to check the conversion. This patch gets
rid of the unnecessary checks.
---
clang/lib/AST/ExprConstant.cpp | 20 +++----------------
.../SemaCXX/constant-expression-cxx11.cpp | 7 +++++++
2 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index ab964e592de80..3417e47e33db6 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15223,21 +15223,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType);
}
- if (Info.Ctx.getLangOpts().CPlusPlus && Info.InConstantContext &&
- Info.EvalMode == EvalInfo::EM_ConstantExpression &&
- DestType->isEnumeralType()) {
-
- bool ConstexprVar = true;
-
- // We know if we are here that we are in a context that we might require
- // a constant expression or a context that requires a constant
- // value. But if we are initializing a value we don't know if it is a
- // constexpr variable or not. We can check the EvaluatingDecl to determine
- // if it constexpr or not. If not then we don't want to emit a diagnostic.
- if (const auto *VD = dyn_cast_or_null<VarDecl>(
- Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
- ConstexprVar = VD->isConstexpr();
-
+ if (Info.Ctx.getLangOpts().CPlusPlus && DestType->isEnumeralType()) {
const EnumType *ET = dyn_cast<EnumType>(DestType.getCanonicalType());
const EnumDecl *ED = ET->getDecl();
// Check that the value is within the range of the enumeration values.
@@ -15257,13 +15243,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
ED->getValueRange(Max, Min);
--Max;
- if (ED->getNumNegativeBits() && ConstexprVar &&
+ if (ED->getNumNegativeBits() &&
(Max.slt(Result.getInt().getSExtValue()) ||
Min.sgt(Result.getInt().getSExtValue())))
Info.CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range)
<< llvm::toString(Result.getInt(), 10) << Min.getSExtValue()
<< Max.getSExtValue() << ED;
- else if (!ED->getNumNegativeBits() && ConstexprVar &&
+ else if (!ED->getNumNegativeBits() &&
Max.ult(Result.getInt().getZExtValue()))
Info.CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range)
<< llvm::toString(Result.getInt(), 10) << Min.getZExtValue()
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 0a135654fab18..10c514be5025f 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2513,6 +2513,9 @@ void testValueInRangeOfEnumerationValues() {
// expected-error at -1 {{constexpr variable 'x2' must be initialized by a constant expression}}
// expected-note at -2 {{integer value 8 is outside the valid range of values [-8, 7] for the enumeration type 'E1'}}
E1 x2b = static_cast<E1>(8); // ok, not a constant expression context
+ static_assert(static_cast<E1>(8));
+ // expected-error at -1 {{static assertion expression is not an integral constant expression}}
+ // expected-note at -2 {{integer value 8 is outside the valid range of values [-8, 7] for the enumeration type 'E1'}}
constexpr E2 x3 = static_cast<E2>(-8);
// expected-error at -1 {{constexpr variable 'x3' must be initialized by a constant expression}}
@@ -2551,6 +2554,10 @@ void testValueInRangeOfEnumerationValues() {
// expected-note at -2 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for the enumeration type 'EMaxInt'}}
const NumberType neg_one = (NumberType) ((NumberType) 0 - (NumberType) 1); // ok, not a constant expression context
+ constexpr NumberType neg_one_constexpr = neg_one;
+ // expected-error at -1 {{constexpr variable 'neg_one_constexpr' must be initialized by a constant expression}}
+ // expected-note at -2 {{initializer of 'neg_one' is not a constant expression}}
+ // expected-note at -4 {{declared here}}
CONSTEXPR_CAST_TO_SYSTEM_ENUM_OUTSIDE_OF_RANGE;
// expected-error at -1 {{constexpr variable 'system_enum' must be initialized by a constant expression}}
More information about the cfe-commits
mailing list