Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / AST / Interp / cxx20.cpp
blob50a7c02925878d5d6954a49678b9c0e1de1f88a8
1 // RUN: %clang_cc1 -fcxx-exceptions -fexperimental-new-constant-interpreter -std=c++20 -verify %s
2 // RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -verify=ref %s
4 void test_alignas_operand() {
5 alignas(8) char dummy;
6 static_assert(__alignof(dummy) == 8);
9 constexpr int getMinus5() {
10 int a = 10;
11 a = -5;
12 int *p = &a;
13 return *p;
15 static_assert(getMinus5() == -5, "");
17 constexpr int assign() {
18 int m = 10;
19 int k = 12;
21 m = (k = 20);
23 return m;
25 static_assert(assign() == 20, "");
28 constexpr int pointerAssign() {
29 int m = 10;
30 int *p = &m;
32 *p = 12; // modifies m
34 return m;
36 static_assert(pointerAssign() == 12, "");
38 constexpr int pointerDeref() {
39 int m = 12;
40 int *p = &m;
42 return *p;
44 static_assert(pointerDeref() == 12, "");
46 constexpr int pointerAssign2() {
47 int m = 10;
48 int *p = &m;
49 int **pp = &p;
51 **pp = 12;
53 int v = **pp;
55 return v;
57 static_assert(pointerAssign2() == 12, "");
59 constexpr int unInitLocal() {
60 int a;
61 return a; // ref-note {{read of uninitialized object}} \
62 // expected-note {{read of uninitialized object}}
64 static_assert(unInitLocal() == 0, ""); // ref-error {{not an integral constant expression}} \
65 // ref-note {{in call to 'unInitLocal()'}} \
66 // expected-error {{not an integral constant expression}} \
67 // expected-note {{in call to 'unInitLocal()'}} \
69 constexpr int initializedLocal() {
70 int a;
71 a = 20;
72 return a;
74 static_assert(initializedLocal() == 20);
76 constexpr int initializedLocal2() {
77 int a[2];
78 return *a; // expected-note {{read of uninitialized object is not allowed in a constant expression}} \
79 // ref-note {{read of uninitialized object is not allowed in a constant expression}}
81 static_assert(initializedLocal2() == 20); // expected-error {{not an integral constant expression}} \
82 // expected-note {{in call to}} \
83 // ref-error {{not an integral constant expression}} \
84 // ref-note {{in call to}}
87 struct Int { int a; };
88 constexpr int initializedLocal3() {
89 Int i;
90 return i.a; // ref-note {{read of uninitialized object is not allowed in a constant expression}} \
91 // expected-note {{read of uninitialized object}}
93 static_assert(initializedLocal3() == 20); // expected-error {{not an integral constant expression}} \
94 // expected-note {{in call to}} \
95 // ref-error {{not an integral constant expression}} \
96 // ref-note {{in call to}}
100 #if 0
101 // FIXME: This code should be rejected because we pass an uninitialized value
102 // as a function parameter.
103 constexpr int inc(int a) { return a + 1; }
104 constexpr int f() {
105 int i;
106 return inc(i);
108 static_assert(f());
109 #endif
111 /// Distinct literals have disctinct addresses.
112 /// see https://github.com/llvm/llvm-project/issues/58754
113 constexpr auto foo(const char *p) { return p; }
114 constexpr auto p1 = "test1";
115 constexpr auto p2 = "test2";
117 constexpr bool b1 = foo(p1) == foo(p1);
118 static_assert(b1);
120 constexpr bool b2 = foo(p1) == foo(p2); // ref-error {{must be initialized by a constant expression}} \
121 // ref-note {{comparison of addresses of literals}} \
122 // ref-note {{declared here}}
123 static_assert(!b2); // ref-error {{not an integral constant expression}} \
124 // ref-note {{not a constant expression}}
126 constexpr auto name1() { return "name1"; }
127 constexpr auto name2() { return "name2"; }
129 constexpr auto b3 = name1() == name1();
130 static_assert(b3);
131 constexpr auto b4 = name1() == name2(); // ref-error {{must be initialized by a constant expression}} \
132 // ref-note {{has unspecified value}} \
133 // ref-note {{declared here}}
134 static_assert(!b4); // ref-error {{not an integral constant expression}} \
135 // ref-note {{not a constant expression}}
137 namespace UninitializedFields {
138 class A {
139 public:
140 int a; // expected-note 4{{subobject declared here}} \
141 // ref-note 4{{subobject declared here}}
142 constexpr A() {}
144 constexpr A a; // expected-error {{must be initialized by a constant expression}} \
145 // expected-note {{subobject 'a' is not initialized}} \
146 // ref-error {{must be initialized by a constant expression}} \
147 // ref-note {{subobject 'a' is not initialized}}
148 constexpr A aarr[2]; // expected-error {{must be initialized by a constant expression}} \
149 // expected-note {{subobject 'a' is not initialized}} \
150 // ref-error {{must be initialized by a constant expression}} \
151 // ref-note {{subobject 'a' is not initialized}}
152 class F {
153 public:
154 int f; // expected-note 3{{subobject declared here}} \
155 // ref-note 3{{subobject declared here}}
157 constexpr F() {}
158 constexpr F(bool b) {
159 if (b)
160 f = 42;
164 constexpr F foo[2] = {true}; // expected-error {{must be initialized by a constant expression}} \
165 // expected-note {{subobject 'f' is not initialized}} \
166 // ref-error {{must be initialized by a constant expression}} \
167 // ref-note {{subobject 'f' is not initialized}}
168 constexpr F foo2[3] = {true, false, true}; // expected-error {{must be initialized by a constant expression}} \
169 // expected-note {{subobject 'f' is not initialized}} \
170 // ref-error {{must be initialized by a constant expression}} \
171 // ref-note {{subobject 'f' is not initialized}}
172 constexpr F foo3[3] = {true, true, F()}; // expected-error {{must be initialized by a constant expression}} \
173 // expected-note {{subobject 'f' is not initialized}} \
174 // ref-error {{must be initialized by a constant expression}} \
175 // ref-note {{subobject 'f' is not initialized}}
179 class Base {
180 public:
181 bool b;
182 int a; // expected-note {{subobject declared here}} \
183 // ref-note {{subobject declared here}}
184 constexpr Base() : b(true) {}
187 class Derived : public Base {
188 public:
189 constexpr Derived() : Base() {} };
191 constexpr Derived D; // expected-error {{must be initialized by a constant expression}} \
192 // expected-note {{subobject 'a' is not initialized}} \
193 // ref-error {{must be initialized by a constant expression}} \
194 // ref-note {{subobject 'a' is not initialized}}
196 class C2 {
197 public:
198 A a;
199 constexpr C2() {} };
200 constexpr C2 c2; // expected-error {{must be initialized by a constant expression}} \
201 // expected-note {{subobject 'a' is not initialized}} \
202 // ref-error {{must be initialized by a constant expression}} \
203 // ref-note {{subobject 'a' is not initialized}}
205 class C3 {
206 public:
207 A a[2];
208 constexpr C3() {}
210 constexpr C3 c3; // expected-error {{must be initialized by a constant expression}} \
211 // expected-note {{subobject 'a' is not initialized}} \
212 // ref-error {{must be initialized by a constant expression}} \
213 // ref-note {{subobject 'a' is not initialized}}
215 class C4 {
216 public:
217 bool B[2][3]; // expected-note {{subobject declared here}} \
218 // ref-note {{subobject declared here}}
219 constexpr C4(){}
221 constexpr C4 c4; // expected-error {{must be initialized by a constant expression}} \
222 // expected-note {{subobject 'B' is not initialized}} \
223 // ref-error {{must be initialized by a constant expression}} \
224 // ref-note {{subobject 'B' is not initialized}}
227 namespace ConstThis {
228 class Foo {
229 const int T = 12; // expected-note {{declared const here}} \
230 // ref-note {{declared const here}}
231 int a;
232 public:
233 constexpr Foo() { // expected-note {{declared here}}
234 this->a = 10;
235 T = 13; // expected-error {{cannot assign to non-static data member 'T' with const-qualified type}} \
236 // ref-error {{cannot assign to non-static data member 'T' with const-qualified type}}
239 constexpr Foo F; // expected-error {{must be initialized by a constant expression}} \
240 // FIXME: The following note is wrong. \
241 // expected-note {{undefined constructor 'Foo' cannot be used in a constant expression}} \
242 // ref-error {{must be initialized by a constant expression}}
245 class FooDtor {
246 int a;
247 public:
248 constexpr FooDtor() {
249 this->a = 10;
251 constexpr ~FooDtor() {
252 this->a = 12;
256 constexpr int foo() {
257 const FooDtor f;
258 return 0;
260 static_assert(foo() == 0);
262 template <bool Good>
263 struct ctor_test {
264 int a = 0;
266 constexpr ctor_test() {
267 if (Good)
268 a = 10;
269 int local = 100 / a; // expected-note {{division by zero}} \
270 // ref-note {{division by zero}}
274 template <bool Good>
275 struct dtor_test {
276 int a = 0;
278 constexpr dtor_test() = default;
279 constexpr ~dtor_test() {
280 if (Good)
281 a = 10;
282 int local = 100 / a; // expected-note {{division by zero}} \
283 // ref-note {{division by zero}}
287 constexpr ctor_test<true> good_ctor;
288 constexpr dtor_test<true> good_dtor;
290 constexpr ctor_test<false> bad_ctor; // expected-error {{must be initialized by a constant expression}} \
291 // expected-note {{in call to}} \
292 // ref-error {{must be initialized by a constant expression}} \
293 // ref-note {{in call to}}
294 constexpr dtor_test<false> bad_dtor; // expected-error {{must have constant destruction}} \
295 // expected-note {{in call to}} \
296 // ref-error {{must have constant destruction}} \
297 // ref-note {{in call to}}
300 namespace BaseInit {
301 struct Base {
302 int a;
305 struct Intermediate : Base {
306 int b;
309 struct Final : Intermediate {
310 int c;
312 constexpr Final(int a, int b, int c) : c(c) {}
315 static_assert(Final{1, 2, 3}.c == 3, ""); // OK
316 static_assert(Final{1, 2, 3}.a == 0, ""); // expected-error {{not an integral constant expression}} \
317 // expected-note {{read of uninitialized object}} \
318 // ref-error {{not an integral constant expression}} \
319 // ref-note {{read of uninitialized object}}
322 struct Mixin {
323 int b;
325 constexpr Mixin() = default;
326 constexpr Mixin(int b) : b(b) {}
329 struct Final2 : Base, Mixin {
330 int c;
332 constexpr Final2(int a, int b, int c) : Mixin(b), c(c) {}
333 constexpr Final2(int a, int b, int c, bool) : c(c) {}
336 static_assert(Final2{1, 2, 3}.c == 3, ""); // OK
337 static_assert(Final2{1, 2, 3}.b == 2, ""); // OK
338 static_assert(Final2{1, 2, 3}.a == 0, ""); // expected-error {{not an integral constant expression}} \
339 // expected-note {{read of uninitialized object}} \
340 // ref-error {{not an integral constant expression}} \
341 // ref-note {{read of uninitialized object}}
344 struct Mixin3 {
345 int b;
348 struct Final3 : Base, Mixin3 {
349 int c;
351 constexpr Final3(int a, int b, int c) : c(c) { this->b = b; }
352 constexpr Final3(int a, int b, int c, bool) : c(c) {}
355 static_assert(Final3{1, 2, 3}.c == 3, ""); // OK
356 static_assert(Final3{1, 2, 3}.b == 2, ""); // OK
357 static_assert(Final3{1, 2, 3}.a == 0, ""); // expected-error {{not an integral constant expression}} \
358 // expected-note {{read of uninitialized object}} \
359 // ref-error {{not an integral constant expression}} \
360 // ref-note {{read of uninitialized object}}
363 namespace Destructors {
365 class Inc final {
366 public:
367 int &I;
368 constexpr Inc(int &I) : I(I) {}
369 constexpr ~Inc() {
370 I++;
374 class Dec final {
375 public:
376 int &I;
377 constexpr Dec(int &I) : I(I) {}
378 constexpr ~Dec() {
379 I--;
385 constexpr int m() {
386 int i = 0;
388 Inc f1(i);
389 Inc f2(i);
390 Inc f3(i);
392 return i;
394 static_assert(m() == 3, "");
397 constexpr int C() {
398 int i = 0;
400 while (i < 10) {
401 Inc inc(i);
402 continue;
403 Dec dec(i);
405 return i;
407 static_assert(C() == 10, "");
410 constexpr int D() {
411 int i = 0;
414 Inc i1(i);
416 Inc i2(i);
417 return i;
421 return i;
423 static_assert(D() == 0, "");
425 constexpr int E() {
426 int i = 0;
428 for(;;) {
429 Inc i1(i);
430 break;
432 return i;
434 static_assert(E() == 1, "");
437 /// FIXME: This should be rejected, since we call the destructor
438 /// twice. However, GCC doesn't care either.
439 constexpr int ManualDtor() {
440 int i = 0;
442 Inc I(i); // ref-note {{destroying object 'I' whose lifetime has already ended}}
443 I.~Inc();
445 return i;
447 static_assert(ManualDtor() == 1, ""); // expected-error {{static assertion failed}} \
448 // expected-note {{evaluates to '2 == 1'}} \
449 // ref-error {{not an integral constant expression}} \
450 // ref-note {{in call to 'ManualDtor()'}}
452 constexpr void doInc(int &i) {
453 Inc I(i);
454 return;
456 constexpr int testInc() {
457 int i = 0;
458 doInc(i);
459 return i;
461 static_assert(testInc() == 1, "");
462 constexpr void doInc2(int &i) {
463 Inc I(i);
464 // No return statement.
466 constexpr int testInc2() {
467 int i = 0;
468 doInc2(i);
469 return i;
471 static_assert(testInc2() == 1, "");
474 namespace DtorOrder {
475 class A {
476 public:
477 int &I;
478 constexpr A(int &I) : I(I) {}
479 constexpr ~A() {
480 I = 1337;
484 class B : public A {
485 public:
486 constexpr B(int &I) : A(I) {}
487 constexpr ~B() {
488 I = 42;
492 constexpr int foo() {
493 int i = 0;
495 B b(i);
497 return i;
500 static_assert(foo() == 1337);
503 class FieldDtor1 {
504 public:
505 Inc I1;
506 Inc I2;
507 constexpr FieldDtor1(int &I) : I1(I), I2(I){}
510 constexpr int foo2() {
511 int i = 0;
513 FieldDtor1 FD1(i);
515 return i;
518 static_assert(foo2() == 2);
520 class FieldDtor2 {
521 public:
522 Inc Incs[3];
523 constexpr FieldDtor2(int &I) : Incs{Inc(I), Inc(I), Inc(I)} {}
526 constexpr int foo3() {
527 int i = 0;
529 FieldDtor2 FD2(i);
531 return i;
534 static_assert(foo3() == 3);
536 struct ArrD {
537 int index;
538 int *arr;
539 int &p;
540 constexpr ~ArrD() {
541 arr[p] = index;
542 ++p;
545 constexpr bool ArrayOrder() {
546 int order[3] = {0, 0, 0};
547 int p = 0;
549 ArrD ds[3] = {
550 {1, order, p},
551 {2, order, p},
552 {3, order, p},
554 // ds will be destroyed.
556 return order[0] == 3 && order[1] == 2 && order[2] == 1;
558 static_assert(ArrayOrder());
561 // Static members aren't destroyed.
562 class Dec2 {
563 public:
564 int A = 0;
565 constexpr ~Dec2() {
566 A++;
569 class Foo {
570 public:
571 static constexpr Dec2 a;
572 static Dec2 b;
574 static_assert(Foo::a.A == 0);
575 constexpr bool f() {
576 Foo f;
577 return true;
579 static_assert(Foo::a.A == 0);
580 static_assert(f());
581 static_assert(Foo::a.A == 0);
584 struct NotConstexpr {
585 NotConstexpr() {}
586 ~NotConstexpr() {}
589 struct Outer {
590 constexpr Outer() = default;
591 constexpr ~Outer();
593 constexpr int foo() {
594 return 12;
597 constexpr int bar()const {
598 return Outer{}.foo();
601 static NotConstexpr Val;
604 constexpr Outer::~Outer() {}
606 constexpr Outer O;
607 static_assert(O.bar() == 12);
610 namespace BaseAndFieldInit {
611 struct A {
612 int a;
615 struct B : A {
616 int b;
619 struct C : B {
620 int c;
623 constexpr C c = {1,2,3};
624 static_assert(c.a == 1 && c.b == 2 && c.c == 3);
627 namespace ImplicitFunction {
628 struct A {
629 int a; // ref-note {{subobject declared here}}
632 constexpr int callMe() {
633 A a;
634 A b{12};
636 /// The operator= call here will fail and the diagnostics should be fine.
637 b = a; // ref-note {{subobject 'a' is not initialized}} \
638 // ref-note {{in call to}} \
639 // expected-note {{read of uninitialized object}} \
640 // expected-note {{in call to}}
642 return 1;
644 static_assert(callMe() == 1, ""); // ref-error {{not an integral constant expression}} \
645 // ref-note {{in call to 'callMe()'}} \
646 // expected-error {{not an integral constant expression}} \
647 // expected-note {{in call to 'callMe()'}}
650 /// FIXME: Unfortunately, the similar tests in test/SemaCXX/{compare-cxx2a.cpp use member pointers,
651 /// which we don't support yet.
652 namespace std {
653 class strong_ordering {
654 public:
655 int n;
656 static const strong_ordering less, equal, greater;
657 constexpr bool operator==(int n) const noexcept { return this->n == n;}
658 constexpr bool operator!=(int n) const noexcept { return this->n != n;}
660 constexpr strong_ordering strong_ordering::less = {-1};
661 constexpr strong_ordering strong_ordering::equal = {0};
662 constexpr strong_ordering strong_ordering::greater = {1};
664 class partial_ordering {
665 public:
666 long n;
667 static const partial_ordering less, equal, greater, equivalent, unordered;
668 constexpr bool operator==(long n) const noexcept { return this->n == n;}
669 constexpr bool operator!=(long n) const noexcept { return this->n != n;}
671 constexpr partial_ordering partial_ordering::less = {-1};
672 constexpr partial_ordering partial_ordering::equal = {0};
673 constexpr partial_ordering partial_ordering::greater = {1};
674 constexpr partial_ordering partial_ordering::equivalent = {0};
675 constexpr partial_ordering partial_ordering::unordered = {-127};
676 } // namespace std
678 namespace ThreeWayCmp {
679 static_assert(1 <=> 2 == -1, "");
680 static_assert(1 <=> 1 == 0, "");
681 static_assert(2 <=> 1 == 1, "");
682 static_assert(1.0 <=> 2.f == -1, "");
683 static_assert(1.0 <=> 1.0 == 0, "");
684 static_assert(2.0 <=> 1.0 == 1, "");
685 constexpr int k = (1 <=> 1, 0); // expected-warning {{comparison result unused}} \
686 // ref-warning {{comparison result unused}}
687 static_assert(k== 0, "");
689 /// Pointers.
690 constexpr int a[] = {1,2,3};
691 constexpr int b[] = {1,2,3};
692 constexpr const int *pa1 = &a[1];
693 constexpr const int *pa2 = &a[2];
694 constexpr const int *pb1 = &b[1];
695 static_assert(pa1 <=> pb1 != 0, ""); // expected-error {{not an integral constant expression}} \
696 // expected-note {{has unspecified value}} \
697 // ref-error {{not an integral constant expression}} \
698 // ref-note {{has unspecified value}}
699 static_assert(pa1 <=> pa1 == 0, "");
700 static_assert(pa1 <=> pa2 == -1, "");
701 static_assert(pa2 <=> pa1 == 1, "");
704 namespace ConstexprArrayInitLoopExprDestructors
706 struct Highlander {
707 int *p = 0;
708 constexpr Highlander() {}
709 constexpr void set(int *p) { this->p = p; ++*p; if (*p != 1) throw "there can be only one"; }
710 constexpr ~Highlander() { --*p; }
713 struct X {
714 int *p;
715 constexpr X(int *p) : p(p) {}
716 constexpr X(const X &x, Highlander &&h = Highlander()) : p(x.p) {
717 h.set(p);
721 constexpr int f() {
722 int n = 0;
723 X x[3] = {&n, &n, &n};
724 auto [a, b, c] = x;
725 return n;
728 static_assert(f() == 0);
731 namespace NonPrimitiveOpaqueValue
733 struct X {
734 int x;
735 constexpr operator bool() const { return x != 0; }
738 constexpr int ternary() { return X(0) ?: X(0); }
740 static_assert(!ternary(), "");
743 namespace TryCatch {
744 constexpr int foo() {
745 int a = 10;
746 try {
747 ++a;
748 } catch(int m) {
749 --a;
751 return a;
753 static_assert(foo() == 11);