diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -71,7 +71,11 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 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: `_. - Clang will now check compile-time determinable string literals as format strings. Fixes `Issue 55805: `_. diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -366,9 +366,6 @@ "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_fixedpoint_constant_overflow : Warning< "overflow in expression; result is %0 with type %1">, InGroup>; +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>; // This is a temporary diagnostic, and shall be removed once our // implementation is complete, and like the preceding constexpr notes belongs diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -13534,7 +13534,7 @@ return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); } - if (DestType->isEnumeralType()) { + if (Info.Ctx.getLangOpts().CPlusPlus && DestType->isEnumeralType()) { const EnumType *ET = dyn_cast(DestType.getCanonicalType()); const EnumDecl *ED = ET->getDecl(); // Check that the value is within the range of the enumeration values. @@ -13557,12 +13557,14 @@ 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(); } } diff --git a/clang/test/SemaCXX/MicrosoftCompatibility.cpp b/clang/test/SemaCXX/MicrosoftCompatibility.cpp --- a/clang/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/clang/test/SemaCXX/MicrosoftCompatibility.cpp @@ -239,14 +239,14 @@ //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'}} }; diff --git a/clang/test/SemaCXX/compare.cpp b/clang/test/SemaCXX/compare.cpp --- a/clang/test/SemaCXX/compare.cpp +++ b/clang/test/SemaCXX/compare.cpp @@ -428,11 +428,6 @@ 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; diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2418,37 +2418,37 @@ void testValueInRangeOfEnumerationValues() { constexpr E1 x1 = static_cast(-8); - constexpr E1 x2 = static_cast(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(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(-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(-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(0); - constexpr E2 x5 = static_cast(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(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(-2048); constexpr E3 x7 = static_cast(-8); constexpr E3 x8 = static_cast(0); constexpr E3 x9 = static_cast(8); - constexpr E3 x10 = static_cast(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(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(0); constexpr E4 x12 = static_cast(1); - constexpr E4 x13 = static_cast(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(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(0); constexpr EEmpty x15 = static_cast(1); - constexpr EEmpty x16 = static_cast(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(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(100); constexpr EScoped x18 = static_cast(100); constexpr EMaxInt x19 = static_cast(__INT_MAX__-1); - constexpr EMaxInt x20 = static_cast((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((long)__INT_MAX__+1); + // expected-error@-1 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for this enumeration type}} } }