[Clang] Allow downgrading to a warning the diagnostic for setting a non fixed enum to a value outside the range of the enumeration values

In D130058 we diagnose the undefined behavior of setting the value outside the
range of the enumerations values for an enum without a fixed underlying type.

Based on feedback we will provide users to the ability to downgrade this
diagnostic to a waring to allow for a transition period. We expect to turn this
diagnostic to an error in the next release.

Differential Revision: https://reviews.llvm.org/D131307
This commit is contained in:
Shafik Yaghmour 2022-08-08 15:17:34 -07:00
parent 67c06c4731
commit cc104113dd
6 changed files with 31 additions and 30 deletions

View File

@ -71,7 +71,11 @@ Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Clang will now correctly diagnose as ill-formed a constant expression where an
enum without a fixed underlying type is set to a value outside the range of
the enumeration's values. Fixes
the enumeration's values. Due to the extended period of time this bug was
present in major C++ implementations (including Clang), this error has the
ability to be downgraded into a warning (via: -Wno-error=enum-constexpr-conversion)
to provide a transition period for users. This diagnostic is expected to turn
into an error-only diagnostic in the next Clang release. Fixes
`Issue 50055: <https://github.com/llvm/llvm-project/issues/50055>`_.
- Clang will now check compile-time determinable string literals as format strings.
Fixes `Issue 55805: <https://github.com/llvm/llvm-project/issues/55805>`_.

View File

@ -366,9 +366,6 @@ def note_constexpr_unsupported_layout : Note<
"type %0 has unexpected layout">;
def note_constexpr_unsupported_flexible_array : Note<
"flexible array initialization is not yet supported">;
def note_constexpr_unscoped_enum_out_of_range : Note<
"integer value %0 is outside the valid range of values [%1, %2] for this "
"enumeration type">;
def err_experimental_clang_interp_failed : Error<
"the experimental clang interpreter failed to evaluate an expression">;
@ -378,6 +375,9 @@ def warn_integer_constant_overflow : Warning<
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">>;
// This is a temporary diagnostic, and shall be removed once our
// implementation is complete, and like the preceding constexpr notes belongs

View File

@ -13534,7 +13534,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType);
}
if (DestType->isEnumeralType()) {
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.
@ -13557,12 +13557,14 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (ED->getNumNegativeBits() &&
(Max.slt(Result.getInt().getSExtValue()) ||
Min.sgt(Result.getInt().getSExtValue())))
CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range)
<< Result.getInt() << Min.getSExtValue() << Max.getSExtValue();
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_constexpr_unscoped_enum_out_of_range)
<< llvm::toString(Result.getInt(),10) << Min.getSExtValue() << Max.getSExtValue();
else if (!ED->getNumNegativeBits() &&
Max.ult(Result.getInt().getZExtValue()))
CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range)
<< Result.getInt() << 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();
}
}

View File

@ -239,14 +239,14 @@ template void function_missing_typename<D>(const D::Type param);
//MSVC allows forward enum declaration
enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
ENUM *var = 0;
ENUM var2 = (ENUM)3;
ENUM var2 = (ENUM)0;
enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}}
enum ENUM1 { kA };
enum ENUM1; // This way round is fine.
enum ENUM2 {
ENUM2_a = (enum ENUM2) 4,
ENUM2_a = (enum ENUM2) 0,
ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
};

View File

@ -428,11 +428,6 @@ namespace templates {
namespace tautological_enum {
enum E { a, b, c } e;
// FIXME: We should warn about constructing this out-of-range numeration value.
const E invalid = (E)-1;
// ... but we should not warn about comparing against it.
bool x = e == invalid;
// We should not warn about relational comparisons for enumerators, even if
// they're tautological.
bool y = e >= a && e <= b;

View File

@ -2418,37 +2418,37 @@ enum EMaxInt {emaxint1=-1, emaxint2=__INT_MAX__};
void testValueInRangeOfEnumerationValues() {
constexpr E1 x1 = static_cast<E1>(-8);
constexpr E1 x2 = static_cast<E1>(8); // expected-error {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value 8 is outside the valid range of values [-8, 7] for this enumeration type}}
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}}
constexpr E2 x3 = static_cast<E2>(-8); // expected-error {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value -8 is outside the valid range of values [0, 7] for this enumeration type}}
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}}
constexpr E2 x4 = static_cast<E2>(0);
constexpr E2 x5 = static_cast<E2>(8); // expected-error {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value 8 is outside the valid range of values [0, 7] for this enumeration type}}
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}}
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 {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value 2048 is outside the valid range of values [-2048, 2047] for this enumeration type}}
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}}
constexpr E4 x11 = static_cast<E4>(0);
constexpr E4 x12 = static_cast<E4>(1);
constexpr E4 x13 = static_cast<E4>(2); // expected-error {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value 2 is outside the valid range of values [0, 1] for this enumeration type}}
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}}
constexpr EEmpty x14 = static_cast<EEmpty>(0);
constexpr EEmpty x15 = static_cast<EEmpty>(1);
constexpr EEmpty x16 = static_cast<EEmpty>(2); // expected-error {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value 2 is outside the valid range of values [0, 1] for this enumeration type}}
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}}
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 {{must be initialized by a constant expression}}
// expected-note@-1 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for this enumeration type}}
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}}
}
}