llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Carlos Galvez (carlosgalvezp) <details> <summary>Changes</summary> The warning has been active for a few releases now, first only in user code, later in system headers, and finally as an error by default. Therefore, we believe it is now time to transition into a hard error, as required by the C++ Standard. The main affected C++ projects have by now fixed the error, or there's a pending patch for review that does it. Fixes #<!-- -->59036 --- Full diff: https://github.com/llvm/llvm-project/pull/102364.diff 8 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+3) - (modified) clang/include/clang/Basic/DiagnosticASTKinds.td (+2-3) - (modified) clang/lib/AST/ExprConstant.cpp (+2-4) - (modified) clang/lib/AST/Interp/Interp.cpp (+2-2) - (modified) clang/test/AST/Interp/cxx11.cpp (+18-9) - (modified) clang/test/SemaCXX/Inputs/enum-constexpr-conversion-system-header.h (+2-1) - (modified) clang/test/SemaCXX/constant-expression-cxx11.cpp (+22-11) - (modified) clang/test/SemaCXX/cxx2a-consteval.cpp (+2-1) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d322da81723a5f..18e20d04298ae2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -49,6 +49,9 @@ C++ Specific Potentially Breaking Changes few users and can be written as ``__is_same(__remove_cv(T), decltype(nullptr))``, which GCC supports as well. +- The warning `-Wenum-constexpr-conversion` has been upgraded into a hard + compiler error that cannot be suppressed, as required by the C++ Standard. + ABI Changes in This Version --------------------------- diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index a024f9b2a9f8c0..af53cf651e51ab 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -410,10 +410,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< +def note_constexpr_unscoped_enum_out_of_range : Note< "integer value %0 is outside the valid range of values [%1, %2] for the " - "enumeration type %3">, DefaultError, ShowInSystemHeader, ShowInSystemMacro, - InGroup<DiagGroup<"enum-constexpr-conversion">>; + "enumeration type %3">; // 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 index d4b9095c7509b3..f2b8161f4a9014 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14406,14 +14406,12 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { if (ED->getNumNegativeBits() && ConstexprVar && (Max.slt(Result.getInt().getSExtValue()) || Min.sgt(Result.getInt().getSExtValue()))) - Info.Ctx.getDiagnostics().Report( - E->getExprLoc(), diag::warn_constexpr_unscoped_enum_out_of_range) + 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 && Max.ult(Result.getInt().getZExtValue())) - Info.Ctx.getDiagnostics().Report( - E->getExprLoc(), diag::warn_constexpr_unscoped_enum_out_of_range) + Info.CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range) << llvm::toString(Result.getInt(), 10) << Min.getZExtValue() << Max.getZExtValue() << ED; } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 0f72b860ddad77..f2440f698b22b2 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -924,12 +924,12 @@ void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, if (ED->getNumNegativeBits() && (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) { const SourceLocation &Loc = S.Current->getLocation(OpPC); - S.report(Loc, diag::warn_constexpr_unscoped_enum_out_of_range) + S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range) << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue() << ED; } else if (!ED->getNumNegativeBits() && Max.ult(Value.getZExtValue())) { const SourceLocation &Loc = S.Current->getLocation(OpPC); - S.report(Loc, diag::warn_constexpr_unscoped_enum_out_of_range) + S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range) << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue() << ED; } diff --git a/clang/test/AST/Interp/cxx11.cpp b/clang/test/AST/Interp/cxx11.cpp index cf2dfba079ef7e..481e3da9289efa 100644 --- a/clang/test/AST/Interp/cxx11.cpp +++ b/clang/test/AST/Interp/cxx11.cpp @@ -93,49 +93,58 @@ 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); - // both-error@-1 {{integer value 8 is outside the valid range of values [-8, 7] for the enumeration type 'E1'}} + // both-error@-1 {{constexpr variable 'x2' must be initialized by a constant expression}} + // both-note@-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 constexpr E2 x3 = static_cast<E2>(-8); - // both-error@-1 {{integer value -8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} + // both-error@-1 {{constexpr variable 'x3' must be initialized by a constant expression}} + // both-note@-2 {{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); - // both-error@-1 {{integer value 8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} + // both-error@-1 {{constexpr variable 'x5' must be initialized by a constant expression}} + // both-note@-2 {{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); - // both-error@-1 {{integer value 2048 is outside the valid range of values [-2048, 2047] for the enumeration type 'E3'}} + // both-error@-1 {{constexpr variable 'x10' must be initialized by a constant expression}} + // both-note@-2 {{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); - // both-error@-1 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'E4'}} + // both-error@-1 {{constexpr variable 'x13' must be initialized by a constant expression}} + // both-note@-2 {{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); - // both-error@-1 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'EEmpty'}} + // both-error@-1 {{constexpr variable 'x16' must be initialized by a constant expression}} + // both-note@-2 {{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); - // both-error@-1 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for the enumeration type 'EMaxInt'}} + // both-error@-1 {{constexpr variable 'x20' must be initialized by a constant expression}} + // both-note@-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 } template<class T, unsigned size> struct Bitfield { - static constexpr T max = static_cast<T>((1 << size) - 1); // #enum + static constexpr T max = static_cast<T>((1 << size) - 1); + // both-error@-1 {{constexpr variable 'max' must be initialized by a constant expression}} + // both-note@-2 {{integer value 15 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} }; void testValueInRangeOfEnumerationValuesViaTemplate() { Bitfield<E2, 3> good; - Bitfield<E2, 4> bad; // both-error@#enum {{integer value 15 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} + Bitfield<E2, 4> bad; // both-note {{in instantiation}} } enum SortOrder { diff --git a/clang/test/SemaCXX/Inputs/enum-constexpr-conversion-system-header.h b/clang/test/SemaCXX/Inputs/enum-constexpr-conversion-system-header.h index 0850f3405eed3a..7d35d5b71d1dfe 100644 --- a/clang/test/SemaCXX/Inputs/enum-constexpr-conversion-system-header.h +++ b/clang/test/SemaCXX/Inputs/enum-constexpr-conversion-system-header.h @@ -10,7 +10,8 @@ enum SystemEnum void testValueInRangeOfEnumerationValuesInSystemHeader() { constexpr SystemEnum x1 = static_cast<SystemEnum>(123); - // expected-error@-1 {{integer value 123 is outside the valid range of values [0, 1] for the enumeration type 'SystemEnum'}} + // expected-error@-1 {{constexpr variable 'x1' must be initialized by a constant expression}} + // expected-note@-2 {{integer value 123 is outside the valid range of values [0, 1] for the enumeration type 'SystemEnum'}} const SystemEnum x2 = static_cast<SystemEnum>(123); // ok, not a constant expression context } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 6df8a4740d6ccc..d888887bd8c6f3 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2460,52 +2460,62 @@ 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 the enumeration type 'E1'}} + // expected-error@-1 {{constexpr variable 'x2' must be initialized by a constant expression}} + // expected-note@-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 constexpr E2 x3 = static_cast<E2>(-8); - // expected-error@-1 {{integer value -8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} + // expected-error@-1 {{constexpr variable 'x3' must be initialized by a constant expression}} + // expected-note@-2 {{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 the enumeration type 'E2'}} + // expected-error@-1 {{constexpr variable 'x5' must be initialized by a constant expression}} + // expected-note@-2 {{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 the enumeration type 'E3'}} + // expected-error@-1 {{constexpr variable 'x10' must be initialized by a constant expression}} + // expected-note@-2 {{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 the enumeration type 'E4'}} + // expected-error@-1 {{constexpr variable 'x13' must be initialized by a constant expression}} + // expected-note@-2 {{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 the enumeration type 'EEmpty'}} + // expected-error@-1 {{constexpr variable 'x16' must be initialized by a constant expression}} + // expected-note@-2 {{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 the enumeration type 'EMaxInt'}} + // expected-error@-1 {{constexpr variable 'x20' must be initialized by a constant expression}} + // expected-note@-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_CAST_TO_SYSTEM_ENUM_OUTSIDE_OF_RANGE; - // expected-error@-1 {{integer value 123 is outside the valid range of values [0, 1] for the enumeration type 'SystemEnum'}} + // expected-error@-1 {{constexpr variable 'system_enum' must be initialized by a constant expression}} + // expected-note@-2 {{integer value 123 is outside the valid range of values [0, 1] for the enumeration type 'SystemEnum'}} } template<class T, unsigned size> struct Bitfield { - static constexpr T max = static_cast<T>((1 << size) - 1); // #enum + static constexpr T max = static_cast<T>((1 << size) - 1); + // cxx11-error@-1 {{constexpr variable 'max' must be initialized by a constant expression}} + // cxx11-note@-2 {{integer value 15 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} }; 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'}} + Bitfield<E2, 4> bad; // cxx11-note {{in instantiation}} } enum SortOrder { @@ -2526,4 +2536,5 @@ 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 the enumeration type 'E2'}} +// expected-error@-1 {{constexpr variable 'GlobalInitCE' must be initialized by a constant expression}} +// expected-note@-2 {{integer value -1 is outside the valid range of values [0, 7] for the enumeration type 'E2'}} diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index ba80e57f814244..6b0609a26c5882 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -920,12 +920,13 @@ 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 the enumeration type 'E'}} +// expected-note@-1 {{integer value -1 is outside the valid range of values [0, 1] for the enumeration type 'E'}} return (int)eParam; } int test() { return testDefaultArgForParam() + testDefaultArgForParam((E)1); + // expected-error@-1 {{call to consteval function 'GH50055::testDefaultArgForParam' is not a constant expression}} } } `````````` </details> https://github.com/llvm/llvm-project/pull/102364 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits