[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaCXX / cxx2b-consteval-propagate.cpp
blob378414f136172911b29ac7444d84bca58452881b
1 // RUN: %clang_cc1 -std=c++2a -Wno-unused-value %s -verify
2 // RUN: %clang_cc1 -std=c++2b -Wno-unused-value %s -verify
4 consteval int id(int i) { return i; }
5 constexpr char id(char c) { return c; }
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}}
12 namespace examples {
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}}
17 static_assert(f(3) == 6); // ok
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
24 template <typename T, typename F>
25 constexpr bool is_not(T t, F f) {
26 return not f(t);
29 consteval bool is_even(int i) { return i % 2 == 0; }
31 static_assert(is_not(5, is_even));
33 int x = 0; // expected-note {{declared here}}
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;
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>();
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>()'}}
50 struct A {
51 int x;
52 int y = id(x);
55 template <typename T>
56 constexpr int k(int) {
57 return A(42).y;
62 namespace nested {
64 template <typename T>
65 constexpr int fdupe(T t) {
66 return id(t);
69 struct a {
70 constexpr a(int) { }
73 a aa(fdupe<int>((f<int>(7))));
75 template <typename T>
76 constexpr int foo(T t); // expected-note {{declared here}}
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}}
83 namespace e2{
84 template <typename T>
85 constexpr int f(T t);
86 auto a = &f<char>;
87 auto b = &f<int>;
90 namespace forward_declare_constexpr{
91 template <typename T>
92 constexpr int f(T t);
94 auto a = &f<char>;
95 auto b = &f<int>;
97 template <typename T>
98 constexpr int f(T t) {
99 return id(0);
103 namespace forward_declare_consteval{
104 template <typename T>
105 constexpr int f(T t);
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}}
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}}
117 namespace constructors {
118 consteval int f(int) {
119 return 0;
121 struct S {
122 constexpr S(auto i) {
123 f(i);
126 constexpr void g(auto i) {
127 [[maybe_unused]] S s{i};
129 void test() {
130 g(0);
134 namespace aggregate {
135 consteval int f(int);
136 struct S{
137 int a = 0;
138 int b = f(a);
141 constexpr bool test(auto i) {
142 S s{i};
143 return s.b == 2 *i;
145 consteval int f(int i) {
146 return 2 * i;
149 void test() {
150 static_assert(test(42));
155 namespace ConstevalConstructor{
156 int x = 0; // expected-note {{declared here}}
157 struct S {
158 consteval S(int) {};
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;
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}}
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}}
177 constexpr S immediate(auto) {
178 return S{};
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)'}}
185 consteval int f(int i) {
186 return i;
188 consteval void test() {
189 constexpr S s = immediate(0);
190 static_assert(s.x == 42);
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;
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();
209 SS::SS(){} // expected-note {{in the default initializer of 'x'}}
211 consteval int f2(int x) {
212 if (!__builtin_is_constant_evaluated()) side_effect();
213 return x;
215 struct S2 {
216 int x = f2(0);
217 constexpr S2();
220 constexpr S2::S2(){}
221 S2 s = {};
222 constinit S2 s2 = {};
224 struct S3 {
225 int x = f2(0);
226 S3();
228 S3::S3(){}
232 namespace Defaulted {
233 consteval int f(int x);
234 struct SS {
235 int x = f(0);
236 SS() = default;
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}}
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}}
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()'}}
255 namespace UserDefinedConstructors {
256 consteval int f(int x) {
257 return x;
259 extern int NonConst; // expected-note 2{{declared here}}
261 struct ConstevalCtr {
262 int y;
263 int x = f(y);
264 consteval ConstevalCtr(int yy)
265 : y(f(yy)) {}
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}}
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)) {}
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}}
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'}}
294 NonEscalating s = {1};
298 namespace AggregateInit {
300 consteval int f(int x) {
301 return x;
304 struct S {
305 int i;
306 int j = f(i);
309 constexpr S test(auto) {
310 return {};
313 S s = test(0);
317 namespace GlobalAggregateInit {
319 consteval int f(int x) {
320 return x;
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}}
330 S s(0); // expected-note {{in the default initializer of 'j'}}
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}}
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}}
349 namespace GH66324 {
351 consteval int allocate(); // expected-note 2{{declared here}}
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}}
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'}}
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()'}}
373 namespace GH82258 {
375 template <class R, class Pred>
376 constexpr auto none_of(R&& r, Pred pred) -> bool { return true; }
378 struct info { int value; };
379 consteval auto is_invalid(info i) -> bool { return false; }
380 constexpr info types[] = { {1}, {3}, {5}};
382 static_assert(none_of(
383 types,
384 +[](info i) consteval {
385 return is_invalid(i);
389 static_assert(none_of(
390 types,
392 return is_invalid;
398 #if __cplusplus >= 202302L
399 namespace lvalue_to_rvalue_init_from_heap {
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; }
406 consteval S fn() { return S(5); }
407 int fn2() { return 2; } // expected-note {{declared here}}
409 constexpr int a = *fn().value;
410 constinit int b = *fn().value;
411 const int c = *fn().value;
412 int d = *fn().value;
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}}
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}}
422 #endif
425 #if __cplusplus >= 202302L
427 namespace GH91509 {
429 consteval int f(int) { return 0; }
431 template<typename T>
432 constexpr int g(int x) {
433 if consteval {
434 return f(x);
436 if !consteval {}
437 else {
438 return f(x);
440 return 1;
443 int h(int x) {
444 return g<void>(x);
448 #endif
451 namespace GH91308 {
452 constexpr void f(auto) {
453 static_assert(false);
455 using R1 = decltype(&f<int>);
458 namespace GH94935 {
460 consteval void f(int) {}
461 consteval void undef(int); // expected-note {{declared here}}
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}}
474 struct X {
475 static consteval int fn() { return 0; }
476 static consteval int undef2(); // expected-note {{declared here}}
480 void test() {
481 G<X>{}.g(); // expected-note {{instantiation}}
485 template<typename T>
486 void g() {
487 auto l = []{
488 ::f(T::fn());
492 struct Y {
493 static int fn();
496 template void g<Y>();