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