shafik updated this revision to Diff 521507.
shafik added a comment.
- Adding release note
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D150226/new/
https://reviews.llvm.org/D150226
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticASTKinds.td
clang/lib/AST/ExprConstant.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp
clang/test/SemaCXX/cxx2a-consteval.cpp
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}}
}
}
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<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 this enumeration type}}
+ constexpr E1 x2 = static_cast<E1>(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<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 this enumeration type}}
+ constexpr E2 x3 = static_cast<E2>(-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<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 this enumeration type}}
+ constexpr E2 x5 = static_cast<E2>(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<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 this enumeration type}}
+ constexpr E3 x10 = static_cast<E3>(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<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 this enumeration type}}
+ constexpr E4 x13 = static_cast<E4>(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<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 this enumeration type}}
+ constexpr EEmpty x16 = static_cast<EEmpty>(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<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 this enumeration type}}
+ constexpr EMaxInt x20 = static_cast<EMaxInt>((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 <int V, Enum X = static_cast<Enum>(V)>
+constexpr bool test(int) {
+ return true;
+}
+
+template <int V>
+constexpr bool test(...) {
+ return false;
+}
+
+static_assert(test<4>(0) == false, "Should be false");
+}
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<VarDecl>(
- Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
- ConstexprVar = VD->isConstexpr();
-
+ if (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.
@@ -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/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<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
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -55,6 +55,19 @@
-----------------------------------------
- Clang won't search for coroutine_traits in std::experimental namespace any more.
Clang will only search for std::coroutine_traits for coroutines then.
+- Setting a non-fixed enum to a value outside the range of the enumeration values
+ is undefined behavior:
+
+ .. code-block:: c++
+
+ enum E {e1=0, e2=4};
+ constexpr E x = static_cast<E>(8); // Undefined behavior 8 outside the range of values for enumerators
+
+ In a constant expression context this is ill-formed and requires a diagnostic.
+ We have allowed users to turn this diagnostic into a warning using
+ -Wno-error=enum-constexpr-conversion to give users a transition period, see D131307.
+ We are now removing this option and making the diagnostic an error that can not be turned off.
+
ABI Changes in This Version
---------------------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits