forked from OSchip/llvm-project
[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:
parent
67c06c4731
commit
cc104113dd
|
@ -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>`_.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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'}}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue