brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.2 KiB · 4140704 Raw
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