aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/c2x-enum-6.c
blob: 5ab9694302fa03a01edd81c80a828352a5002df3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* 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);
}