xref: /llvm-project/clang/test/AST/ByteCode/constexpr.c (revision e8674af6f41b2e78ceebabb23e40588c41da5a23)
1 // RUN: %clang_cc1 -std=c23 -verify=ref,both -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion -Wno-div-by-zero %s
2 // RUN: %clang_cc1 -std=c23 -verify=expected,both -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion -Wno-div-by-zero -fexperimental-new-constant-interpreter %s
3 
4 // Check that constexpr only applies to variables.
5 constexpr void f0() {} // both-error {{'constexpr' can only be used in variable declarations}}
6 constexpr const int f1() { return 0; } // both-error {{'constexpr' can only be used in variable declarations}}
7 
8 constexpr struct S1 { int f; }; //both-error {{struct cannot be marked constexpr}}
9 constexpr struct S2 ; // both-error {{struct cannot be marked constexpr}}
10 constexpr union U1; // both-error {{union cannot be marked constexpr}}
11 constexpr union U2 {int a; float b;}; // both-error {{union cannot be marked constexpr}}
12 constexpr enum E1 {A = 1, B = 2} ; // both-error {{enum cannot be marked constexpr}}
13 struct S3 {
14   static constexpr int f = 0; // both-error {{type name does not allow storage class}}
15   // both-error@-1 {{type name does not allow constexpr}}
16   // both-error@-2 {{expected ';' at end}}
17   constexpr int f1 = 0;
18   // both-error@-1 {{type name does not allow constexpr}}
19   // both-error@-2 {{expected ';' at end}}
20 };
21 
22 constexpr; // both-error {{'constexpr' can only be used in variable declarations}}
23 constexpr int V1 = 3;
24 constexpr float V2 = 7.0;
25 int V3 = (constexpr)3; // both-error {{expected expression}}
26 
27 void f2() {
28   constexpr int a = 0;
29   constexpr float b = 1.7f;
30 }
31 
32 // Check how constexpr works with other storage-class specifiers.
33 constexpr auto V4 = 1;
34 constexpr static auto V5 = 1;
35 constexpr static const auto V6 = 1;
36 constexpr static const int V7 = 1;
37 constexpr static int V8 = 1;
38 constexpr auto Ulong = 1L;
39 constexpr auto CompoundLiteral = (int){13};
40 constexpr auto DoubleCast = (double)(1 / 3);
41 constexpr auto String = "this is a string"; // both-error {{constexpr pointer initializer is not null}}
42 constexpr signed auto Long = 1L; // both-error {{'auto' cannot be signed or unsigned}}
43 _Static_assert(_Generic(Ulong, long : 1));
44 _Static_assert(_Generic(CompoundLiteral, int : 1));
45 _Static_assert(_Generic(DoubleCast, double : 1));
46 _Static_assert(_Generic(String, char* : 1));
47 
48 typedef constexpr int Foo; // both-error {{typedef cannot be constexpr}}
49 constexpr typedef int Bar; // both-error {{typedef cannot be constexpr}}
50 
51 void f3(constexpr register int P1) { // both-error {{function parameter cannot be constexpr}}
52   constexpr register int V9 = 0;
53   constexpr register auto V10 = 0.0;
54 }
55 
56 constexpr thread_local int V11 = 38; // both-error {{cannot combine with previous '_Thread_local' declaration specifier}}
57 constexpr static thread_local double V12 = 38; // both-error {{cannot combine with previous '_Thread_local' declaration specifier}}
58 constexpr extern thread_local char V13; // both-error {{cannot combine with previous '_Thread_local' declaration specifier}}
59 // both-error@-1 {{cannot combine with previous 'extern' declaration specifier}}
60 // both-error@-2 {{constexpr variable declaration must be a definition}}
61 constexpr thread_local short V14 = 38; // both-error {{cannot combine with previous '_Thread_local' declaration specifier}}
62 
63 // Check how constexpr works with qualifiers.
64 constexpr _Atomic int V15 = 0; // both-error {{constexpr variable cannot have type 'const _Atomic(int)'}}
65 constexpr _Atomic(int) V16 = 0; // both-error {{constexpr variable cannot have type 'const _Atomic(int)'}}
66 
67 constexpr volatile int V17 = 0; // both-error {{constexpr variable cannot have type 'const volatile int'}}
68 
69 constexpr int * restrict V18 = 0; // both-error {{constexpr variable cannot have type 'int *const restrict'}}
70 
71 constexpr extern char Oops = 1; // both-error {{cannot combine with previous 'extern' declaration specifier}} \
72                                 // both-warning {{'extern' variable has an initializer}}
73 
74 constexpr int * restrict * Oops1 = 0;
75 
76 typedef _Atomic(int) TheA;
77 typedef volatile short TheV;
78 typedef float * restrict TheR;
79 
80 constexpr TheA V19[3] = {};
81 // both-error@-1 {{constexpr variable cannot have type 'const TheA[3]' (aka 'const _Atomic(int)[3]')}}
82 constexpr TheV V20[3] = {};
83 // both-error@-1 {{constexpr variable cannot have type 'const TheV[3]' (aka 'const volatile short[3]')}}
84 constexpr TheR V21[3] = {};
85 // both-error@-1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *restrict const[3]')}}
86 
87 struct HasA {
88   TheA f;
89   int b;
90 };
91 
92 struct HasV {
93   float b;
94   TheV f;
95 };
96 
97 struct HasR {
98   short b;
99   int a;
100   TheR f;
101 };
102 
103 constexpr struct HasA V22[2] = {};
104 // both-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
105 constexpr struct HasV V23[2] = {};
106 // both-error@-1 {{constexpr variable cannot have type 'TheV' (aka 'volatile short')}}
107 constexpr struct HasR V24[2] = {};
108 // both-error@-1 {{constexpr variable cannot have type 'TheR' (aka 'float *restrict')}}
109 
110 union U3 {
111   float a;
112   union {
113     struct HasA f;
114     struct HasR f1;
115   };
116 };
117 
118 constexpr union U3 V25 = {};
119 // both-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
120 constexpr union U3 V26[8] = {};
121 // both-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
122 
123 struct S4 {
124   union U3 f[3];
125 };
126 
127 constexpr struct S4 V27 = {};
128 // both-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
129 constexpr const int V28 = 28;
130 
131 struct S {
132   union {
133     volatile int i;
134   };
135   int j;
136 };
137 
138 constexpr struct S s = {}; // both-error {{constexpr variable cannot have type 'volatile int'}}
139 
140 // Check that constexpr variable must have a valid initializer which is a
141 // constant expression.
142 constexpr int V29;
143 // both-error@-1 {{constexpr variable 'V29' must be initialized by a constant expression}}
144 
145 struct S5 {
146   int f;
147 };
148 
149 constexpr struct S5 V30;
150 // both-error@-1 {{constexpr variable 'V30' must be initialized by a constant expression}}
151 constexpr struct S5 V31 = {};
152 
153 int randomFoo() { return 7; }
154 
155 constexpr float V32 = randomFoo();
156 // both-error@-1 {{constexpr variable 'V32' must be initialized by a constant expression}}
157 
158 const int V33 = 4;
159 const int V34 = 0;
160 const int V35 = 2;
161 
162 constexpr int V36 = V33 / V34;
163 // both-error@-1 {{constexpr variable 'V36' must be initialized by a constant expression}}
164 constexpr int V37 = V33 / V35;
165 // both-error@-1 {{constexpr variable 'V37' must be initialized by a constant expression}}
166 constexpr int V38 = 3;
167 constexpr int V39 = V38 / V38;
168 constexpr int V40 = V38 / 2;
169 constexpr int V41 = V38 / 0;
170 // both-error@-1 {{constexpr variable 'V41' must be initialized by a constant expression}}
171 // both-note@-2 {{division by zero}}
172 constexpr int V42 = V38 & 0;
173 
174 constexpr struct S5 V43 = { randomFoo() };
175 // both-error@-1 {{constexpr variable 'V43' must be initialized by a constant expression}}
176 constexpr struct S5 V44 = { 0 };
177 constexpr struct S5 V45 = { V38 / 0 };
178 // both-error@-1 {{constexpr variable 'V45' must be initialized by a constant expression}}
179 // both-note@-2 {{division by zero}}
180 
181 constexpr float V46[3] = {randomFoo() };
182 // both-error@-1 {{constexpr variable 'V46' must be initialized by a constant expression}}
183 constexpr struct S5 V47[3] = {randomFoo() };
184 // both-error@-1 {{constexpr variable 'V47' must be initialized by a constant expression}}
185 
186 const static int V48 = V38;
187 constexpr static int V49 = V48;
188 // both-error@-1 {{constexpr variable 'V49' must be initialized by a constant expression}}
189 
190 void f4(const int P1) {
191   constexpr int V = P1;
192 // both-error@-1 {{constexpr variable 'V' must be initialized by a constant expression}}
193 
194   constexpr int V1 = 12;
195   constexpr const int *V2 = &V1;
196 // both-error@-1 {{constexpr variable 'V2' must be initialized by a constant expression}}
197 }
198 
199 // Check that initializer for constexpr variable should match the type of the
200 // variable and is exactly representable int the variable's type.
201 
202 struct S6 {
203   unsigned char a;
204 };
205 
206 struct S7 {
207   union {
208     float a;
209   };
210   unsigned int b;
211 };
212 
213 struct S8 {
214   unsigned char a[3];
215   unsigned int b[3];
216 };
217 
218 constexpr struct S8 DesigInit = {.b = {299, 7, 8}, .a = {-1, 7, 8}};
219 // both-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned char'}}
220 
221 void f5() {
222   constexpr char V50 = 300;
223   // both-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'const char'}}
224   constexpr float V51 = 1.0 / 3.0;
225   // both-error@-1 {{constexpr initializer evaluates to 3.333333e-01 which is not exactly representable in type 'const float'}}
226   constexpr float V52 = 0.7;
227   // both-error@-1 {{constexpr initializer evaluates to 7.000000e-01 which is not exactly representable in type 'const float'}}
228   constexpr float V53 = 1.0f / 3.0f;
229   constexpr float V54 = 432000000000;
230   // both-error@-1 {{constexpr initializer evaluates to 432000000000 which is not exactly representable in type 'const float'}}
231   constexpr unsigned char V55[] = {
232       "\xAF",
233   // both-error@-1 {{constexpr initializer evaluates to -81 which is not exactly representable in type 'const unsigned char'}}
234   };
235 
236   constexpr unsigned char V56[] = {
237       u8"\xAF",
238   };
239   constexpr struct S6 V57 = {299};
240   // both-error@-1 {{constexpr initializer evaluates to 299 which is not exactly representable in type 'unsigned char'}}
241   constexpr struct S6 V58 = {-299};
242   // both-error@-1 {{constexpr initializer evaluates to -299 which is not exactly representable in type 'unsigned char'}}
243   constexpr double V59 = 0.5;
244   constexpr double V60 = 1.0;
245   constexpr float V61 = V59 / V60;
246   constexpr double V62 = 1.7;
247   constexpr float V63 = V59 / V62;
248   // both-error@-1 {{constexpr initializer evaluates to 2.941176e-01 which is not exactly representable in type 'const float'}}
249 
250   constexpr unsigned char V64 = '\xAF';
251   // both-error@-1 {{constexpr initializer evaluates to -81 which is not exactly representable in type 'const unsigned char'}}
252   constexpr unsigned char V65 = u8'\xAF';
253 
254   constexpr char V66[3] = {300};
255   // both-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'const char'}}
256   constexpr struct S6 V67[3] = {300};
257   // both-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'unsigned char'}}
258 
259   constexpr struct S7 V68 = {0.3, -1 };
260   // both-error@-1 {{constexpr initializer evaluates to 3.000000e-01 which is not exactly representable in type 'float'}}
261   // both-error@-2 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned int'}}
262   constexpr struct S7 V69 = {0.5, -1 };
263   // both-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned int'}}
264   constexpr struct S7 V70[3] = {{123456789}};
265   // both-error@-1 {{constexpr initializer evaluates to 123456789 which is not exactly representable in type 'float'}}
266 
267   constexpr int V71 = 0.3;
268   // both-error@-1 {{constexpr initializer for type 'const int' is of type 'double'}}
269   constexpr int V72 = V59;
270   // both-error@-1 {{constexpr initializer for type 'const int' is of type 'const double'}}
271   constexpr struct S6 V73 = {V59};
272   // both-error@-1 {{constexpr initializer for type 'unsigned char' is of type 'const double'}}
273 
274   constexpr float V74 = 1;
275   constexpr float V75 = V59;
276   constexpr unsigned int V76[3] = {0.5};
277   // both-error@-1 {{constexpr initializer for type 'const unsigned int' is of type 'double'}}
278 
279   constexpr _Complex float V77 = 0;
280   constexpr float V78 = V77;
281   // both-error@-1 {{constexpr initializer for type 'const float' is of type 'const _Complex float'}}
282   constexpr int V79 = V77;
283   // both-error@-1 {{constexpr initializer for type 'const int' is of type 'const _Complex float'}}
284 
285 }
286 
287 constexpr char string[] = "test""ing this out\xFF";
288 constexpr unsigned char ustring[] = "test""ing this out\xFF";
289 // both-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
290 constexpr char u8string[] = u8"test"u8"ing this out\xFF";
291 // both-error@-1 {{constexpr initializer evaluates to 255 which is not exactly representable in type 'const char'}}
292 constexpr unsigned char u8ustring[] = u8"test"u8"ing this out\xFF";
293 constexpr unsigned short uustring[] = u"test"u"ing this out\xFF";
294 constexpr unsigned int Ustring[] = U"test"U"ing this out\xFF";
295 constexpr unsigned char Arr2[6][6] = {
296   {"ek\xFF"}, {"ek\xFF"}
297 // both-error@-1 2{{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
298 };
299 
300 constexpr int i = (12);
301 constexpr int j = (i);
302 constexpr unsigned jneg = (-i);
303 // both-error@-1 {{constexpr initializer evaluates to -12 which is not exactly representable in type 'const unsigned int'}}
304 
305 // Check that initializer for pointer constexpr variable should be null.
306 constexpr int V80 = 3;
307 constexpr const int *V81 = &V80;
308 // both-error@-1 {{constexpr pointer initializer is not null}}
309 constexpr int *V82 = 0;
310 constexpr int *V83 = V82;
311 constexpr int *V84 = 42;
312 // both-error@-1 {{constexpr variable 'V84' must be initialized by a constant expression}}
313 // both-note@-2 {{this conversion is not allowed in a constant expression}}
314 // both-error@-3 {{constexpr pointer initializer is not null}}
315 constexpr int *V85 = nullptr;
316 
317 // Check that constexpr variables should not be VLAs.
318 void f6(const int P1) {
319   constexpr int V86[P1] = {};
320 // both-error@-1 {{constexpr variable cannot have type 'const int[P1]'}}
321   const int V87 = 3;
322   constexpr int V88[V87] = {};
323 // both-warning@-1 {{variable length array folded to constant array as an extension}}
324   int V89 = 7;
325   constexpr int V90[V89] = {};
326 // both-error@-1 {{constexpr variable cannot have type 'const int[V89]'}}
327 }
328 
329 void f7(int n, int array[n]) {
330   constexpr typeof(array) foo = 0; // Accepted because array is a pointer type, not a VLA type
331   int (*(*fp)(int n))[n];
332   constexpr typeof(fp) bar = 0; // both-error {{constexpr variable cannot have type 'const typeof (fp)' (aka 'int (*(*const)(int))[n]')}}
333 }
334 
335 // Check how constexpr works with NaNs and infinities.
336 #define FLT_NAN __builtin_nanf("1")
337 #define DBL_NAN __builtin_nan("1")
338 #define LD_NAN __builtin_nanf("1")
339 #define FLT_SNAN __builtin_nansf("1")
340 #define DBL_SNAN __builtin_nans("1")
341 #define LD_SNAN __builtin_nansl("1")
342 #define INF __builtin_inf()
343 void infsNaNs() {
344   // Inf and quiet NaN is always fine, signaling NaN must have the same type.
345   constexpr float fl0 = INF;
346   constexpr float fl1 = (long double)INF;
347   constexpr float fl2 = (long double)FLT_NAN;
348   constexpr float fl3 = FLT_NAN;
349   constexpr float fl5 = DBL_NAN;
350   constexpr float fl6 = LD_NAN;
351   constexpr float fl7 = DBL_SNAN; // both-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
352   constexpr float fl8 = LD_SNAN; // both-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
353 
354   constexpr double db0 = FLT_NAN;
355   constexpr double db2 = DBL_NAN;
356   constexpr double db3 = DBL_SNAN;
357   constexpr double db4 = FLT_SNAN; // both-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
358   constexpr double db5 = LD_SNAN; // both-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
359   constexpr double db6 = INF;
360 }
361 
362 constexpr struct S9 s9 = {  }; // both-error {{variable has incomplete type 'const struct S9'}} \
363                                // both-note {{forward declaration of 'struct S9'}}
364 
365 struct S10 {
366   signed long long i : 8;
367 };
368 constexpr struct S10 c = { 255 };
369 // FIXME-expected-error@-1 {{constexpr initializer evaluates to 255 which is not exactly representable in 'long long' bit-field with width 8}}
370 // See: GH#101299
371