-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[Clang] treat fixed-underlying enum constants as the enumerated type in C23 to follow the spec #172211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…in C23 to follow the spec
|
@llvm/pr-subscribers-clang Author: Oleksandr T. (a-tarasyuk) ChangesFixes #172118 This patch resolves an issue where C23 fixed-underlying enum constants were incorrectly treated as the underlying integer type instead of the enumeration type. According to C23 > The enumeration member type of an enumerated type with a fixed underlying type is the same as the type itself. Full diff: https://github.com/llvm/llvm-project/pull/172211.diff 4 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index feaf92ad4415f..66ec693e69826 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -534,6 +534,7 @@ Bug Fixes in This Version
- Fixed false-positive shadow diagnostics for lambdas in explicit object member functions. (#GH163731)
- Fix an assertion failure when a ``target_clones`` attribute is only on the
forward declaration of a multiversioned function. (#GH165517) (#GH129483)
+- Clang now treats enumeration constants of fixed-underlying enums as the enumerated type. (#GH172118)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index db711ee08c8da..7dbce349d48af 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -20814,10 +20814,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
NewSign = true;
} else if (ECD->getType() == BestType) {
// Already the right type!
- if (getLangOpts().CPlusPlus)
+ if (getLangOpts().CPlusPlus || (getLangOpts().C23 && Enum->isFixed()))
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
// enumeration.
+ // C23 6.7.2.2p15: For an enumerated type with fixed underlying type,
+ // the enumeration member type is the enumerated type.
ECD->setType(EnumType);
continue;
} else {
@@ -20837,10 +20839,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
ECD->setInitExpr(ImplicitCastExpr::Create(
Context, NewTy, CK_IntegralCast, ECD->getInitExpr(),
/*base paths*/ nullptr, VK_PRValue, FPOptionsOverride()));
- if (getLangOpts().CPlusPlus)
+ if (getLangOpts().CPlusPlus || (getLangOpts().C23 && Enum->isFixed()))
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
// enumeration.
+ // C23 6.7.2.2p15: For an enumerated type with fixed underlying type, the
+ // enumeration member type is the enumerated type.
ECD->setType(EnumType);
else
ECD->setType(NewTy);
diff --git a/clang/test/Sema/c23-switch.c b/clang/test/Sema/c23-switch.c
new file mode 100644
index 0000000000000..32be0bb8e6a48
--- /dev/null
+++ b/clang/test/Sema/c23-switch.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify -Wswitch %s
+
+typedef enum : long { E0 } E;
+void test1(E e) {
+ auto v = E0;
+ switch (v) { } // expected-warning {{enumeration value 'E0' not handled in switch}}
+}
+
+void test2(E e) {
+ __auto_type v = E0;
+ switch (v) { } // expected-warning {{enumeration value 'E0' not handled in switch}}
+}
+
+void test3(_Bool b, E e) {
+ __auto_type v = E0;
+ if (b) {
+ v = e;
+ }
+ switch (v) { } // expected-warning {{enumeration value 'E0' not handled in switch}}
+}
diff --git a/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp b/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp
index 5eaa3eb2d85e3..71367cfc7ec4d 100644
--- a/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp
+++ b/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp
@@ -377,9 +377,9 @@ void write_high_constantA(S_A *s) {
void write_high_constantB(S_B *s) {
s->field1 = ENUM_CLASS_REF(B, B_d);
// cpp-warning@-1 {{implicit truncation from 'B' to bit-field changes value from 3 to 1}}
- // c-warning@-2 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
+ // c-warning@-2 {{implicit truncation from 'enum B' to bit-field changes value from 3 to -1}}
s->field2 = ENUM_CLASS_REF(B, B_d);
- // c-warning@-1 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
+ // c-warning@-1 {{implicit truncation from 'enum B' to bit-field changes value from 3 to -1}}
s->field3 = ENUM_CLASS_REF(B, B_d);
s->field4 = (unsigned)ENUM_CLASS_REF(B, B_d);
// expected-warning@-1 {{implicit truncation from 'unsigned int' to bit-field changes value from 3 to 1}}
@@ -396,7 +396,7 @@ void write_high_constantB(S_B *s) {
void write_high_constantC(S_C *s) {
s->field1 = ENUM_CLASS_REF(C, C_d);
// cpp-warning@-1 {{implicit truncation from 'C' to bit-field changes value from 3 to 1}}
- // c-warning@-2 {{implicit truncation from 'unsigned int' to bit-field changes value from 3 to 1}}
+ // c-warning@-2 {{implicit truncation from 'enum C' to bit-field changes value from 3 to 1}}
s->field2 = ENUM_CLASS_REF(C, C_d);
s->field3 = ENUM_CLASS_REF(C, C_d);
s->field4 = (unsigned)ENUM_CLASS_REF(C, C_d);
|
Fznamznon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, thanks for the patch, does that also fix #147370 ? I think we could reuse some test cases from there as well.
Fixes #172118
This patch resolves an issue where C23 fixed-underlying enum constants were incorrectly treated as the underlying integer type instead of the enumeration type.
According to C23
6.7.2.2p15: