https://github.com/keinflue updated https://github.com/llvm/llvm-project/pull/106841
>From 533f32f7be161bfec45ee93cef3fbd78fc55e721 Mon Sep 17 00:00:00 2001 From: keinflue <80230456+keinf...@users.noreply.github.com> Date: Sat, 31 Aug 2024 11:27:57 +0200 Subject: [PATCH] [clang] fix range of empty enumeration without fixed underlying type In C++ enumerations without fixed underlying type which have either no enumerator or only enumerators with value 0 have a value set containing only 0, instead of 0 and 1. See [decl.enum]/8. Fixes #106815 --- clang/lib/Sema/SemaChecking.cpp | 1 - clang/lib/Sema/SemaDecl.cpp | 11 +---------- clang/test/AST/ByteCode/cxx11.cpp | 8 ++++++-- clang/test/CodeGenCXX/pr12251.cpp | 4 ++-- clang/test/SemaCXX/constant-expression-cxx11.cpp | 8 ++++++-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b021e27209cf1b..5a092279ea12b0 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10284,7 +10284,6 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, // inconsistency by storing this as a signed type. if (S.getLangOpts().CPlusPlus11 && !BitfieldEnumDecl->getIntegerTypeSourceInfo() && - BitfieldEnumDecl->getNumPositiveBits() > 0 && BitfieldEnumDecl->getNumNegativeBits() == 0) { S.Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield) << BitfieldEnumDecl; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6327ae9b99aa4c..3efd01673f40fa 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19903,23 +19903,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, // Keep track of the size of positive and negative values. if (InitVal.isUnsigned() || InitVal.isNonNegative()) { - // If the enumerator is zero that should still be counted as a positive - // bit since we need a bit to store the value zero. unsigned ActiveBits = InitVal.getActiveBits(); - NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u}); + NumPositiveBits = std::max(NumPositiveBits, ActiveBits); } else { NumNegativeBits = std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits()); } } - // If we have an empty set of enumerators we still need one bit. - // From [dcl.enum]p8 - // If the enumerator-list is empty, the values of the enumeration are as if - // the enumeration had a single enumerator with value 0 - if (!NumPositiveBits && !NumNegativeBits) - NumPositiveBits = 1; - // Figure out the type that should be used for this enum. QualType BestType; unsigned BestWidth; diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp index 481e3da9289efa..ead47faffcf7a6 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -115,15 +115,19 @@ void testValueInRangeOfEnumerationValues() { constexpr E4 x11 = static_cast<E4>(0); constexpr E4 x12 = static_cast<E4>(1); + // both-error@-1 {{constexpr variable 'x12' must be initialized by a constant expression}} + // both-note@-2 {{integer value 1 is outside the valid range of values [0, 0] for the enumeration type 'E4'}} constexpr E4 x13 = static_cast<E4>(2); // 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'}} + // both-note@-2 {{integer value 2 is outside the valid range of values [0, 0] for the enumeration type 'E4'}} constexpr EEmpty x14 = static_cast<EEmpty>(0); constexpr EEmpty x15 = static_cast<EEmpty>(1); + // both-error@-1 {{constexpr variable 'x15' must be initialized by a constant expression}} + // both-note@-2 {{integer value 1 is outside the valid range of values [0, 0] for the enumeration type 'EEmpty'}} constexpr EEmpty x16 = static_cast<EEmpty>(2); // 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'}} + // both-note@-2 {{integer value 2 is outside the valid range of values [0, 0] for the enumeration type 'EEmpty'}} constexpr EFixed x17 = static_cast<EFixed>(100); constexpr EScoped x18 = static_cast<EScoped>(100); diff --git a/clang/test/CodeGenCXX/pr12251.cpp b/clang/test/CodeGenCXX/pr12251.cpp index bd5c85b83f2caf..5d0afb639d668d 100644 --- a/clang/test/CodeGenCXX/pr12251.cpp +++ b/clang/test/CodeGenCXX/pr12251.cpp @@ -18,14 +18,14 @@ e1 g1(e1 *x) { return *x; } // CHECK-LABEL: define{{.*}} i32 @_Z2g1P2e1 -// CHECK: ret i32 %0 +// CHECK: ret i32 0 enum e2 { e2_a = 0 }; e2 g2(e2 *x) { return *x; } // CHECK-LABEL: define{{.*}} i32 @_Z2g2P2e2 -// CHECK: ret i32 %0 +// CHECK: ret i32 0 enum e3 { e3_a = 16 }; e3 g3(e3 *x) { diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 44ef540f41fa8c..2c64f603029b85 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2485,15 +2485,19 @@ void testValueInRangeOfEnumerationValues() { constexpr E4 x11 = static_cast<E4>(0); constexpr E4 x12 = static_cast<E4>(1); + // expected-error@-1 {{constexpr variable 'x12' must be initialized by a constant expression}} + // expected-note@-2 {{integer value 1 is outside the valid range of values [0, 0] for the enumeration type 'E4'}} constexpr E4 x13 = static_cast<E4>(2); // 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'}} + // expected-note@-2 {{integer value 2 is outside the valid range of values [0, 0] for the enumeration type 'E4'}} constexpr EEmpty x14 = static_cast<EEmpty>(0); constexpr EEmpty x15 = static_cast<EEmpty>(1); + // expected-error@-1 {{constexpr variable 'x15' must be initialized by a constant expression}} + // expected-note@-2 {{integer value 1 is outside the valid range of values [0, 0] for the enumeration type 'EEmpty'}} constexpr EEmpty x16 = static_cast<EEmpty>(2); // 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'}} + // expected-note@-2 {{integer value 2 is outside the valid range of values [0, 0] for the enumeration type 'EEmpty'}} constexpr EFixed x17 = static_cast<EFixed>(100); constexpr EScoped x18 = static_cast<EScoped>(100); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits