Skip to content

Commit a9d9b0a

Browse files
authored
[clang][C23] Claim N3030 Enhancements to Enumerations supported (#107260)
Clang already implemented functionality as an extension.
1 parent 11b95de commit a9d9b0a

File tree

5 files changed

+122
-15
lines changed

5 files changed

+122
-15
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,12 @@ def ext_cxx11_enum_fixed_underlying_type : Extension<
113113
def ext_ms_c_enum_fixed_underlying_type : Extension<
114114
"enumeration types with a fixed underlying type are a Microsoft extension">,
115115
InGroup<MicrosoftFixedEnum>;
116-
def ext_clang_c_enum_fixed_underlying_type : Extension<
117-
"enumeration types with a fixed underlying type are a Clang extension">,
118-
InGroup<DiagGroup<"fixed-enum-extension">>;
116+
def ext_c23_enum_fixed_underlying_type : Extension<
117+
"enumeration types with a fixed underlying type are a C23 extension">,
118+
InGroup<C23>;
119+
def warn_c17_compat_enum_fixed_underlying_type : Warning<
120+
"enumeration types with a fixed underlying type are incompatible with C standards before C23">,
121+
DefaultIgnore, InGroup<CPre23Compat>;
119122
def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
120123
"enumeration types with a fixed underlying type are incompatible with C++98">,
121124
InGroup<CXX98Compat>, DefaultIgnore;

clang/lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,18 +5439,20 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
54395439

54405440
BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());
54415441

5442-
if (!getLangOpts().ObjC && !getLangOpts().C23) {
5442+
if (!getLangOpts().ObjC) {
54435443
if (getLangOpts().CPlusPlus11)
54445444
Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
54455445
<< BaseRange;
54465446
else if (getLangOpts().CPlusPlus)
54475447
Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
54485448
<< BaseRange;
5449-
else if (getLangOpts().MicrosoftExt)
5449+
else if (getLangOpts().MicrosoftExt && !getLangOpts().C23)
54505450
Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
54515451
<< BaseRange;
54525452
else
5453-
Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)
5453+
Diag(ColonLoc, getLangOpts().C23
5454+
? diag::warn_c17_compat_enum_fixed_underlying_type
5455+
: diag::ext_c23_enum_fixed_underlying_type)
54545456
<< BaseRange;
54555457
}
54565458
}

clang/test/C/C23/n3030.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only -std=c23 %s -pedantic -Wall
2+
3+
#include <limits.h>
4+
5+
enum us : unsigned short {
6+
us_max = USHRT_MAX,
7+
us_violation, // expected-error {{enumerator value 65536 is not representable in the underlying type 'unsigned short'}}
8+
us_violation_2 = us_max + 1, // expected-error {{enumerator value is not representable in the underlying type 'unsigned short'}}
9+
us_wrap_around_to_zero = (unsigned short)(USHRT_MAX + 1) /* Okay: conversion
10+
done in constant expression before conversion to
11+
underlying type: unsigned semantics okay. */
12+
};
13+
14+
enum ui : unsigned int {
15+
ui_max = UINT_MAX,
16+
ui_violation, // expected-error {{enumerator value 4294967296 is not representable in the underlying type 'unsigned int'}}
17+
ui_no_violation = ui_max + 1,
18+
ui_wrap_around_to_zero = (unsigned int)(UINT_MAX + 1)
19+
};
20+
21+
enum E1 : short;
22+
enum E2 : short; // expected-note {{previous}}
23+
enum E3; // expected-warning {{ISO C forbids forward references to 'enum' types}}
24+
enum E4 : unsigned long long;
25+
26+
enum E1 : short { m11, m12 };
27+
enum E1 x = m11;
28+
29+
enum E2 : long { // expected-error {{enumeration redeclared with different underlying type 'long' (was 'short')}}
30+
m21,
31+
m22
32+
};
33+
34+
enum E3 { // expected-note {{definition of 'enum E3' is not complete until the closing '}'}}
35+
// expected-note@-1 {{previous}}
36+
m31,
37+
m32,
38+
m33 = sizeof(enum E3) // expected-error {{invalid application of 'sizeof' to an incomplete type 'enum E3'}}
39+
};
40+
enum E3 : int; // expected-error {{enumeration previously declared with nonfixed underlying type}}
41+
42+
enum E4 : unsigned long long {
43+
m40 = sizeof(enum E4),
44+
m41 = ULLONG_MAX,
45+
m42 // expected-error {{enumerator value 18446744073709551616 is not representable in the underlying type 'unsigned long long'}}
46+
};
47+
48+
enum E5 y; // expected-error {{tentative definition has type 'enum E5' that is never completed}}
49+
// expected-warning@-1 {{ISO C forbids forward references to 'enum' types}}
50+
// expected-note@-2 {{forward declaration of 'enum E5'}}
51+
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?}}
52+
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?}}
53+
// expected-error@-1 {{expected identifier or '('}}
54+
55+
enum underlying : unsigned char { b0 };
56+
57+
constexpr int a = _Generic(b0, int: 2, unsigned char: 1, default: 0);
58+
constexpr int b = _Generic((enum underlying)b0, int: 2, unsigned char: 1, default: 0);
59+
static_assert(a == 1);
60+
static_assert(b == 1);
61+
62+
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?}}
63+
// expected-warning@-1 {{declaration of 'enum a' will not be visible outside of this function}}
64+
void f2(enum c : long{x} d); // expected-warning {{declaration of 'enum c' will not be visible outside of this function}}
65+
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?}}
66+
67+
typedef enum t u; // expected-warning {{ISO C forbids forward references to 'enum' types}}
68+
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?}}
69+
typedef enum q : short { s } R;
70+
71+
struct s1 {
72+
int x;
73+
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?}}
74+
int y;
75+
};
76+
77+
enum forward; // expected-warning {{ISO C forbids forward references to 'enum' types}}
78+
extern enum forward fwd_val0; /* Constraint violation: incomplete type */
79+
extern enum forward *fwd_ptr0; // expected-note {{previous}}
80+
extern int
81+
*fwd_ptr0; // expected-error {{redeclaration of 'fwd_ptr0' with a different type: 'int *' vs 'enum forward *'}}
82+
83+
enum forward1 : int;
84+
extern enum forward1 fwd_val1;
85+
extern int fwd_val1;
86+
extern enum forward1 *fwd_ptr1;
87+
extern int *fwd_ptr1;
88+
89+
enum ee1 : short;
90+
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?}}
91+
enum g : short { yyy } h = yyy;
92+
93+
enum ee2 : typeof ((enum ee3 : short { A })0, (short)0);

clang/test/Sema/fixed-enum.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@
55
// RUN: %clang_cc1 -pedantic -std=c11 -xc -DC11 -verify %s
66
// RUN: %clang_cc1 -Weverything -std=c11 -xc -fms-extensions -DMS -verify %s
77
// RUN: %clang_cc1 -Weverything -std=c2x -xc -DC23 -verify %s
8-
// RUN: %clang_cc1 -pedantic -std=c2x -xc -DC23 -verify %s
8+
// RUN: %clang_cc1 -pedantic -std=c2x -xc -DC23 -verify -Wpre-c23-compat %s
99
// RUN: %clang_cc1 -Weverything -std=c23 -xc -DC23 -verify %s
10-
// RUN: %clang_cc1 -pedantic -std=c23 -xc -DC23 -verify %s
10+
// RUN: %clang_cc1 -pedantic -std=c23 -xc -DC23 -verify -Wpre-c23-compat %s
1111
// RUN: %clang_cc1 -Weverything -std=c23 -xc -fms-extensions -DC23 -verify %s
1212

1313
enum X : int {e};
1414
#if defined(CXX11)
1515
// expected-warning@-2{{enumeration types with a fixed underlying type are incompatible with C++98}}
1616
#elif defined(CXX03)
1717
// expected-warning@-4{{enumeration types with a fixed underlying type are a C++11 extension}}
18-
#elif defined(OBJC) || defined(C23)
19-
// No diagnostic
18+
#elif defined(OBJC)
19+
// diagnostic
20+
#elif defined(C23)
21+
// expected-warning@-8{{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
2022
#elif defined(C11)
21-
// expected-warning@-8{{enumeration types with a fixed underlying type are a Clang extension}}
23+
// expected-warning@-10{{enumeration types with a fixed underlying type are a C23 extension}}
2224
#elif defined(MS)
23-
// expected-warning@-10{{enumeration types with a fixed underlying type are a Microsoft extension}}
25+
// expected-warning@-12{{enumeration types with a fixed underlying type are a Microsoft extension}}
2426
#endif
2527

2628
// Don't warn about the forward declaration in any language mode.
@@ -29,16 +31,23 @@ enum Fwd : int { e2 };
2931
#if !defined(OBJC) && !defined(C23)
3032
// expected-warning@-3 {{enumeration types with a fixed underlying type}}
3133
// expected-warning@-3 {{enumeration types with a fixed underlying type}}
34+
#elif defined(C23)
35+
// expected-warning@-6 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
36+
// expected-warning@-6 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
3237
#endif
3338

3439
// Always error on the incompatible redeclaration.
3540
enum BadFwd : int;
3641
#if !defined(OBJC) && !defined(C23)
3742
// expected-warning@-2 {{enumeration types with a fixed underlying type}}
43+
#elif defined(C23)
44+
// expected-warning@-4 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
3845
#endif
39-
// expected-note@-4 {{previous declaration is here}}
46+
// expected-note@-6 {{previous declaration is here}}
4047
enum BadFwd : char { e3 };
4148
#if !defined(OBJC) && !defined(C23)
4249
// expected-warning@-2 {{enumeration types with a fixed underlying type}}
50+
#elif defined(C23)
51+
// expected-warning@-4 {{enumeration types with a fixed underlying type are incompatible with C standards before C23}}
4352
#endif
44-
// expected-error@-4 {{enumeration redeclared with different underlying type 'char' (was 'int')}}
53+
// expected-error@-6 {{enumeration redeclared with different underlying type 'char' (was 'int')}}

clang/www/c_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ <h2 id="c2x">C23 implementation status</h2>
697697
<tr>
698698
<td>Enhanced enumerations</td>
699699
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3030.htm">N3030</a></td>
700-
<td class="unknown" align="center">Unknown</td>
700+
<td class="unreleased" align="center">Clang 20</td>
701701
</tr>
702702
<tr>
703703
<td>Freestanding C and IEC 60559 conformance scope reduction</td>

0 commit comments

Comments
 (0)