| /* Test C2x enumerations with fixed underlying type. Valid code. */ |
| /* { dg-do run } */ |
| /* { dg-options "-std=c2x -pedantic-errors" } */ |
| |
| /* Check a type while defining an enum (via a diagnostic for incompatible |
| pointer types if the wrong type was chosen). */ |
| #define TYPE_CHECK(cst, type) \ |
| cst ## _type_check = sizeof (1 ? (type *) 0 : (typeof (cst) *) 0) |
| |
| extern int i; |
| |
| enum e1 : short { e1a = __SHRT_MAX__, |
| TYPE_CHECK (e1a, short), |
| e1z = (long long) 0, |
| TYPE_CHECK (e1z, enum e1), |
| e1b = -__SHRT_MAX__ - 1, |
| e1c, |
| TYPE_CHECK (e1c, enum e1) }; |
| extern enum e1 e1v; |
| extern typeof (e1a) e1v; |
| extern typeof (e1b) e1v; |
| extern typeof (e1c) e1v; |
| extern typeof (e1z) e1v; |
| extern short e1v; |
| static_assert (e1a == __SHRT_MAX__); |
| static_assert (e1b == -__SHRT_MAX__ - 1); |
| static_assert (e1c == -__SHRT_MAX__); |
| static_assert (e1a > 0); |
| static_assert (e1b < 0); |
| static_assert (e1c < 0); |
| static_assert (e1z == 0); |
| extern typeof (+e1v) i; |
| extern typeof (+e1a) i; |
| extern typeof (e1a + e1b) i; |
| enum e1 : short; |
| enum e1 : volatile short; |
| enum e1 : _Atomic short; |
| enum e1 : typeof (short); |
| |
| enum e2 : bool { b0, b1, b0a = 0, b1a = 1 }; |
| extern enum e2 e2v; |
| extern typeof (b0) e2v; |
| extern typeof (b0a) e2v; |
| extern typeof (b1) e2v; |
| extern typeof (b1a) e2v; |
| extern bool e2v; |
| extern typeof (+e2v) i; |
| extern typeof (+b0) i; |
| static_assert (b0 == 0); |
| static_assert (b1 == 1); |
| static_assert (b0a == 0); |
| static_assert (b1a == 1); |
| |
| enum e3 : volatile const _Atomic unsigned short; |
| enum e3 : unsigned short { e3a, e3b }; |
| extern enum e3 e3v; |
| extern typeof (e3a) e3v; |
| extern typeof (e3b) e3v; |
| extern unsigned short e3v; |
| |
| /* The enum type is complete from the end of the first enum type specifier |
| (which is nested inside another enum type specifier in this example). */ |
| enum e4 : typeof ((enum e4 : long { e4a = sizeof (enum e4) })0, 0L); |
| extern enum e4 e4v; |
| extern typeof (e4a) e4v; |
| extern long e4v; |
| |
| enum e5 : unsigned int; |
| extern enum e5 e5v; |
| extern typeof (e5v + e5v) e5v; |
| extern unsigned int e5v; |
| |
| enum : unsigned short { e6a, e6b, TYPE_CHECK (e6a, unsigned short) } e6v; |
| extern typeof (e6a) e6v; |
| extern typeof (e6b) e6v; |
| extern unsigned short e6v; |
| |
| struct s1; |
| struct s2 { int a; }; |
| union u1; |
| union u2 { int a; }; |
| enum xe1 { XE1 }; |
| enum xe2 : long long { XE2 }; |
| enum xe3 : unsigned long; |
| |
| void |
| f () |
| { |
| /* Tags can be redeclared in an inner scope. */ |
| enum s1 : char; |
| enum s2 : int { S2 }; |
| enum u1 : long { U1 }; |
| enum u2 : unsigned char; |
| enum xe1 : long long; |
| enum xe2 : short; |
| enum xe3 : char { XE3 }; |
| static_assert (sizeof (enum xe3) == 1); |
| static_assert (sizeof (enum xe2) == sizeof (short)); |
| static_assert (sizeof (enum xe1) == sizeof (long long)); |
| } |
| |
| void *p; |
| typeof (nullptr) np; |
| |
| extern void abort (void); |
| extern void exit (int); |
| |
| int |
| main () |
| { |
| /* Conversions to enums with fixed underlying type have the same semantics as |
| converting to the underlying type. */ |
| volatile enum e1 e1vm; |
| volatile enum e2 e2vm; |
| e1vm = __LONG_LONG_MAX__; /* { dg-warning "overflow" } */ |
| if (e1vm != (short) __LONG_LONG_MAX__) |
| abort (); |
| e2vm = 10; |
| if (e2vm != 1) |
| abort (); |
| e2vm = 0; |
| if (e2vm != 0) |
| abort (); |
| /* Arithmetic on enums with fixed underlying type has the same semantics as |
| arithmetic on the underlying type; in particular, the special semantics |
| for bool apply to enums with bool as fixed underlying type. */ |
| if (e2vm++ != 0) |
| abort (); |
| if (e2vm != 1) |
| abort (); |
| if (e2vm++ != 1) |
| abort (); |
| if (e2vm != 1) |
| abort (); |
| if (e2vm-- != 1) |
| abort (); |
| if (e2vm != 0) |
| abort (); |
| if (e2vm-- != 0) |
| abort (); |
| if (e2vm != 1) |
| abort (); |
| if (++e2vm != 1) |
| abort (); |
| if (e2vm != 1) |
| abort (); |
| e2vm = 0; |
| if (++e2vm != 1) |
| abort (); |
| if (e2vm != 1) |
| abort (); |
| if (--e2vm != 0) |
| abort (); |
| if (e2vm != 0) |
| abort (); |
| if (--e2vm != 1) |
| abort (); |
| if (e2vm != 1) |
| abort (); |
| e2vm = p; |
| e2vm = np; |
| e2vm = (bool) p; |
| e2vm = (bool) np; |
| if (e2vm != 0) |
| abort (); |
| exit (0); |
| } |