-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][C23] Claim N3030 Enhancements to Enumerations supported #107260
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
Conversation
Clang already implemented functionality as an extension.
@llvm/pr-subscribers-clang Author: Mariya Podchishchaeva (Fznamznon) ChangesClang already implemented functionality as an extension. Full diff: https://github.com/llvm/llvm-project/pull/107260.diff 5 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 0b8ab4bf092509..a1070aceea7572 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -113,9 +113,12 @@ def ext_cxx11_enum_fixed_underlying_type : Extension<
def ext_ms_c_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
InGroup<MicrosoftFixedEnum>;
-def ext_clang_c_enum_fixed_underlying_type : Extension<
- "enumeration types with a fixed underlying type are a Clang extension">,
- InGroup<DiagGroup<"fixed-enum-extension">>;
+def ext_c23_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a C23 extension">,
+ InGroup<C23>;
+def warn_c17_compat_enum_fixed_underlying_type : Warning<
+ "enumeration types with a fixed underlying type are incompatible with C standards before C23">,
+ DefaultIgnore, InGroup<CPre23Compat>;
def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
"enumeration types with a fixed underlying type are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 78d729c5ef7d8a..b563f875c663c6 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -5413,18 +5413,20 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());
- if (!getLangOpts().ObjC && !getLangOpts().C23) {
+ if (!getLangOpts().ObjC) {
if (getLangOpts().CPlusPlus11)
Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
<< BaseRange;
else if (getLangOpts().CPlusPlus)
Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
<< BaseRange;
- else if (getLangOpts().MicrosoftExt)
+ else if (getLangOpts().MicrosoftExt && !getLangOpts().C23)
Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
<< BaseRange;
else
- Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)
+ Diag(ColonLoc, (getLangOpts().C23)
+ ? diag::warn_c17_compat_enum_fixed_underlying_type
+ : diag::ext_c23_enum_fixed_underlying_type)
<< BaseRange;
}
}
diff --git a/clang/test/C/C23/n3030.c b/clang/test/C/C23/n3030.c
new file mode 100644
index 00000000000000..82e50484fd7ebc
--- /dev/null
+++ b/clang/test/C/C23/n3030.c
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic -Wall
+
+#include <limits.h>
+
+enum us : unsigned short {
+ us_max = USHRT_MAX,
+ us_violation, // expected-error {{enumerator value 65536 is not representable in the underlying type 'unsigned short'}}
+ // expected-warning@-1 {{overflow}}
+ us_violation_2 = us_max + 1, // expected-error {{enumerator value is not representable in the underlying type 'unsigned short'}}
+ us_wrap_around_to_zero = (unsigned short)(USHRT_MAX + 1) /* Okay: conversion
+ done in constant expression before conversion to
+ underlying type: unsigned semantics okay. */
+};
+
+enum ui : unsigned int {
+ ui_max = UINT_MAX,
+ ui_violation, // expected-error {{enumerator value 4294967296 is not representable in the underlying type 'unsigned int'}}
+ // expected-warning@-1 {{overflow}}
+ ui_no_violation = ui_max + 1,
+ ui_wrap_around_to_zero = (unsigned int)(UINT_MAX + 1)
+};
+
+enum E1 : short;
+enum E2 : short; // expected-note {{previous}}
+enum E3; // expected-warning {{ISO C forbids forward references to 'enum' types}}
+enum E4 : unsigned long long;
+
+enum E1 : short { m11, m12 };
+enum E1 x = m11;
+
+enum E2 : long { // expected-error {{enumeration redeclared with different underlying type 'long' (was 'short')}}
+ m21,
+ m22
+};
+
+enum E3 { // expected-note {{definition of 'enum E3' is not complete until the closing '}'}}
+ // expected-note@-1 {{previous}}
+ m31,
+ m32,
+ m33 = sizeof(enum E3) // expected-error {{invalid application of 'sizeof' to an incomplete type 'enum E3'}}
+};
+enum E3 : int; // expected-error {{enumeration previously declared with nonfixed underlying type}}
+
+enum E4 : unsigned long long {
+ m40 = sizeof(enum E4),
+ m41 = ULLONG_MAX,
+ m42 // expected-error {{enumerator value 18446744073709551616 is not representable in the underlying type 'unsigned long long'}}
+};
+
+enum E5 y; // expected-error {{tentative definition has type 'enum E5' that is never completed}}
+ // expected-warning@-1 {{ISO C forbids forward references to 'enum' types}}
+ // expected-note@-2 {{forward declaration of 'enum E5'}}
+enum E6 : long int z; // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+enum E7 : long int = 0; // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+ // expected-error@-1 {{expected identifier or '('}}
+
+enum underlying : unsigned char { b0 };
+
+constexpr int a = _Generic(b0, int: 2, unsigned char: 1, default: 0);
+constexpr int b = _Generic((enum underlying)b0, int: 2, unsigned char: 1, default: 0);
+static_assert(a == 1);
+static_assert(b == 1);
+
+void f1(enum a : long b); // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+ // expected-warning@-1 {{declaration of 'enum a' will not be visible outside of this function}}
+void f2(enum c : long{x} d); // expected-warning {{declaration of 'enum c' will not be visible outside of this function}}
+enum e : int f3(); // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+
+typedef enum t u; // expected-warning {{ISO C forbids forward references to 'enum' types}}
+typedef enum v : short W; // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+typedef enum q : short { s } R;
+
+struct s1 {
+ int x;
+ enum e:int : 1; // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+ int y;
+};
+
+enum forward; // expected-warning {{ISO C forbids forward references to 'enum' types}}
+extern enum forward fwd_val0; /* Constraint violation: incomplete type */
+extern enum forward *fwd_ptr0; // expected-note {{previous}}
+extern int
+ *fwd_ptr0; // expected-error {{redeclaration of 'fwd_ptr0' with a different type: 'int *' vs 'enum forward *'}}
+
+enum forward1 : int;
+extern enum forward1 fwd_val1;
+extern int fwd_val1;
+extern enum forward1 *fwd_ptr1;
+extern int *fwd_ptr1;
+
+enum ee1 : short;
+enum e : short f = 0; // expected-error {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}}
+enum g : short { yyy } h = yyy;
+
+enum ee2 : typeof ((enum ee3 : short { A })0, (short)0);
diff --git a/clang/test/Sema/fixed-enum.c b/clang/test/Sema/fixed-enum.c
index 954ff8c452b80c..2b02def0e1788d 100644
--- a/clang/test/Sema/fixed-enum.c
+++ b/clang/test/Sema/fixed-enum.c
@@ -5,9 +5,9 @@
// RUN: %clang_cc1 -pedantic -std=c11 -xc -DC11 -verify %s
// RUN: %clang_cc1 -Weverything -std=c11 -xc -fms-extensions -DMS -verify %s
// RUN: %clang_cc1 -Weverything -std=c2x -xc -DC23 -verify %s
-// RUN: %clang_cc1 -pedantic -std=c2x -xc -DC23 -verify %s
+// RUN: %clang_cc1 -pedantic -std=c2x -xc -DC23 -verify -Wpre-c23-compat %s
// RUN: %clang_cc1 -Weverything -std=c23 -xc -DC23 -verify %s
-// RUN: %clang_cc1 -pedantic -std=c23 -xc -DC23 -verify %s
+// RUN: %clang_cc1 -pedantic -std=c23 -xc -DC23 -verify -Wpre-c23-compat %s
// RUN: %clang_cc1 -Weverything -std=c23 -xc -fms-extensions -DC23 -verify %s
enum X : int {e};
@@ -15,12 +15,14 @@ enum X : int {e};
// expected-warning@-2{{enumeration types with a fixed underlying type are incompatible with C++98}}
#elif defined(CXX03)
// expected-warning@-4{{enumeration types with a fixed underlying type are a C++11 extension}}
-#elif defined(OBJC) || defined(C23)
-// No diagnostic
+#elif defined(OBJC)
+// diagnostic
+#elif defined(C23)
+// expected-warning@-8{{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
#elif defined(C11)
-// expected-warning@-8{{enumeration types with a fixed underlying type are a Clang extension}}
+// expected-warning@-10{{enumeration types with a fixed underlying type are a C23 extension}}
#elif defined(MS)
-// expected-warning@-10{{enumeration types with a fixed underlying type are a Microsoft extension}}
+// expected-warning@-12{{enumeration types with a fixed underlying type are a Microsoft extension}}
#endif
// Don't warn about the forward declaration in any language mode.
@@ -29,16 +31,23 @@ enum Fwd : int { e2 };
#if !defined(OBJC) && !defined(C23)
// expected-warning@-3 {{enumeration types with a fixed underlying type}}
// expected-warning@-3 {{enumeration types with a fixed underlying type}}
+#elif defined(C23)
+// expected-warning@-6 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
+// expected-warning@-6 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
#endif
// Always error on the incompatible redeclaration.
enum BadFwd : int;
#if !defined(OBJC) && !defined(C23)
// expected-warning@-2 {{enumeration types with a fixed underlying type}}
+#elif defined(C23)
+// expected-warning@-4 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
#endif
-// expected-note@-4 {{previous declaration is here}}
+// expected-note@-6 {{previous declaration is here}}
enum BadFwd : char { e3 };
#if !defined(OBJC) && !defined(C23)
// expected-warning@-2 {{enumeration types with a fixed underlying type}}
+#elif defined(C23)
+// expected-warning@-4 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
#endif
-// expected-error@-4 {{enumeration redeclared with different underlying type 'char' (was 'int')}}
+// expected-error@-6 {{enumeration redeclared with different underlying type 'char' (was 'int')}}
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 255690cd6d34e2..47124bd91f846f 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -697,7 +697,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>Enhanced enumerations</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3030.htm">N3030</a></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 20</td>
</tr>
<tr>
<td>Freestanding C and IEC 60559 conformance scope reduction</td>
|
enum forward; // expected-warning {{ISO C forbids forward references to 'enum' types}} | ||
extern enum forward fwd_val0; /* Constraint violation: incomplete type */ |
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.
This example is taken directly from the paper. gcc gives the same set of diagnostics here. The paper says there should be errors, however the area is covered with lots of extensions, so I'm not sure if I'm missing some historical context here.
Please let me know what you think.
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.
Mostly LGTM, just some minor nits.
}; | ||
|
||
enum forward; // expected-warning {{ISO C forbids forward references to 'enum' types}} | ||
extern enum forward fwd_val0; /* Constraint violation: incomplete type */ |
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.
This should get the same pedantic diagnostic as the line above, I believe.
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.
@AaronBallman , after looking into this, I noticed that we emit this pedantic warning only for a first met declaration. So if I do
extern enum forward fwd_val0;
extern enum forward *fwd_ptr0;
The warning appears. Demo https://godbolt.org/z/saPEcPKs8
We don't enter the code emitting the diagnostic if there was a previous declaration.
It is emitted here:
llvm-project/clang/lib/Sema/SemaDecl.cpp
Line 17797 in f710612
Diag(Loc, DiagID); |
I wonder if that is still a problem and we need to change anything?
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.
Good catch, that's interesting! I think we may do that to reduce chattiness given how often C code uses elaborated type specifiers: https://godbolt.org/z/v1ob54G5o -- but git blame
on GitHub is utterly useless and I'm struggling to see why we ended up doing what we did.
I think for now we can leave it as-is; we still handle strict conformance properly because we only need to emit one diagnostic for the entire TU. We can revisit later if we think that's worth it.
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.
Thanks!
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.
LG!
…#107260) Clang already implemented functionality as an extension.
Clang already implemented functionality as an extension.