diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a65a41357523..4f5e71e0ba80 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -52,10 +52,6 @@ Bug Fixes 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 - of the enumerations values. Fixes - `Issue 50055: `_. Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 6441cd339d91..fb87a75a1241 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3842,11 +3842,6 @@ public: /// -101 1001011 8 unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; } - /// Calculates the [Min,Max) values the enum can store based on the - /// NumPositiveBits and NumNegativeBits. This matters for enums that do not - /// have a fixed underlying type. - void getValueRange(llvm::APInt &Max, llvm::APInt &Min) const; - /// Returns true if this is a C++11 scoped enumeration. bool isScoped() const { return EnumDeclBits.IsScoped; } diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 93e4dfecc49c..5e694c6ad07b 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -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">; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 030792bfc7ca..aaba4345587b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4621,21 +4621,6 @@ SourceRange EnumDecl::getSourceRange() const { return Res; } -void EnumDecl::getValueRange(llvm::APInt &Max, llvm::APInt &Min) const { - unsigned Bitwidth = getASTContext().getIntWidth(getIntegerType()); - unsigned NumNegativeBits = getNumNegativeBits(); - unsigned NumPositiveBits = getNumPositiveBits(); - - if (NumNegativeBits) { - unsigned NumBits = std::max(NumNegativeBits, NumPositiveBits + 1); - Max = llvm::APInt(Bitwidth, 1) << (NumBits - 1); - Min = -Max; - } else { - Max = llvm::APInt(Bitwidth, 1) << NumPositiveBits; - Min = llvm::APInt::getZero(Bitwidth); - } -} - //===----------------------------------------------------------------------===// // RecordDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0f15859fc07a..9d92c848ccb8 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -13519,34 +13519,6 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); } - if (const EnumType *ET = dyn_cast(DestType)) { - const EnumDecl *ED = ET->getDecl(); - // Check that the value is within the range of the enumeration values. - // - // This corressponds to [expr.static.cast]p10 which says: - // A value of integral or enumeration type can be explicitly converted - // to a complete enumeration type ... If the enumeration type does not - // have a fixed underlying type, the value is unchanged if the original - // value is within the range of the enumeration values ([dcl.enum]), and - // otherwise, the behavior is undefined. - // - // This was resolved as part of DR2338 which has CD5 status. - if (!ED->isFixed()) { - llvm::APInt Min; - llvm::APInt Max; - - ED->getValueRange(Max, Min); - - if (ED->getNumNegativeBits() && - (Max.sle(Result.getInt()) || Min.sgt(Result.getInt()))) - CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range) - << Result.getInt() << Min.getSExtValue() << Max.getSExtValue(); - else if (!ED->getNumNegativeBits() && Max.ule(Result.getInt())) - CCEDiag(E, diag::note_constexpr_unscoped_enum_out_of_range) - << Result.getInt() << Min.getZExtValue() << Max.getZExtValue(); - } - } - return Success(HandleIntToIntCast(Info, E, DestType, SrcType, Result.getInt()), E); } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 0b8c200335a0..bf3dd812b9e8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1661,7 +1661,21 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty, End = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2); } else { const EnumDecl *ED = ET->getDecl(); - ED->getValueRange(End, Min); + llvm::Type *LTy = CGF.ConvertTypeForMem(ED->getIntegerType()); + unsigned Bitwidth = LTy->getScalarSizeInBits(); + unsigned NumNegativeBits = ED->getNumNegativeBits(); + unsigned NumPositiveBits = ED->getNumPositiveBits(); + + if (NumNegativeBits) { + unsigned NumBits = std::max(NumNegativeBits, NumPositiveBits + 1); + assert(NumBits <= Bitwidth); + End = llvm::APInt(Bitwidth, 1) << (NumBits - 1); + Min = -End; + } else { + assert(NumPositiveBits <= Bitwidth); + End = llvm::APInt(Bitwidth, 1) << NumPositiveBits; + Min = llvm::APInt::getZero(Bitwidth); + } } return true; } diff --git a/clang/test/Sema/aarch64-sve-intrinsics/acle_sve_imm.cpp b/clang/test/Sema/aarch64-sve-intrinsics/acle_sve_imm.cpp index cfd3b3685a0c..7be8aec449c9 100644 --- a/clang/test/Sema/aarch64-sve-intrinsics/acle_sve_imm.cpp +++ b/clang/test/Sema/aarch64-sve-intrinsics/acle_sve_imm.cpp @@ -206,19 +206,19 @@ void test_range_0_13(svbool_t pg, const void *const_void_ptr) { // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfb(pg, const_void_ptr, svprfop(14)); - // expected-error-re@+1 {{must be a constant integer}} + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfb_vnum(pg, const_void_ptr, 0, svprfop(-1)); // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfd(pg, const_void_ptr, svprfop(14)); - // expected-error-re@+1 {{must be a constant integer}} + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfd_vnum(pg, const_void_ptr, 0, svprfop(-1)); // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfh(pg, const_void_ptr, svprfop(14)); - // expected-error-re@+1 {{must be a constant integer}} + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfh_vnum(pg, const_void_ptr, 0, svprfop(-1)); // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfw(pg, const_void_ptr, svprfop(14)); - // expected-error-re@+1 {{must be a constant integer}} + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 13]}} svprfw_vnum(pg, const_void_ptr, 0, svprfop(-1)); } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index d97c27426b94..e0163fe1f2bb 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2399,50 +2399,3 @@ void local_constexpr_var() { constexpr int a = 0; // expected-note {{address of non-static constexpr variable 'a' may differ on each invocation of the enclosing function; add 'static' to give it a constant address}} constexpr const int *p = &a; // expected-error {{constant expression}} expected-note {{pointer to 'a' is not a constant expression}} } - -namespace GH50055 { -// Enums without fixed underlying type -enum E1 {e11=-4, e12=4}; -enum E2 {e21=0, e22=4}; -enum E3 {e31=-4, e32=1024}; -enum E4 {e41=0}; -// Empty but as-if it had a single enumerator with value 0 -enum EEmpty {}; - -// Enum with fixed underlying type because the underlying type is explicitly specified -enum EFixed : int {efixed1=-4, efixed2=4}; -// Enum with fixed underlying type because it is scoped -enum class EScoped {escoped1=-4, escoped2=4}; - -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, 8) 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, 8) 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, 8) 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, 2048) 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, 2) 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, 2) for this enumeration type}} - - constexpr EFixed x17 = static_cast(100); - constexpr EScoped x18 = static_cast(100); -} -} diff --git a/clang/test/SemaTemplate/temp_arg_enum_printing.cpp b/clang/test/SemaTemplate/temp_arg_enum_printing.cpp index 5a486edd2d30..c5570af82bc8 100644 --- a/clang/test/SemaTemplate/temp_arg_enum_printing.cpp +++ b/clang/test/SemaTemplate/temp_arg_enum_printing.cpp @@ -3,7 +3,7 @@ namespace NamedEnumNS { -enum class NamedEnum +enum NamedEnum { Val0, Val1 @@ -13,9 +13,9 @@ template void foo(); void test() { - // CHECK: template<> void foo() - NamedEnumNS::foo(); - // CHECK: template<> void foo() + // CHECK: template<> void foo() + NamedEnumNS::foo(); + // CHECK: template<> void foo() NamedEnumNS::foo<(NamedEnum)1>(); // CHECK: template<> void foo<(NamedEnumNS::NamedEnum)2>() NamedEnumNS::foo<(NamedEnum)2>(); diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index f3cfe9faea15..466f287c75d9 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -13842,7 +13842,7 @@ and POD class 2338 CD5 Undefined behavior converting to short enums with fixed underlying types - Clang 16 + Clang 12 2339