990 lines · cpp
1// RUN: %clang_cc1 -verify=expected,both %s -fexperimental-new-constant-interpreter2// RUN: %clang_cc1 -std=c++20 -verify=expected,both %s -fexperimental-new-constant-interpreter3// RUN: %clang_cc1 -verify=ref,both %s4// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s5 6#define assert_active(F) if (!__builtin_is_within_lifetime(&F)) (1/0);7#define assert_inactive(F) if ( __builtin_is_within_lifetime(&F)) (1/0);8 9union U {10 int a;11 int b;12};13 14constexpr U a = {12};15static_assert(a.a == 12, "");16static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \17 // both-note {{read of member 'b' of union with active member 'a'}}18union U1 {19 int i;20 float f = 3.0f;21};22constexpr U1 u1{};23static_assert(u1.f == 3.0, "");24static_assert(u1.i == 1, ""); // both-error {{not an integral constant expression}} \25 // both-note {{read of member 'i' of union with active member 'f'}}26 27 28 29union A {30 int a;31 double d;32};33constexpr A aa = {1, 2.0}; // both-error {{excess elements in union initializer}}34constexpr A ab = {.d = 1.0};35static_assert(ab.d == 1.0, "");36static_assert(ab.a == 1, ""); // both-error {{not an integral constant expression}} \37 // both-note {{read of member 'a' of union with active member 'd'}}38 39 40namespace Empty {41 union E {};42 constexpr E e{};43}44 45namespace SimpleStore {46 union A {47 int a;48 int b;49 };50 constexpr int foo() {51 A a{.b = 4};52 a.b = 10;53 return a.b;54 }55 static_assert(foo() == 10, "");56 57 constexpr int empty() {58 A a{}; /// Just test that this works.59 return 10;60 }61 static_assert(empty() == 10, "");62}63 64namespace ZeroInit {65 struct S { int m; };66 union Z {67 float f;68 };69 70 constexpr Z z{};71 static_assert(z.f == 0.0, "");72}73 74namespace DefaultInit {75 union U1 {76 constexpr U1() {}77 int a, b = 42;78 };79 80 constexpr U1 u1; /// OK.81 82 constexpr int foo() {83 U1 u;84 return u.a; // both-note {{read of member 'a' of union with active member 'b'}}85 }86 static_assert(foo() == 42); // both-error {{not an integral constant expression}} \87 // both-note {{in call to}}88}89 90#if __cplusplus >= 202002L91namespace SimpleActivate {92 constexpr int foo() { // both-error {{never produces a constant expression}}93 union {94 int a;95 int b;96 } Z;97 98 Z.a = 10;99 Z.b = 20;100 return Z.a; // both-note 2{{read of member 'a' of union with active member 'b'}}101 }102 static_assert(foo() == 20); // both-error {{not an integral constant expression}} \103 // both-note {{in call to}}104 105 constexpr int foo2() {106 union {107 int a;108 int b;109 } Z;110 111 Z.a = 10;112 Z.b = 20;113 return Z.b;114 }115 static_assert(foo2() == 20);116 117 118 constexpr int foo3() {119 union {120 struct {121 float x,y;122 } a;123 int b;124 } Z;125 126 Z.a.y = 10;127 128 return Z.a.x; // both-note {{read of uninitialized object}}129 }130 static_assert(foo3() == 10); // both-error {{not an integral constant expression}} \131 // both-note {{in call to}}132 133 constexpr int foo4() {134 union {135 struct {136 float x,y;137 } a;138 int b;139 } Z;140 141 Z.a.x = 100;142 Z.a.y = 10;143 144 return Z.a.x;145 }146 static_assert(foo4() == 100);147}148 149namespace IndirectFieldDecl {150 struct C {151 union { int a, b = 2, c; };152 union { int d, e = 5, f; };153 constexpr C() : a(1) {}154 };155 static_assert(C().a == 1, "");156}157 158namespace UnionDtor {159 160 union U {161 int *I;162 constexpr U(int *I) : I(I) {}163 constexpr ~U() {164 *I = 10;165 }166 };167 168 constexpr int foo() {169 int a = 100;170 {171 U u(&a);172 }173 return a;174 }175 static_assert(foo() == 10);176}177 178namespace UnionMemberDtor {179 class UM {180 public:181 int &I;182 constexpr UM(int &I) : I(I) {}183 constexpr ~UM() { I = 200; }184 };185 186 union U {187 UM um;188 constexpr U(int &I) : um(I) {}189 constexpr ~U() {190 }191 };192 193 constexpr int foo() {194 int a = 100;195 {196 U u(a);197 }198 199 return a;200 }201 static_assert(foo() == 100);202}203 204namespace Nested {205 union U {206 int a;207 int b;208 };209 210 union U2 {211 U u;212 U u2;213 int x;214 int y;215 };216 217 constexpr int foo() { // both-error {{constexpr function never produces a constant expression}}218 U2 u;219 u.u.a = 10;220 int a = u.y; // both-note 2{{read of member 'y' of union with active member 'u' is not allowed in a constant expression}}221 222 return 1;223 }224 static_assert(foo() == 1); // both-error {{not an integral constant expression}} \225 // both-note {{in call to}}226 227 constexpr int foo2() {228 U2 u;229 u.u.a = 10;230 return u.u.a;231 }232 static_assert(foo2() == 10);233 234 consteval int foo3() { // both-error {{function never produces a constant expression}}235 U2 u;236 /// No active field.237 assert_active(u);238 assert_inactive(u.u);239 assert_inactive(u.u2);240 assert_inactive(u.x);241 assert_inactive(u.y);242 243 u.u.a = 10;244 assert_active(u);245 assert_active(u.u);246 assert_active(u.u.a);247 assert_inactive(u.u.b);248 assert_inactive(u.u2);249 assert_inactive(u.x);250 assert_inactive(u.y);251 252 int a = u.u.b; // both-note 2{{read of member 'b' of union with active member 'a' is not allowed in a constant expression}}253 254 return 1;255 }256 static_assert(foo3() == 1); // both-error {{not an integral constant expression}} \257 // both-note {{in call to}}258 259 constexpr int foo4() { // both-error {{constexpr function never produces a constant expression}}260 U2 u;261 262 u.x = 10;263 264 return u.u.a; // both-note 2{{read of member 'u' of union with active member 'x' is not allowed in a constant expression}}265 }266 static_assert(foo4() == 1); // both-error {{not an integral constant expression}} \267 // both-note {{in call to}}268 269}270 271 272namespace Zeroing {273 struct non_trivial_constructor {274 constexpr non_trivial_constructor() : x(100) {}275 int x;276 };277 union U2 {278 int a{1000};279 non_trivial_constructor b;280 };281 282 static_assert(U2().b.x == 100, ""); // both-error {{not an integral constant expression}} \283 // both-note {{read of member 'b' of union with active member 'a'}}284 285 union { int a; int b; } constexpr u1{};286 static_assert(u1.a == 0, "");287 static_assert(u1.b == 0, ""); // both-error {{not an integral constant expression}} \288 // both-note {{read of member 'b' of union with active member 'a'}}289 290 union U { int a; int b; } constexpr u2 = U();291 static_assert(u2.a == 0, "");292 static_assert(u2.b == 0, ""); // both-error {{not an integral constant expression}} \293 // both-note {{read of member 'b' of union with active member 'a'}}294 295 296 struct F {int x; int y; };297 union { F a; int b; } constexpr u3{};298 static_assert(u3.a.x == 0, "");299 300 union U4 { F a; int b; } constexpr u4 = U4();301 static_assert(u4.a.x == 0, "");302 303 union { int a[5]; int b; } constexpr u5{};304 static_assert(u5.a[0] == 0, "");305 static_assert(u5.a[4] == 0, "");306 static_assert(u5.b == 0, ""); // both-error {{not an integral constant expression}} \307 // both-note {{read of member 'b' of union with active member 'a'}}308 309 union U6 { int a[5]; int b; } constexpr u6 = U6();310 static_assert(u6.a[0] == 0, "");311 static_assert(u6.a[4] == 0, "");312 static_assert(u6.b == 0, ""); // both-error {{not an integral constant expression}} \313 // both-note {{read of member 'b' of union with active member 'a'}}314 315 union UnionWithUnnamedBitfield {316 int : 3;317 int n;318 };319 static_assert(UnionWithUnnamedBitfield().n == 0, "");320 static_assert(UnionWithUnnamedBitfield{}.n == 0, "");321 static_assert(UnionWithUnnamedBitfield{1}.n == 1, "");322}323 324namespace IndirectField {325 struct S {326 struct {327 union {328 struct {329 int a;330 int b;331 };332 int c;333 };334 int d;335 };336 union {337 int e;338 int f;339 };340 constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {}341 constexpr S(int c, int d, int f) : c(c), d(d), f(f) {}342 };343 344 constexpr S s1(1,2,3,4);345 constexpr S s2(5, 6, 7);346 347 static_assert(s1.a == 1, "");348 static_assert(s1.b == 2, "");349 350 static_assert(s1.c == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}351 static_assert(s1.d == 3, "");352 static_assert(s1.e == 4, "");353 static_assert(s1.f == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}354 355 static_assert(s2.a == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}356 static_assert(s2.b == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}357 static_assert(s2.c == 5, "");358 static_assert(s2.d == 6, "");359 static_assert(s2.e == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}360 static_assert(s2.f == 7, "");361}362 363namespace CtorActivatesFields {364 struct TailClobberer {365 constexpr TailClobberer() { b = false; }366 bool b;367 };368 369 class expected {370 union __union_t {371 constexpr __union_t() : __unex_() {}372 TailClobberer __unex_;373 } __union_;374 };375 constexpr expected y;376}377 378namespace CopyCtor {379 union U {380 int a;381 int b;382 };383 384 constexpr U x = {42};385 constexpr U y = x;386 static_assert(y.a == 42, "");387 static_assert(y.b == 42, ""); // both-error {{constant expression}} \388 // both-note {{'b' of union with active member 'a'}}389}390 391namespace UnionInBase {392 struct Base {393 int y; // both-note {{subobject declared here}}394 };395 struct A : Base {396 int x;397 int arr[3];398 union { int p, q; };399 };400 union B {401 A a;402 int b;403 };404 constexpr int read_wrong_member_indirect() { // both-error {{never produces a constant}}405 B b = {.b = 1};406 int *p = &b.a.y;407 return *p; // both-note 2{{read of member 'a' of union with active member 'b'}}408 409 }410 static_assert(read_wrong_member_indirect() == 1); // both-error {{not an integral constant expression}} \411 // both-note {{in call to}}412 constexpr int read_uninitialized() {413 B b = {.b = 1};414 int *p = &b.a.y;415 b.a.x = 1;416 return *p; // both-note {{read of uninitialized object}}417 }418 static_assert(read_uninitialized() == 0); // both-error {{constant}} \419 // both-note {{in call}}420 constexpr int write_uninitialized() {421 B b = {.b = 1};422 int *p = &b.a.y;423 b.a.x = 1;424 *p = 1;425 return *p;426 }427 428 constexpr B return_uninit() {429 B b = {.b = 1};430 b.a.x = 2;431 return b;432 }433 constexpr B uninit = return_uninit(); // both-error {{constant expression}} \434 // both-note {{subobject 'y' is not initialized}}435 static_assert(return_uninit().a.x == 2);436}437 438namespace One {439 struct A { long x; };440 441 union U;442 constexpr A foo(U *up);443 union U {444 A a = foo(this); // both-note {{in call to 'foo(&u)'}}445 int y;446 };447 448 constexpr A foo(U *up) {449 return {up->y}; // both-note {{read of member 'y' of union}}450 }451 452 constinit U u = {}; // both-error {{constant init}} \453 // both-note {{constinit}}454}455 456namespace CopyAssign {457 union A {458 int a;459 int b;460 };461 462 constexpr int f() {463 A a{12};464 A b{13};465 466 b.b = 32;467 b = a ;468 return b.a;469 }470 static_assert(f()== 12);471 472 473 constexpr int f2() {474 A a{12};475 A b{13};476 477 b.b = 32;478 b = a ;479 return b.b; // both-note {{read of member 'b' of union with active member 'a'}}480 }481 static_assert(f2() == 12); // both-error {{not an integral constant expression}} \482 // both-note {{in call to}}483}484 485namespace MoveAssign {486 union A {487 int a;488 int b;489 };490 491 constexpr int f() {492 A b{13};493 494 b = A{12} ;495 return b.a;496 }497 static_assert(f()== 12);498}499 500namespace IFD {501 template <class T>502 struct Optional {503 struct {504 union {505 char null_state;506 T val;507 };508 };509 constexpr Optional() : null_state(){}510 };511 512 constexpr bool test()513 {514 Optional<int> opt{};515 Optional<int> opt2{};516 opt = opt2;517 return true;518 }519 static_assert(test());520}521 522namespace AnonymousUnion {523 struct A {524 int x;525 union { int p, q; };526 };527 union B {528 A a;529 int bb;530 };531 532 constexpr B return_init_all() {533 B b = {.bb = 1};534 b.a.x = 2;535 return b;536 }537 static_assert(return_init_all().a.p == 7); // both-error {{}} \538 // both-note {{read of member 'p' of union with no active member}}539}540 541namespace MemberCalls {542 struct S {543 constexpr bool foo() const { return true; }544 };545 546 constexpr bool foo() { // both-error {{never produces a constant expression}}547 union {548 int a;549 S s;550 } u;551 552 u.a = 10;553 return u.s.foo(); // both-note 2{{member call on member 's' of union with active member 'a'}}554 }555 static_assert(foo()); // both-error {{not an integral constant expression}} \556 // both-note {{in call to}}557}558 559namespace InactiveDestroy {560 struct A {561 constexpr ~A() {}562 };563 union U {564 A a;565 constexpr ~U() {566 }567 };568 569 constexpr bool foo() { // both-error {{never produces a constant expression}}570 U u;571 u.a.~A(); // both-note 2{{destruction of member 'a' of union with no active member}}572 return true;573 }574 static_assert(foo()); // both-error {{not an integral constant expression}} \575 // both-note {{in call to}}576}577 578namespace InactiveTrivialDestroy {579 struct A {};580 union U {581 A a;582 };583 584 constexpr bool foo() { // both-error {{never produces a constant expression}}585 U u;586 u.a.~A(); // both-note 2{{destruction of member 'a' of union with no active member}}587 return true;588 }589 static_assert(foo()); // both-error {{not an integral constant expression}} \590 // both-note {{in call to}}591}592 593namespace ActiveDestroy {594 struct A {};595 union U {596 A a;597 };598 constexpr bool foo2() {599 U u{};600 u.a.~A();601 return true;602 }603 static_assert(foo2());604}605 606namespace MoveOrAssignOp {607 struct min_pointer {608 int *ptr_;609 constexpr min_pointer(int *p) : ptr_(p) {}610 min_pointer() = default;611 };612 613 class F {614 public:615 struct __long {616 min_pointer __data_;617 };618 union __rep {619 int __s;620 __long __l;621 } __rep_;622 623 public:624 constexpr F() {625 __rep_ = __rep();626 __rep_.__l.__data_ = nullptr;627 }628 };629 630 constexpr bool foo() {631 F f{};632 return true;633 }634 static_assert(foo());635 636 constexpr F f2{};637 static_assert(__builtin_is_within_lifetime(&f2.__rep_));638 static_assert(__builtin_is_within_lifetime(&f2.__rep_.__l));639 static_assert(__builtin_is_within_lifetime(&f2.__rep_.__l.__data_));640}641 642namespace CopyEmptyUnion {643 struct A {644 union {}; // both-warning {{declaration does not declare anything}}645 };646 constexpr int foo() {647 A a;648 A a2 = a;649 return 1;650 }651 static_assert(foo() == 1);652}653 654namespace BitFields {655 constexpr bool simple() {656 union U {657 unsigned a : 1;658 unsigned b : 1;659 };660 661 U u{1};662 u.b = 1;663 return u.b;664 }665 static_assert(simple());666}667 668namespace deactivateRecurses {669 670 constexpr int foo() {671 struct A {672 struct {673 int a;674 };675 int b;676 };677 struct B {678 struct {679 int a;680 int b;681 };682 };683 684 union U {685 A a;686 B b;687 } u;688 689 u.b.a = 10;690 ++u.b.a;691 692 u.a.a = 10;693 ++u.a.a;694 695 if (__builtin_constant_p(u.b.a))696 return 10;697 698 return 1;699 }700 static_assert(foo() == 1);701}702 703namespace AnonymousUnion {704 struct Long {705 struct {706 unsigned is_long;707 };708 unsigned Size;709 };710 711 struct Short {712 struct {713 unsigned is_long;714 unsigned Size;715 };716 char data;717 };718 719 union Rep {720 Short S;721 Long L;722 };723 724 consteval int test() {725 union UU {726 struct {727 Rep R;728 int a;729 };730 } U;731 732 U.R.S.Size = 10;733 assert_active(U);734 assert_active(U.R);735 assert_active(U.R.S);736 assert_active(U.R.S.Size);737 738 U.a = 10;739 assert_active(U.a);740 assert_active(U);741 742 assert_active(U);743 assert_active(U.R);744 assert_active(U.R.S);745 assert_active(U.R.S.Size);746 747 return 1;748 }749 static_assert(test() == 1);750}751 752namespace AccessViaPointer {753 struct A {754 int x;755 int y;756 int arr[3];757 union { int p, q; };758 };759 union B {760 A a;761 int b;762 };763 764 constexpr int write_wrong_member_indirect() { // both-error {{never produces a constant}}765 B b = {.b = 1};766 int *p = &b.a.y;767 768 *p = 12; // both-note 2{{assignment to member 'a' of union with active member 'b'}}769 770 return *p;771 }772 static_assert(write_wrong_member_indirect() == 1); // both-error {{not an integral constant expression}} \773 // both-note {{in call to}}774}775 776namespace Activation {777 union U {778 int a;779 int b;780 };781 782 struct S { int& b; };783 784 constexpr int foo() { // both-error {{never produces a constant expression}}785 U u;786 u.a = 10;787 S s{u.b};788 789 // LHS is a MemberExpr, but not of a union type. shouldn't activate u.b.790 s.b = 12; // both-note 2{{assignment to member 'b' of union with active member 'a'}}791 792 return u.b;793 794 }795 static_assert(foo() == 12); // both-error {{not an integral constant expression}} \796 // both-note {{in call to}}797 798 struct SS {799 int a;800 consteval SS() {801 a = 10;802 }803 };804 805 /// Activating the struct should also activate all the struct members.806 consteval int structInUnion() {807 union {808 SS s;809 int b;810 } u{};811 812 // assert_active(u.s);813 // assert_active(u.s.a);814 //assert_inactive(u.b);815 816 return u.s.a;817 }818 static_assert(structInUnion() == 10);819 820}821 822namespace Activation2 {823 struct Base {824 int y;825 };826 struct A : Base {827 int x;828 int arr[3];829 union { int p, q; };830 };831 union B {832 A a;833 int b;834 };835 836 constexpr int change_member_indirectly() {837 B b = {.b = 1};838 b.a.arr[1] = 1;839 int &r = b.a.y;840 r = 123;841 842 b.b = 2;843 b.a.y = 3;844 b.a.arr[2] = 4;845 return b.a.arr[2];846 }847 static_assert(change_member_indirectly() == 4);848}849 850namespace CopyCtorMutable {851 struct E {852 union {853 int a;854 mutable int b; // both-note {{here}}855 };856 };857 constexpr E e1 = {{1}};858 constexpr E e2 = e1; // both-error {{constant}} \859 // both-note {{read of mutable member 'b'}} \860 // both-note {{in call}}861}862 863 864namespace NonTrivialCtor {865 struct A { int x = 1; constexpr int f() { return 1; } };866 struct B : A { int y = 1; constexpr int g() { return 2; } };867 struct C {868 int x;869 constexpr virtual int f() = 0;870 };871 struct D : C {872 int y;873 constexpr virtual int f() override { return 3; }874 };875 876 union U {877 int n;878 B b;879 D d;880 };881 882 consteval int test(int which) {883 if (which == 0) {}884 885 U u{.n = 5};886 assert_active(u);887 assert_active(u.n);888 assert_inactive(u.b);889 890 switch (which) {891 case 0:892 u.b.x = 10; // both-note {{assignment to member 'b' of union with active member 'n'}}893 return u.b.f();894 case 1:895 u.b.y = 10; // both-note {{assignment to member 'b' of union with active member 'n'}}896 return u.b.g();897 case 2:898 u.d.x = 10; // both-note {{assignment to member 'd' of union with active member 'n'}}899 return u.d.f();900 case 3:901 u.d.y = 10; // both-note {{assignment to member 'd' of union with active member 'n'}}902 return u.d.f();903 }904 905 return 1;906 }907 static_assert(test(0)); // both-error {{not an integral constant expression}} \908 // both-note {{in call}}909 static_assert(test(1)); // both-error {{not an integral constant expression}} \910 // both-note {{in call}}911 static_assert(test(2)); // both-error {{not an integral constant expression}} \912 // both-note {{in call}}913 static_assert(test(3)); // both-error {{not an integral constant expression}} \914 // both-note {{in call}}915 916}917 918namespace PrimitiveFieldInitActivates {919 /// The initializer of a needs the field to be active _before_ it's visited.920 template<int> struct X {};921 union V {922 int a, b;923 constexpr V(X<0>) : a(a = 1) {} // ok924 constexpr V(X<2>) : a() { b = 1; } // ok925 };926 constinit V v0 = X<0>();927 constinit V v2 = X<2>();928}929 930#endif931 932namespace AddressComparison {933 union {934 int a;935 int c;936 } U;937 static_assert(__builtin_addressof(U.a) == (void*)__builtin_addressof(U.c));938 static_assert(&U.a == &U.c);939 940 941 struct {942 union {943 struct {944 int a;945 int b;946 } a;947 struct {948 int b;949 int a;950 }b;951 } u;952 int b;953 } S;954 955 static_assert(&S.u.a.a == &S.u.b.b);956 static_assert(&S.u.a.b != &S.u.b.b);957 static_assert(&S.u.a.b == &S.u.b.b); // both-error {{failed}}958 959 960 union {961 int a[2];962 int b[2];963 } U2;964 965 static_assert(&U2.a[0] == &U2.b[0]);966 static_assert(&U2.a[0] != &U2.b[1]);967 static_assert(&U2.a[0] == &U2.b[1]); // both-error {{failed}}968}969 970#if __cplusplus >= 202002L971namespace UnionMemberOnePastEnd {972 constexpr bool b() {973 union {974 int p;975 };976 return &p == (&p + 1);977 }978 static_assert(!b());979}980 981namespace ActicvateInvalidPtr {982 constexpr void bar() { // both-error {{never produces a constant expression}}983 union {984 int a[1];985 } foo;986 foo.a[1] = 0; // both-note {{assignment to dereferenced one-past-the-end pointer}}987 }988}989#endif990