Index: clang/include/clang/Basic/DiagnosticASTKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticASTKinds.td +++ clang/include/clang/Basic/DiagnosticASTKinds.td @@ -385,6 +385,9 @@ "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">; @@ -394,9 +397,6 @@ 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 Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -13656,21 +13656,7 @@ return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); } - if (Info.Ctx.getLangOpts().CPlusPlus && Info.InConstantContext && - Info.EvalMode == EvalInfo::EM_ConstantExpression && - DestType->isEnumeralType()) { - - bool ConstexprVar = true; - - // We know if we are here that we are in a context that we might require - // a constant expression or a context that requires a constant - // value. But if we are initializing a value we don't know if it is a - // constexpr variable or not. We can check the EvaluatingDecl to determine - // if it constexpr or not. If not then we don't want to emit a diagnostic. - if (const auto *VD = dyn_cast_or_null( - Info.EvaluatingDecl.dyn_cast())) - ConstexprVar = VD->isConstexpr(); - + if (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. @@ -13690,18 +13676,15 @@ ED->getValueRange(Max, Min); --Max; - if (ED->getNumNegativeBits() && ConstexprVar && + if (ED->getNumNegativeBits() && (Max.slt(Result.getInt().getSExtValue()) || Min.sgt(Result.getInt().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() && ConstexprVar && + CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range) + << Result.getInt() << Min.getSExtValue() << Max.getSExtValue(); + else if (!ED->getNumNegativeBits() && 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(); + CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range) + << Result.getInt() << Min.getZExtValue() << Max.getZExtValue(); } } Index: clang/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx11.cpp +++ clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2439,39 +2439,39 @@ void testValueInRangeOfEnumerationValues() { constexpr E1 x1 = static_cast(-8); - 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 E1 x2 = static_cast(8); // expected-error {{constexpr variable 'x2' 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}} E1 x2b = static_cast(8); // ok, not a constant expression context - 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 x3 = static_cast(-8); // expected-error {{constexpr variable 'x3' 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 x4 = static_cast(0); - 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 E2 x5 = static_cast(8); // expected-error {{constexpr variable 'x5' 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 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@-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 {{constexpr variable 'x10' 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 E4 x11 = static_cast(0); constexpr E4 x12 = static_cast(1); - 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 E4 x13 = static_cast(2); // expected-error {{constexpr variable 'x13' 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 x14 = static_cast(0); constexpr EEmpty x15 = static_cast(1); - 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 EEmpty x16 = static_cast(2); // expected-error {{constexpr variable 'x16' 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 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@-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 {{constexpr variable 'x20' 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}} const NumberType neg_one = (NumberType) ((NumberType) 0 - (NumberType) 1); // ok, not a constant expression context } @@ -2493,5 +2493,21 @@ 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}} +constexpr GH50055::E2 GlobalInitCE = (GH50055::E2)-1; // expected-error {{constexpr variable 'GlobalInitCE' must be initialized by a constant expression}} +// expected-note@-1 {{integer value -1 is outside the valid range of values [0, 7] for this enumeration type}} + +namespace GH57176 { +enum Enum { A, B, C }; + +template (V)> +constexpr bool test(int) { + return true; +} + +template +constexpr bool test(...) { + return false; +} + +static_assert(test<4>(0) == false, "Should be false"); +} Index: clang/test/SemaCXX/cxx2a-consteval.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-consteval.cpp +++ clang/test/SemaCXX/cxx2a-consteval.cpp @@ -900,12 +900,12 @@ 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-note@-1 {{integer value -1 is outside the valid range of values [0, 1] for this enumeration type}} return (int)eParam; } int test() { - return testDefaultArgForParam() + testDefaultArgForParam((E)1); + return testDefaultArgForParam() + testDefaultArgForParam((E)1); // expected-error {{call to consteval function 'GH50055::testDefaultArgForParam' is not a constant expression}} } }