-
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,93 @@ | ||||
// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only -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'}} | ||||
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'}} | ||||
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 */ | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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
The warning appears. Demo https://godbolt.org/z/saPEcPKs8 We don't enter the code emitting the diagnostic if there was a previous declaration. llvm-project/clang/lib/Sema/SemaDecl.cpp Line 17797 in f710612
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 commentThe 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 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 commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||||
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); |
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.