blob: 5ab9694302fa03a01edd81c80a828352a5002df3 [file] [log] [blame]
/* 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);
}