[Clang] Show type in enum out of range diagnostic

When the diagnostic for an out of range enum value is printed, it
currently does not show the actual enum type in question, for example:

    v8/src/base/bit-field.h:43:29: error: integer value 7 is outside the valid range of values [0, 3] for this enumeration type [-Wenum-constexpr-conversion]
      static constexpr T kMax = static_cast<T>(kNumValues - 1);
                                ^

This can make it cumbersome to find the cause for the problem. Add the
enum type to the diagnostic message, to make it easier.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D152788
This commit is contained in:
Dimitry Andric 2023-06-13 10:58:07 +02:00
parent 505829eacf
commit 69d42eef4b
5 changed files with 28 additions and 15 deletions

View File

@ -344,6 +344,9 @@ Improvements to Clang's diagnostics
(`#42992: <https://github.com/llvm/llvm-project/issues/42992>`_)
- Clang now diagnoses unused const-qualified variable template as
"unused variable template" rather than "unused variable".
- When diagnosing a constant expression where an enum without a fixed underlying
type is set to a value outside the range of the enum's values, clang will now
print the name of the enum in question.
Bug Fixes in This Version
-------------------------

View File

@ -395,8 +395,8 @@ def warn_fixedpoint_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
InGroup<DiagGroup<"fixed-point-overflow">>;
def warn_constexpr_unscoped_enum_out_of_range : Warning<
"integer value %0 is outside the valid range of values [%1, %2] for this "
"enumeration type">, DefaultError, InGroup<DiagGroup<"enum-constexpr-conversion">>;
"integer value %0 is outside the valid range of values [%1, %2] for the "
"enumeration type %3">, DefaultError, InGroup<DiagGroup<"enum-constexpr-conversion">>;
// This is a temporary diagnostic, and shall be removed once our
// implementation is complete, and like the preceding constexpr notes belongs

View File

@ -13708,12 +13708,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
Info.Ctx.getDiagnostics().Report(
E->getExprLoc(), diag::warn_constexpr_unscoped_enum_out_of_range)
<< llvm::toString(Result.getInt(), 10) << Min.getSExtValue()
<< Max.getSExtValue();
<< Max.getSExtValue() << ED;
else if (!ED->getNumNegativeBits() && ConstexprVar &&
Max.ult(Result.getInt().getZExtValue()))
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_constexpr_unscoped_enum_out_of_range)
<< llvm::toString(Result.getInt(),10) << Min.getZExtValue() << Max.getZExtValue();
Info.Ctx.getDiagnostics().Report(
E->getExprLoc(), diag::warn_constexpr_unscoped_enum_out_of_range)
<< llvm::toString(Result.getInt(), 10) << Min.getZExtValue()
<< Max.getZExtValue() << ED;
}
}

View File

@ -2440,42 +2440,51 @@ E2 testDefaultArgForParam(E2 e2Param = (E2)-1) { // ok, not a constant expressio
void testValueInRangeOfEnumerationValues() {
constexpr E1 x1 = static_cast<E1>(-8);
constexpr E1 x2 = static_cast<E1>(8);
// expected-error@-1 {{integer value 8 is outside the valid range of values [-8, 7] for this enumeration type}}
// expected-error@-1 {{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
constexpr E2 x3 = static_cast<E2>(-8);
// expected-error@-1 {{integer value -8 is outside the valid range of values [0, 7] for this enumeration type}}
// expected-error@-1 {{integer value -8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}
constexpr E2 x4 = static_cast<E2>(0);
constexpr E2 x5 = static_cast<E2>(8);
// expected-error@-1 {{integer value 8 is outside the valid range of values [0, 7] for this enumeration type}}
// expected-error@-1 {{integer value 8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}
constexpr E3 x6 = static_cast<E3>(-2048);
constexpr E3 x7 = static_cast<E3>(-8);
constexpr E3 x8 = static_cast<E3>(0);
constexpr E3 x9 = static_cast<E3>(8);
constexpr E3 x10 = static_cast<E3>(2048);
// expected-error@-1 {{integer value 2048 is outside the valid range of values [-2048, 2047] for this enumeration type}}
// expected-error@-1 {{integer value 2048 is outside the valid range of values [-2048, 2047] for the enumeration type 'E3'}}
constexpr E4 x11 = static_cast<E4>(0);
constexpr E4 x12 = static_cast<E4>(1);
constexpr E4 x13 = static_cast<E4>(2);
// expected-error@-1 {{integer value 2 is outside the valid range of values [0, 1] for this enumeration type}}
// expected-error@-1 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'E4'}}
constexpr EEmpty x14 = static_cast<EEmpty>(0);
constexpr EEmpty x15 = static_cast<EEmpty>(1);
constexpr EEmpty x16 = static_cast<EEmpty>(2);
// expected-error@-1 {{integer value 2 is outside the valid range of values [0, 1] for this enumeration type}}
// expected-error@-1 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'EEmpty'}}
constexpr EFixed x17 = static_cast<EFixed>(100);
constexpr EScoped x18 = static_cast<EScoped>(100);
constexpr EMaxInt x19 = static_cast<EMaxInt>(__INT_MAX__-1);
constexpr EMaxInt x20 = static_cast<EMaxInt>((long)__INT_MAX__+1);
// expected-error@-1 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for this enumeration type}}
// expected-error@-1 {{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
}
template<class T, unsigned size> struct Bitfield {
static constexpr T max = static_cast<T>((1 << size) - 1); // #enum
};
void testValueInRangeOfEnumerationValuesViaTemplate() {
Bitfield<E2, 3> good;
Bitfield<E2, 4> bad; // cxx11-error@#enum {{integer value 15 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}
}
enum SortOrder {
AscendingOrder,
DescendingOrder
@ -2494,4 +2503,4 @@ void A::f(SortOrder order) {
GH50055::E2 GlobalInitNotCE1 = (GH50055::E2)-1; // ok, not a constant expression context
GH50055::E2 GlobalInitNotCE2 = GH50055::testDefaultArgForParam(); // ok, not a constant expression context
constexpr GH50055::E2 GlobalInitCE = (GH50055::E2)-1;
// expected-error@-1 {{integer value -1 is outside the valid range of values [0, 7] for this enumeration type}}
// expected-error@-1 {{integer value -1 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}

View File

@ -900,7 +900,7 @@ consteval int aConstevalFunction() { // expected-error {{consteval function neve
namespace GH50055 {
enum E {e1=0, e2=1};
consteval int testDefaultArgForParam(E eParam = (E)-1) {
// expected-error@-1 {{integer value -1 is outside the valid range of values [0, 1] for this enumeration type}}
// expected-error@-1 {{integer value -1 is outside the valid range of values [0, 1] for the enumeration type 'E'}}
return (int)eParam;
}