xref: /llvm-project/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp (revision 820c6ac7f5e438cc268ecb1fa2c6b17f0d168000)
1 // RUN: %clang_cc1 -std=c++2a -Wno-unused-value %s -verify
2 // RUN: %clang_cc1 -std=c++2b -Wno-unused-value %s -verify
3 
4 consteval int id(int i) { return i; }
5 constexpr char id(char c) { return c; }
6 
7 template <typename T>
8 constexpr int f(T t) { // expected-note {{declared here}}
9     return t + id(t);  // expected-note 2{{'f<int>' is an immediate function because its body contains a call to a consteval function 'id' and that call is not a constant expression}}
10 }
11 
12 namespace examples {
13 
14 auto a = &f<char>; // ok, f<char> is not an immediate function
15 auto b = &f<int>;  // expected-error {{cannot take address of immediate function 'f<int>' outside of an immediate invocation}}
16 
17 static_assert(f(3) == 6); // ok
18 
19 template <typename T>
20 constexpr int g(T t) {    // g<int> is not an immediate function
21     return t + id(42);    // because id(42) is already a constant
22 }
23 
24 template <typename T, typename F>
25 constexpr bool is_not(T t, F f) {
26     return not f(t);
27 }
28 
29 consteval bool is_even(int i) { return i % 2 == 0; }
30 
31 static_assert(is_not(5, is_even));
32 
33 int x = 0; // expected-note {{declared here}}
34 
35 template <typename T>
36 constexpr T h(T t = id(x)) { // expected-note {{read of non-const variable 'x' is not allowed in a constant expression}} \
37                              // expected-note {{'hh<int>' is an immediate function because its body contains a call to a consteval function 'id' and that call is not a constant expression}}
38     return t;
39 }
40 
41 template <typename T>
42 constexpr T hh() {           // hh<int> is an immediate function
43     [[maybe_unused]] auto x = h<T>();
44     return h<T>();
45 }
46 
47 int i = hh<int>(); // expected-error {{call to immediate function 'examples::hh<int>' is not a constant expression}} \
48                    // expected-note {{in call to 'hh<int>()'}}
49 
50 struct A {
51   int x;
52   int y = id(x);
53 };
54 
55 template <typename T>
56 constexpr int k(int) {
57   return A(42).y;
58 }
59 
60 }
61 
62 namespace nested {
63 
64 template <typename T>
65 constexpr int fdupe(T t) {
66     return id(t);
67 }
68 
69 struct a {
70   constexpr a(int) { }
71 };
72 
73 a aa(fdupe<int>((f<int>(7))));
74 
75 template <typename T>
76 constexpr int foo(T t);     // expected-note {{declared here}}
77 
78 a bb(f<int>(foo<int>(7))); // expected-error{{call to immediate function 'f<int>' is not a constant expression}} \
79                            // expected-note{{undefined function 'foo<int>' cannot be used in a constant expression}}
80 
81 }
82 
83 namespace e2{
84 template <typename T>
85 constexpr int f(T t);
86 auto a = &f<char>;
87 auto b = &f<int>;
88 }
89 
90 namespace forward_declare_constexpr{
91 template <typename T>
92 constexpr int f(T t);
93 
94 auto a = &f<char>;
95 auto b = &f<int>;
96 
97 template <typename T>
98 constexpr int f(T t) {
99     return id(0);
100 }
101 }
102 
103 namespace forward_declare_consteval{
104 template <typename T>
105 constexpr int f(T t);
106 
107 auto a = &f<char>;
108 auto b = &f<int>; // expected-error {{immediate function 'f<int>' used before it is defined}} \
109                   // expected-note {{in instantiation of function template specialization}}
110 
111 template <typename T>
112 constexpr int f(T t) { // expected-note {{'f<int>' defined here}}
113     return id(t); // expected-note {{'f<int>' is an immediate function because its body contains a call to a consteval function 'id' and that call is not a constant expression}}
114 }
115 }
116 
117 namespace constructors {
118 consteval int f(int) {
119   return 0;
120 }
121 struct S {
122   constexpr S(auto i) {
123     f(i);
124   }
125 };
126 constexpr void g(auto i) {
127   [[maybe_unused]] S s{i};
128 }
129 void test() {
130   g(0);
131 }
132 }
133 
134 namespace aggregate {
135 consteval int f(int);
136 struct S{
137     int a = 0;
138     int b = f(a);
139 };
140 
141 constexpr bool test(auto i) {
142     S s{i};
143     return s.b == 2 *i;
144 }
145 consteval int f(int i) {
146     return 2 * i;
147 }
148 
149 void test() {
150     static_assert(test(42));
151 }
152 
153 }
154 
155 namespace ConstevalConstructor{
156 int x = 0; // expected-note {{declared here}}
157 struct S {
158     consteval S(int) {};
159 };
160 constexpr int g(auto t) {
161     S s(t); // expected-note {{'g<int>' is an immediate function because its body contains a call to a consteval constructor 'S' and that call is not a constant expression}}
162     return 0;
163 }
164 int i = g(x); // expected-error {{call to immediate function 'ConstevalConstructor::g<int>' is not a constant expression}} \
165               // expected-note {{read of non-const variable 'x' is not allowed in a constant expression}}
166 }
167 
168 
169 
170 namespace Aggregate {
171 consteval int f(int); // expected-note {{declared here}}
172 struct S {
173   int x = f(42); // expected-note {{undefined function 'f' cannot be used in a constant expression}} \
174                  // expected-note {{'immediate<int>' is an immediate function because its body contains a call to a consteval function 'f' and that call is not a constant expression}}
175 };
176 
177 constexpr S immediate(auto) {
178     return S{};
179 }
180 
181 void test_runtime() {
182     (void)immediate(0); // expected-error {{call to immediate function 'Aggregate::immediate<int>' is not a constant expression}} \
183                         // expected-note {{in call to 'immediate<int>(0)'}}
184 }
185 consteval int f(int i) {
186     return i;
187 }
188 consteval void test() {
189     constexpr S s = immediate(0);
190     static_assert(s.x == 42);
191 }
192 }
193 
194 
195 
196 namespace GH63742 {
197 void side_effect(); // expected-note  {{declared here}}
198 consteval int f(int x) {
199     if (!x) side_effect(); // expected-note {{non-constexpr function 'side_effect' cannot be used in a constant expression}}
200     return x;
201 }
202 struct SS {
203   int y = f(1); // Ok
204   int x = f(0); // expected-error {{call to consteval function 'GH63742::f' is not a constant expression}} \
205                 // expected-note  {{declared here}} \
206                 // expected-note  {{in call to 'f(0)'}}
207   SS();
208 };
209 SS::SS(){} // expected-note {{in the default initializer of 'x'}}
210 
211 consteval int f2(int x) {
212     if (!__builtin_is_constant_evaluated()) side_effect();
213     return x;
214 }
215 struct S2 {
216     int x = f2(0);
217     constexpr S2();
218 };
219 
220 constexpr S2::S2(){}
221 S2 s = {};
222 constinit S2 s2 = {};
223 
224 struct S3 {
225     int x = f2(0);
226     S3();
227 };
228 S3::S3(){}
229 
230 }
231 
232 namespace Defaulted {
233 consteval int f(int x);
234 struct SS {
235   int x = f(0);
236   SS() = default;
237 };
238 }
239 
240 namespace DefaultedUse{
241 consteval int f(int x);  // expected-note {{declared here}}
242 struct SS {
243   int a = sizeof(f(0)); // Ok
244   int x = f(0); // expected-note {{undefined function 'f' cannot be used in a constant expression}}
245 
246   SS() = default; // expected-note {{'SS' is an immediate constructor because the default initializer of 'x' contains a call to a consteval function 'f' and that call is not a constant expression}}
247 };
248 
249 void test() {
250     [[maybe_unused]] SS s; // expected-error {{call to immediate function 'DefaultedUse::SS::SS' is not a constant expression}} \
251                            //  expected-note {{in call to 'SS()'}}
252 }
253 }
254 
255 namespace UserDefinedConstructors {
256 consteval int f(int x) {
257     return x;
258 }
259 extern int NonConst; // expected-note 2{{declared here}}
260 
261 struct ConstevalCtr {
262     int y;
263     int x = f(y);
264     consteval ConstevalCtr(int yy)
265     : y(f(yy)) {}
266 };
267 
268 ConstevalCtr c1(1);
269 ConstevalCtr c2(NonConst);
270 // expected-error@-1 {{call to consteval function 'UserDefinedConstructors::ConstevalCtr::ConstevalCtr' is not a constant expression}} \
271 // expected-note@-1 {{read of non-const variable 'NonConst' is not allowed in a constant expression}}
272 
273 struct ImmediateEscalating {
274     int y;
275     int x = f(y);
276     template<typename T>
277     constexpr ImmediateEscalating(T yy) // expected-note {{ImmediateEscalating<int>' is an immediate constructor because the initializer of 'y' contains a call to a consteval function 'f' and that call is not a constant expression}}
278     : y(f(yy)) {}
279 };
280 
281 ImmediateEscalating c3(1);
282 ImmediateEscalating c4(NonConst);
283 // expected-error@-1 {{call to immediate function 'UserDefinedConstructors::ImmediateEscalating::ImmediateEscalating<int>' is not a constant expression}} \
284 // expected-note@-1 {{read of non-const variable 'NonConst' is not allowed in a constant expression}}
285 
286 
287 struct NonEscalating {
288     int y;
289     int x = f(this->y); // expected-error {{call to consteval function 'UserDefinedConstructors::f' is not a constant expression}} \
290                         // expected-note  {{declared here}} \
291                         // expected-note  {{use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}}
292     constexpr NonEscalating(int yy) : y(yy) {} // expected-note {{in the default initializer of 'x'}}
293 };
294 NonEscalating s = {1};
295 
296 }
297 
298 namespace AggregateInit {
299 
300 consteval int f(int x) {
301     return x;
302 }
303 
304 struct S {
305     int i;
306     int j = f(i);
307 };
308 
309 constexpr S  test(auto) {
310     return {};
311 }
312 
313 S s = test(0);
314 
315 }
316 
317 namespace GlobalAggregateInit {
318 
319 consteval int f(int x) {
320     return x;
321 }
322 
323 struct S {
324     int i;
325     int j = f(i); // expected-error {{call to consteval function 'GlobalAggregateInit::f' is not a constant expression}} \
326                   // expected-note {{implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}} \
327                   // expected-note {{declared here}}
328 };
329 
330 S s(0); // expected-note {{in the default initializer of 'j'}}
331 
332 }
333 
334 namespace GH65985 {
335 consteval int invalid(); // expected-note 2{{declared here}}
336 constexpr int escalating(auto) {
337     return invalid();
338     // expected-note@-1 {{'escalating<int>' is an immediate function because its body contains a call to a consteval function 'invalid' and that call is not a constant expression}}
339     // expected-note@-2 2{{undefined function 'invalid' cannot be used in a constant expression}}
340 }
341 struct S {
342     static constexpr int a = escalating(0); // expected-note 2{{in call to}}
343     // expected-error@-1 {{call to immediate function 'GH65985::escalating<int>' is not a constant expression}}
344     // expected-error@-2 {{constexpr variable 'a' must be initialized by a constant expression}}
345 };
346 
347 }
348 
349 namespace GH66324 {
350 
351 consteval int allocate();  // expected-note  2{{declared here}}
352 
353 struct _Vector_base {
354   int b =  allocate(); // expected-note 2{{undefined function 'allocate' cannot be used in a constant expression}} \
355   // expected-error {{call to consteval function 'GH66324::allocate' is not a constant expression}} \
356   // expected-note  {{declared here}}
357 };
358 
359 template <typename>
360 struct vector : _Vector_base {
361   constexpr vector()
362   // expected-note@-1 {{'vector' is an immediate constructor because its body contains a call to a consteval function 'allocate' and that call is not a constant expression}}
363   : _Vector_base{} {} // expected-note {{in the default initializer of 'b'}}
364 };
365 
366 vector<void> v{};
367 // expected-error@-1 {{call to immediate function 'GH66324::vector<void>::vector' is not a constant expression}}
368 // expected-note@-2 {{in call to 'vector()'}}
369 
370 }
371 
372 
373 namespace GH82258 {
374 
375 template <class R, class Pred>
376 constexpr auto none_of(R&& r, Pred pred) -> bool { return true; }
377 
378 struct info { int value; };
379 consteval auto is_invalid(info i) -> bool { return false; }
380 constexpr info types[] = { {1}, {3}, {5}};
381 
382 static_assert(none_of(
383     types,
384     +[](info i) consteval {
385         return is_invalid(i);
386     }
387 ));
388 
389 static_assert(none_of(
390     types,
391     []{
392         return is_invalid;
393     }()
394 ));
395 
396 }
397 
398 #if __cplusplus >= 202302L
399 namespace lvalue_to_rvalue_init_from_heap {
400 
401 struct S {
402     int *value;
403     constexpr S(int v) : value(new int {v}) {}  // expected-note 2 {{heap allocation performed here}}
404     constexpr ~S() { delete value; }
405 };
406 consteval S fn() { return S(5); }
407 int fn2() { return 2; }  // expected-note {{declared here}}
408 
409 constexpr int a = *fn().value;
410 constinit int b = *fn().value;
411 const int c = *fn().value;
412 int d = *fn().value;
413 
414 constexpr int e = *fn().value + fn2(); // expected-error {{must be initialized by a constant expression}} \
415                                        // expected-error {{call to consteval function 'lvalue_to_rvalue_init_from_heap::fn' is not a constant expression}} \
416                                        // expected-note {{non-constexpr function 'fn2'}} \
417                                        // expected-note {{pointer to heap-allocated object}}
418 
419 int f = *fn().value + fn2();  // expected-error {{call to consteval function 'lvalue_to_rvalue_init_from_heap::fn' is not a constant expression}} \
420                               // expected-note {{pointer to heap-allocated object}}
421 }
422 #endif
423 
424 
425 #if __cplusplus >= 202302L
426 
427 namespace GH91509 {
428 
429 consteval int f(int) { return 0; }
430 
431 template<typename T>
432 constexpr int g(int x) {
433     if consteval {
434         return f(x);
435     }
436     if !consteval {}
437     else {
438         return f(x);
439     }
440     return 1;
441 }
442 
443 int h(int x) {
444     return g<void>(x);
445 }
446 }
447 
448 #endif
449 
450 
451 namespace GH91308 {
452     constexpr void f(auto) {
453         static_assert(false);
454     }
455     using R1 = decltype(&f<int>);
456 }
457 
458 namespace GH94935 {
459 
460 consteval void f(int) {}
461 consteval void undef(int); // expected-note {{declared here}}
462 
463 template<typename T>
464 struct G {
465     void g() {
466         GH94935::f(T::fn());
467         GH94935::f(T::undef2());  // expected-error {{call to consteval function 'GH94935::f' is not a constant expression}} \
468                                   // expected-note  {{undefined function 'undef2' cannot be used in a constant expression}}
469         GH94935::undef(T::fn());  // expected-error {{call to consteval function 'GH94935::undef' is not a constant expression}} \
470                                   // expected-note  {{undefined function 'undef' cannot be used in a constant expression}}
471     }
472 };
473 
474 struct X {
475     static consteval int fn() { return 0; }
476     static consteval int undef2();  // expected-note {{declared here}}
477 
478 };
479 
480 void test() {
481     G<X>{}.g(); // expected-note {{instantiation}}
482 }
483 
484 
485 template<typename T>
486 void g() {
487     auto l = []{
488         ::f(T::fn());
489     };
490 }
491 
492 struct Y {
493     static int fn();
494 };
495 
496 template void g<Y>();
497 
498 }
499 
500 namespace GH112677 {
501 
502 class ConstEval {
503  public:
504   consteval ConstEval(int); // expected-note 2{{declared here}}
505 };
506 
507 struct TemplateCtor {
508     ConstEval val;
509     template <class Anything = int> constexpr
510     TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}}
511 };
512 struct C : TemplateCtor {
513     using TemplateCtor::TemplateCtor; // expected-note {{in call to 'TemplateCtor<int>(0)'}}
514 };
515 
516 C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}}
517 // expected-error@-1 {{call to immediate function 'GH112677::C::TemplateCtor' is not a constant expression}}
518 
519 struct SimpleCtor { constexpr SimpleCtor(int) {}};
520 struct D : SimpleCtor {
521     int y = 10;
522     ConstEval x = y; // expected-note {{undefined constructor 'ConstEval'}}
523     using SimpleCtor::SimpleCtor;
524     //expected-note@-1 {{'SimpleCtor' is an immediate constructor because the default initializer of 'x' contains a call to a consteval constructor 'ConstEval' and that call is not a constant expression}}
525 };
526 
527 D d(0); // expected-note {{in implicit initialization for inherited constructor of 'D'}}
528 // expected-error@-1 {{call to immediate function 'GH112677::D::SimpleCtor' is not a constant expression}}
529 
530 }
531 
532 namespace GH123405 {
533 
534 consteval void fn() {}
535 
536 template <typename>
537 constexpr auto tfn(int) {
538     auto p = &fn;  // expected-note {{'tfn<int>' is an immediate function because its body evaluates the address of a consteval function 'fn'}}
539     return p;
540 }
541 
542 void g() {
543    int a; // expected-note {{declared here}}
544    tfn<int>(a); // expected-error {{call to immediate function 'GH123405::tfn<int>' is not a constant expression}}\
545                 // expected-note {{read of non-const variable 'a' is not allowed in a constant expression}}
546 }
547 } // namespace GH123405
548 
549 namespace GH118000 {
550 consteval int baz() { return 0;}
551 struct S {
552     int mSize = baz();
553 };
554 
555 consteval void bar() {
556     S s;
557 }
558 
559 void foo() {
560     S s;
561 }
562 } // namespace GH118000
563 
564 namespace GH119046 {
565 
566 template <typename Cls> constexpr auto tfn(int) {
567   return (unsigned long long)(&Cls::sfn);
568   //expected-note@-1 {{'tfn<GH119046::S>' is an immediate function because its body evaluates the address of a consteval function 'sfn'}}
569 };
570 struct S { static consteval void sfn() {} };
571 
572 int f() {
573   int a = 0; // expected-note{{declared here}}
574   return tfn<S>(a);
575   //expected-error@-1 {{call to immediate function 'GH119046::tfn<GH119046::S>' is not a constant expression}}
576   //expected-note@-2 {{read of non-const variable 'a' is not allowed in a constant expression}}
577 }
578 }
579