brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.8 KiB · ea4843e Raw
1214 lines · cpp
1// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -verify=both,expected -fcxx-exceptions %s -DNEW_INTERP -fexperimental-new-constant-interpreter2// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -verify=both,ref      -fcxx-exceptions %s3 4void test_alignas_operand() {5  alignas(8) char dummy;6  static_assert(__alignof(dummy) == 8);7}8 9constexpr int getMinus5() {10  int a = 10;11  a = -5;12  int *p = &a;13  return *p;14}15static_assert(getMinus5() == -5, "");16 17constexpr int assign() {18  int m = 10;19  int k = 12;20 21  m = (k = 20);22 23  return m;24}25static_assert(assign() == 20, "");26 27 28constexpr int pointerAssign() {29  int m = 10;30  int *p = &m;31 32  *p = 12; // modifies m33 34  return m;35}36static_assert(pointerAssign() == 12, "");37 38constexpr int pointerDeref() {39  int m = 12;40  int *p = &m;41 42  return *p;43}44static_assert(pointerDeref() == 12, "");45 46constexpr int pointerAssign2() {47  int m = 10;48  int *p = &m;49  int **pp = &p;50 51  **pp = 12;52 53  int v = **pp;54 55  return v;56}57static_assert(pointerAssign2() == 12, "");58 59constexpr int unInitLocal() {60  int a;61  return a; // both-note {{read of uninitialized object}}62}63static_assert(unInitLocal() == 0, ""); // both-error {{not an integral constant expression}} \64                                       // both-note {{in call to 'unInitLocal()'}}65 66constexpr int initializedLocal() {67  int a;68  a = 20;69  return a;70}71static_assert(initializedLocal() == 20);72 73constexpr int initializedLocal2() {74  int a[2];75  return *a; // both-note {{read of uninitialized object is not allowed in a constant expression}}76}77static_assert(initializedLocal2() == 20); // both-error {{not an integral constant expression}} \78                                          // both-note {{in call to}}79 80 81struct Int { int a; };82constexpr int initializedLocal3() {83  Int i;84  return i.a; // both-note {{read of uninitialized object is not allowed in a constant expression}}85}86static_assert(initializedLocal3() == 20); // both-error {{not an integral constant expression}} \87                                          // both-note {{in call to}}88 89 90 91#if 092// FIXME: This code should be rejected because we pass an uninitialized value93//   as a function parameter.94constexpr int inc(int a) { return a + 1; }95constexpr int f() {96    int i;97    return inc(i);98}99static_assert(f());100#endif101 102/// Distinct literals have distinct addresses.103/// see https://github.com/llvm/llvm-project/issues/58754104constexpr auto foo(const char *p) { return p; }105constexpr auto p1 = "test1";106constexpr auto p2 = "test2";107 108constexpr bool b1 = foo(p1) == foo(p1);109static_assert(b1);110 111constexpr bool b2 = foo(p1) == foo(p2);112static_assert(!b2);113 114constexpr auto name1() { return "name1"; }115constexpr auto name2() { return "name2"; }116 117constexpr auto b3 = name1() == name1(); // ref-error {{must be initialized by a constant expression}} \118                                        // ref-note {{comparison of addresses of potentially overlapping literals}}119constexpr auto b4 = name1() == name2();120static_assert(!b4);121 122constexpr auto bar(const char *p) { return p + __builtin_strlen(p); }123constexpr auto b5 = bar(p1) == p1;124static_assert(!b5);125constexpr auto b6 = bar(p1) == ""; // both-error {{must be initialized by a constant expression}} \126                                   // both-note {{comparison of addresses of potentially overlapping literals}}127constexpr auto b7 = bar(p1) + 1 == ""; // both-error {{must be initialized by a constant expression}} \128                                       // both-note {{comparison against pointer '&"test1"[6]' that points past the end of a complete object has unspecified value}}129 130namespace UninitializedFields {131  class A {132  public:133    int a; // both-note 4{{subobject declared here}}134    constexpr A() {}135  };136  constexpr A a; // both-error {{must be initialized by a constant expression}} \137                 // both-note {{subobject 'a' is not initialized}}138  constexpr A aarr[2]; // both-error {{must be initialized by a constant expression}} \139                       // both-note {{subobject 'a' is not initialized}}140  class F {141    public:142      int f; // both-note 3{{subobject declared here}}143 144      constexpr F() {}145      constexpr F(bool b) {146        if (b)147          f = 42;148      }149  };150 151  constexpr F foo[2] = {true}; // both-error {{must be initialized by a constant expression}} \152                               // both-note {{subobject 'f' is not initialized}}153  constexpr F foo2[3] = {true, false, true}; // both-error {{must be initialized by a constant expression}} \154                                             // both-note {{subobject 'f' is not initialized}}155  constexpr F foo3[3] = {true, true, F()}; // both-error {{must be initialized by a constant expression}} \156                                           // both-note {{subobject 'f' is not initialized}}157 158 159 160  class Base {161  public:162    bool b;163    int a; // both-note {{subobject declared here}}164    constexpr Base() : b(true) {}165  };166 167  class Derived : public Base {168  public:169    constexpr Derived() : Base() {}   };170 171  constexpr Derived D; // both-error {{must be initialized by a constant expression}} \172                       // both-note {{subobject 'a' is not initialized}}173 174  class C2 {175  public:176    A a;177    constexpr C2() {}   };178  constexpr C2 c2; // both-error {{must be initialized by a constant expression}} \179                   // both-note {{subobject 'a' is not initialized}}180 181  class C3 {182  public:183    A a[2];184    constexpr C3() {}185  };186  constexpr C3 c3; // both-error {{must be initialized by a constant expression}} \187                   // both-note {{subobject 'a' is not initialized}}188 189  class C4 {190  public:191    bool B[2][3]; // both-note {{subobject declared here}}192    constexpr C4(){}193  };194  constexpr C4 c4; // both-error {{must be initialized by a constant expression}} \195                   // both-note {{subobject 'B' is not initialized}}196};197 198namespace ConstThis {199  class Foo {200    const int T = 12; // both-note {{declared const here}}201    int a;202  public:203    constexpr Foo() {204      this->a = 10;205      T = 13; // both-error {{cannot assign to non-static data member 'T' with const-qualified type}}206    }207  };208  constexpr Foo F; // both-error {{must be initialized by a constant expression}}209 210 211  class FooDtor {212    int a;213  public:214    constexpr FooDtor() {215      this->a = 10;216    }217    constexpr ~FooDtor() {218      this->a = 12;219    }220  };221 222  constexpr int foo() {223    const FooDtor f;224    return 0;225  }226  static_assert(foo() == 0);227 228  template <bool Good>229  struct ctor_test {230    int a = 0;231 232    constexpr ctor_test() {233      if (Good)234        a = 10;235      int local = 100 / a; // both-note {{division by zero}}236    }237  };238 239  template <bool Good>240  struct dtor_test {241    int a = 0;242 243    constexpr dtor_test() = default;244    constexpr ~dtor_test() {245      if (Good)246        a = 10;247      int local = 100 / a; // both-note {{division by zero}}248    }249  };250 251  constexpr ctor_test<true> good_ctor;252  constexpr dtor_test<true> good_dtor;253 254  constexpr ctor_test<false> bad_ctor; // both-error {{must be initialized by a constant expression}} \255                                       // both-note {{in call to}}256  constexpr dtor_test<false> bad_dtor; // both-error {{must have constant destruction}} \257                                       // both-note {{in call to}}258};259 260namespace BaseInit {261  struct Base {262    int a;263  };264 265  struct Intermediate : Base {266    int b;267  };268 269  struct Final : Intermediate {270    int c;271 272    constexpr Final(int a, int b, int c) : c(c) {}273  };274 275  static_assert(Final{1, 2, 3}.c == 3, ""); // OK276  static_assert(Final{1, 2, 3}.a == 0, ""); // both-error {{not an integral constant expression}} \277                                            // both-note {{read of uninitialized object}}278 279 280  struct Mixin  {281    int b;282 283    constexpr Mixin() = default;284    constexpr Mixin(int b) : b(b) {}285  };286 287  struct Final2 : Base, Mixin {288    int c;289 290    constexpr Final2(int a, int b, int c) : Mixin(b), c(c) {}291    constexpr Final2(int a, int b, int c, bool) : c(c) {}292  };293 294  static_assert(Final2{1, 2, 3}.c == 3, ""); // OK295  static_assert(Final2{1, 2, 3}.b == 2, ""); // OK296  static_assert(Final2{1, 2, 3}.a == 0, ""); // both-error {{not an integral constant expression}} \297                                             // both-note {{read of uninitialized object}}298 299 300  struct Mixin3  {301    int b;302  };303 304  struct Final3 : Base, Mixin3 {305    int c;306 307    constexpr Final3(int a, int b, int c) : c(c) { this->b = b; }308    constexpr Final3(int a, int b, int c, bool) : c(c) {}309  };310 311  static_assert(Final3{1, 2, 3}.c == 3, ""); // OK312  static_assert(Final3{1, 2, 3}.b == 2, ""); // OK313  static_assert(Final3{1, 2, 3}.a == 0, ""); // both-error {{not an integral constant expression}} \314                                             // both-note {{read of uninitialized object}}315};316 317namespace Destructors {318 319  class Inc final {320  public:321    int &I;322    constexpr Inc(int &I) : I(I) {}323    constexpr ~Inc() {324      I++;325    }326  };327 328  class Dec final {329  public:330    int &I;331    constexpr Dec(int &I) : I(I) {}332    constexpr ~Dec() {333      I--;334    }335  };336 337 338 339  constexpr int m() {340    int i = 0;341    {342      Inc f1(i);343      Inc f2(i);344      Inc f3(i);345    }346    return i;347  }348  static_assert(m() == 3, "");349 350 351  constexpr int C() {352    int i = 0;353 354    while (i < 10) {355      Inc inc(i);356      continue;357      Dec dec(i);358    }359    return i;360  }361  static_assert(C() == 10, "");362 363 364  constexpr int D() {365    int i = 0;366 367    {368      Inc i1(i);369      {370        Inc i2(i);371        return i;372      }373    }374 375    return i;376  }377  static_assert(D() == 0, "");378 379  constexpr int E() {380    int i = 0;381 382    for(;;) {383      Inc i1(i);384      break;385    }386    return i;387  }388  static_assert(E() == 1, "");389 390 391  /// FIXME: This should be rejected, since we call the destructor392  ///   twice. However, GCC doesn't care either.393  constexpr int ManualDtor() {394    int i = 0;395    {396      Inc I(i); // ref-note {{destroying object 'I' whose lifetime has already ended}}397      I.~Inc();398    }399    return i;400  }401  static_assert(ManualDtor() == 1, ""); // expected-error {{static assertion failed}} \402                                        // expected-note {{evaluates to '2 == 1'}} \403                                        // ref-error {{not an integral constant expression}} \404                                        // ref-note {{in call to 'ManualDtor()'}}405 406  constexpr void doInc(int &i) {407    Inc I(i);408    return;409  }410  constexpr int testInc() {411    int i = 0;412    doInc(i);413    return i;414  }415  static_assert(testInc() == 1, "");416  constexpr void doInc2(int &i) {417    Inc I(i);418    // No return statement.419  }420   constexpr int testInc2() {421    int i = 0;422    doInc2(i);423    return i;424  }425  static_assert(testInc2() == 1, "");426 427 428  namespace DtorOrder {429    class A {430      public:431      int &I;432      constexpr A(int &I) : I(I) {}433      constexpr ~A() {434        I = 1337;435      }436    };437 438    class B : public A {439      public:440      constexpr B(int &I) : A(I) {}441      constexpr ~B() {442        I = 42;443      }444    };445 446    constexpr int foo() {447      int i = 0;448      {449        B b(i);450      }451      return i;452    }453 454    static_assert(foo() == 1337);455  }456 457  class FieldDtor1 {458  public:459    Inc I1;460    Inc I2;461    constexpr FieldDtor1(int &I) : I1(I), I2(I){}462  };463 464  constexpr int foo2() {465    int i = 0;466    {467      FieldDtor1 FD1(i);468    }469    return i;470  }471 472  static_assert(foo2() == 2);473 474  class FieldDtor2 {475  public:476    Inc Incs[3];477    constexpr FieldDtor2(int &I)  : Incs{Inc(I), Inc(I), Inc(I)} {}478  };479 480  constexpr int foo3() {481    int i = 0;482    {483      FieldDtor2 FD2(i);484    }485    return i;486  }487 488  static_assert(foo3() == 3);489 490  struct ArrD {491    int index;492    int *arr;493    int &p;494    constexpr ~ArrD() {495      arr[p] = index;496      ++p;497    }498  };499  constexpr bool ArrayOrder() {500    int order[3] = {0, 0, 0};501    int p = 0;502    {503      ArrD ds[3] = {504        {1, order, p},505        {2, order, p},506        {3, order, p},507      };508      // ds will be destroyed.509    }510    return order[0] == 3 && order[1] == 2 && order[2] == 1;511  }512  static_assert(ArrayOrder());513 514 515  // Static members aren't destroyed.516  class Dec2 {517  public:518    int A = 0;519    constexpr ~Dec2() {520      A++;521    }522  };523  class Foo {524  public:525    static constexpr Dec2 a;526    static Dec2 b;527  };528  static_assert(Foo::a.A == 0);529  constexpr bool f() {530    Foo f;531    return true;532  }533  static_assert(Foo::a.A == 0);534  static_assert(f());535  static_assert(Foo::a.A == 0);536 537 538  struct NotConstexpr {539    NotConstexpr() {}540    ~NotConstexpr() {}541  };542 543  struct Outer {544    constexpr Outer() = default;545    constexpr ~Outer();546 547    constexpr int foo() {548      return 12;549    }550 551    constexpr int bar()const  {552      return Outer{}.foo();553    }554 555    static NotConstexpr Val;556  };557 558  constexpr Outer::~Outer() {}559 560  constexpr Outer O;561  static_assert(O.bar() == 12);562}563 564namespace BaseAndFieldInit {565  struct A {566    int a;567  };568 569  struct B : A {570    int b;571  };572 573  struct C : B {574    int c;575  };576 577  constexpr C c = {1,2,3};578  static_assert(c.a == 1 && c.b == 2 && c.c == 3);579}580 581namespace ImplicitFunction {582  struct A {583    int a; // ref-note {{subobject declared here}}584  };585 586  constexpr int callMe() {587   A a;588   A b{12};589 590   /// The operator= call here will fail and the diagnostics should be fine.591   b = a; // ref-note {{subobject 'a' is not initialized}} \592          // expected-note {{read of uninitialized object}} \593          // both-note {{in call to}}594 595   return 1;596  }597  static_assert(callMe() == 1, ""); // both-error {{not an integral constant expression}} \598                                    // both-note {{in call to 'callMe()'}}599}600 601namespace std {602  class strong_ordering {603  public:604    int n;605    static const strong_ordering less, equal, greater;606    constexpr bool operator==(int n) const noexcept { return this->n == n;}607    constexpr bool operator!=(int n) const noexcept { return this->n != n;}608  };609  constexpr strong_ordering strong_ordering::less = {-1};610  constexpr strong_ordering strong_ordering::equal = {0};611  constexpr strong_ordering strong_ordering::greater = {1};612 613  class partial_ordering {614  public:615    long n;616    static const partial_ordering less, equal, greater, equivalent, unordered;617    constexpr bool operator==(long n) const noexcept { return this->n == n;}618    constexpr bool operator!=(long n) const noexcept { return this->n != n;}619  };620  constexpr partial_ordering partial_ordering::less = {-1};621  constexpr partial_ordering partial_ordering::equal = {0};622  constexpr partial_ordering partial_ordering::greater = {1};623  constexpr partial_ordering partial_ordering::equivalent = {0};624  constexpr partial_ordering partial_ordering::unordered = {-127};625} // namespace std626 627namespace ThreeWayCmp {628  static_assert(1 <=> 2 == -1, "");629  static_assert(1 <=> 1 == 0, "");630  static_assert(2 <=> 1 == 1, "");631  static_assert(1.0 <=> 2.f == -1, "");632  static_assert(1.0 <=> 1.0 == 0, "");633  static_assert(2.0 <=> 1.0 == 1, "");634  constexpr int k = (1 <=> 1, 0); // both-warning {{comparison result unused}}635  static_assert(k== 0, "");636 637  static_assert(__builtin_nanf("") <=> __builtin_nanf("") == -127, "");638 639  /// Pointers.640  constexpr int a[] = {1,2,3};641  constexpr int b[] = {1,2,3};642  constexpr const int *pa1 = &a[1];643  constexpr const int *pa2 = &a[2];644  constexpr const int *pb1 = &b[1];645  static_assert(pa1 <=> pb1 != 0, ""); // both-error {{not an integral constant expression}} \646                                       // both-note {{has unspecified value}}647  static_assert(pa1 <=> pa1 == 0, "");648  static_assert(pa1 <=> pa2 == -1, "");649  static_assert(pa2 <=> pa1 == 1, "");650}651 652namespace ConstexprArrayInitLoopExprDestructors653{654  struct Highlander {655      int *p = 0;656      constexpr Highlander() {}657      constexpr void set(int *p) { this->p = p; ++*p; if (*p != 1) throw "there can be only one"; }658      constexpr ~Highlander() { --*p; }659  };660 661  struct X {662      int *p;663      constexpr X(int *p) : p(p) {}664      constexpr X(const X &x, Highlander &&h = Highlander()) : p(x.p) {665          h.set(p);666      }667  };668 669  constexpr int f() {670      int n = 0;671      X x[3] = {&n, &n, &n};672      auto [a, b, c] = x;673      return n;674  }675 676  static_assert(f() == 0);677}678 679namespace NonPrimitiveOpaqueValue680{681  struct X {682    int x;683    constexpr operator bool() const { return x != 0; }684  };685 686  constexpr int ternary() { return X(0) ?: X(0); }687 688  static_assert(!ternary(), "");689}690 691namespace TryCatch {692  constexpr int foo() {693    int a = 10;694    try {695      ++a;696    } catch(int m) {697      --a;698    }699    return a;700  }701  static_assert(foo() == 11);702}703 704namespace IgnoredConstantExpr {705  consteval int immediate() { return 0;}706  struct ReferenceToNestedMembers {707    int m;708    int a = ((void)immediate(), m);709    int b = ((void)immediate(), this->m);710  };711  struct ReferenceToNestedMembersTest {712    void* m = nullptr;713    ReferenceToNestedMembers j{0};714  } test_reference_to_nested_members;715}716 717namespace RewrittenBinaryOperators {718  template <class T, T Val>719  struct Conv {720    constexpr operator T() const { return Val; }721    operator T() { return Val; }722  };723 724  struct X {725    constexpr const Conv<int, -1> operator<=>(X) { return {}; }726  };727  static_assert(X() < X(), "");728}729 730namespace GH61417 {731struct A {732  unsigned x : 1;733  unsigned   : 0;734  unsigned y : 1;735 736  constexpr A() : x(0), y(0) {}737  bool operator==(const A& rhs) const noexcept = default;738};739 740void f1() {741  constexpr A a, b;742  constexpr bool c = (a == b); // no diagnostic, we should not be comparing the743                               // unnamed bit-field which is indeterminate744}745 746void f2() {747    A a, b;748    bool c = (a == b); // no diagnostic nor crash during codegen attempting to749                       // access info for unnamed bit-field750}751}752 753namespace FailingDestructor {754  struct D {755    int n;756    bool can_destroy;757 758    constexpr ~D() {759      if (!can_destroy)760        throw "oh no";761    }762  };763  template<D d>764  void f() {} // both-note {{invalid explicitly-specified argument}}765 766  void g() {767    f<D{0, false}>(); // both-error {{no matching function}}768  }769}770 771 772void overflowInSwitchCase(int n) {773  switch (n) {774  case (int)(float)1e300: // both-error {{constant expression}} \775                          // both-note {{value +Inf is outside the range of representable values of type 'int'}}776    break;777  }778}779 780namespace APValues {781  int g;782  struct A { union { int n, m; }; int *p; int A::*q; char buffer[32]; };783  template<A a> constexpr const A &get = a;784  constexpr const A &v = get<A{}>;785  constexpr const A &w = get<A{1, &g, &A::n, "hello"}>;786}787 788namespace self_referencing {789  struct S {790    S* ptr = nullptr;791    constexpr S(int i) : ptr(this) {792      if (this == ptr && i)793        ptr = nullptr;794    }795    constexpr ~S() {}796  };797 798  void test() {799    S s(1);800  }801}802 803namespace GH64949 {804  struct f {805    int g; // both-note {{subobject declared here}}806    constexpr ~f() {}807  };808 809  class h {810  public:811    consteval h(char *) {}812    f i;813  };814 815  void test() { h{nullptr}; } // both-error {{call to consteval function 'GH64949::h::h' is not a constant expression}} \816                              // both-note {{subobject 'g' is not initialized}} \817                              // both-warning {{expression result unused}}818}819 820/// This used to cause an assertion failure inside EvaluationResult::checkFullyInitialized.821namespace CheckingNullPtrForInitialization {822  struct X {823    consteval operator const char *() const {824      return nullptr;825    }826  };827  const char *f() {828    constexpr X x;829    return x;830  }831}832 833namespace VariadicCallOperator {834  class F {835  public:836    constexpr void operator()(int a, int b, ...) {}837  };838  constexpr int foo() {839    F f;840 841    f(1,2, 3);842    return 1;843  }844  constexpr int A = foo();845}846 847namespace DefinitionLoc {848 849  struct NonConstexprCopy {850    constexpr NonConstexprCopy() = default;851    NonConstexprCopy(const NonConstexprCopy &);852    constexpr NonConstexprCopy(NonConstexprCopy &&) = default;853 854    int n = 42;855  };856 857  NonConstexprCopy::NonConstexprCopy(const NonConstexprCopy &) = default; // both-note {{here}}858 859  constexpr NonConstexprCopy ncc1 = NonConstexprCopy(NonConstexprCopy());860  constexpr NonConstexprCopy ncc2 = ncc1; // both-error {{constant expression}} \861                                          // both-note {{non-constexpr constructor}}862}863 864namespace VirtDtor {865  class B {866  public:867    constexpr B(char *p) : p(p) {}868    virtual constexpr ~B() {869      *p = 'B';870      ++p;871    }872 873    char *p;874  };875 876  class C : public B {877  public:878    constexpr C(char *p) : B(p) {}879    virtual constexpr ~C() override {880      *p = 'C';881      ++p;882    }883  };884 885  union U {886    constexpr U(char *p) : c(p) {}887    constexpr ~U() {}888 889    C c;890  };891 892  constexpr int test(char a, char b) {893    char buff[2] = {};894    U u(buff);895 896    /// U is a union, so it won't call the destructor of its fields.897    /// We do this manually here. Explicitly calling ~C() here should898    /// also call the destructor of the base classes however.899    u.c.~C();900 901    return buff[0] == a && buff[1] == b;902  }903 904  static_assert(test('C', 'B'));905}906 907namespace TemporaryInNTTP {908  template<auto n> struct B { /* ... */ };909  struct J1 {910    J1 *self=this;911  };912  /// FIXME: The bytecode interpreter emits a different diagnostic here.913  /// The current interpreter creates a fake MaterializeTemporaryExpr (see EvaluateAsConstantExpr)914  /// which is later used as the LValueBase of the created APValue.915  B<J1{}> j1;  // ref-error {{pointer to temporary object is not allowed in a template argument}} \916               // expected-error {{non-type template argument is not a constant expression}} \917               // expected-note {{pointer to temporary is not a constant expression}} \918               // expected-note {{created here}}919  B<2> j2; /// Ok.920}921 922namespace LocalDestroy {923  /// This is reduced from a libc++ test case.924  /// The local f.TI.copied points to the local variable Copied, and we used to925  /// destroy Copied before f, causing problems later on when a DeadBlock had a926  /// pointer pointing to it that was already destroyed.927  struct TrackInitialization {928    bool *copied_;929  };930  struct TrackingPred : TrackInitialization {931    constexpr TrackingPred(bool *copied) : TrackInitialization(copied) {}932  };933  struct F {934    const TrackingPred &TI;935  };936  constexpr int f() {937    bool Copied = false;938    TrackingPred TI(&Copied);939    F f{TI};940    return 1;941  }942  static_assert(f() == 1);943}944 945namespace PseudoDtor {946  constexpr int f1() {947   using T = int;948   int a = 0;949   a.~T();950   return a; // both-note {{read of object outside its lifetime}}951  }952  static_assert(f1() == 0); // both-error {{not an integral constant expression}} \953                            // both-note {{in call to}}954 955  constexpr int f2() {956   using T = int;957   int a = 0;958   a.~T();959   a = 0; // both-note {{assignment to object outside its lifetime}}960   return a;961  }962  static_assert(f2() == 0); // both-error {{not an integral constant expression}} \963                            // both-note {{in call to}}964 965#ifdef NEW_INTERP966  /// FIXME: Currently crashes with the current interpreter, see https://github.com/llvm/llvm-project/issues/53741967  constexpr int f3() {968   using T = int;969   0 .~T();970   return 0;971  }972  static_assert(f3() == 0);973#endif974}975 976namespace NastyChar {977  struct nasty_char {978    template <typename T> friend auto operator<=>(T, T) = delete;979    template <typename T> friend void operator+(T &&) = delete;980    template <typename T> friend void operator-(T &&) = delete;981    template <typename T> friend void operator&(T &&) = delete;982 983    char c;984  };985 986 987  template <unsigned N> struct ToNastyChar {988    constexpr ToNastyChar(const char (&r)[N]) {989      for (unsigned I = 0; I != N; ++I)990        text[I] = nasty_char{r[I]};991    }992    nasty_char text[N];993  };994 995  template <unsigned N> ToNastyChar(const char (&)[N]) -> ToNastyChar<N>;996 997  template <ToNastyChar t> constexpr auto to_nasty_char() { return t; }998  constexpr auto result = to_nasty_char<"12345">();999}1000 1001namespace TempDtor {1002  struct A {1003    int n;1004  };1005  constexpr A &&a_ref = A(); // both-note {{temporary created here}}1006  constexpr void destroy_extern_2() { // both-error {{never produces a constant expression}}1007    a_ref.~A(); // both-note {{destruction of temporary is not allowed in a constant expression outside the expression that created the temporary}}1008  }1009}1010 1011namespace OnePastEndDtor {1012  struct A {int n; };1013  constexpr void destroy_past_end() { // both-error {{never produces a constant expression}}1014    A a;1015    (&a+1)->~A(); // both-note {{destruction of dereferenced one-past-the-end pointer}}1016  }1017}1018 1019namespace Virtual {1020  struct NonZeroOffset { int padding = 123; };1021 1022  constexpr void assert(bool b) { if (!b) throw 0; }1023 1024  // Ensure that we pick the right final overrider during construction.1025  struct A {1026    virtual constexpr char f() const { return 'A'; }1027    char a = f();1028    constexpr ~A() { assert(f() == 'A'); }1029  };1030  struct NoOverrideA : A {};1031  struct B : NonZeroOffset, NoOverrideA {1032    virtual constexpr char f() const { return 'B'; }1033    char b = f();1034    constexpr ~B() { assert(f() == 'B'); }1035  };1036  struct NoOverrideB : B {};1037  struct C : NonZeroOffset, A {1038    virtual constexpr char f() const { return 'C'; }1039    A *pba;1040    char c = ((A*)this)->f();1041    char ba = pba->f();1042    constexpr C(A *pba) : pba(pba) {}1043    constexpr ~C() { assert(f() == 'C'); }1044  };1045  struct D : NonZeroOffset, NoOverrideB, C { // both-warning {{inaccessible}}1046    virtual constexpr char f() const { return 'D'; }1047    char d = f();1048    constexpr D() : C((B*)this) {}1049    constexpr ~D() { assert(f() == 'D'); }1050  };1051  constexpr int n = (D(), 0);1052 1053  constexpr D d;1054  static_assert(((B&)d).a == 'A');1055  static_assert(((C&)d).a == 'A');1056  static_assert(d.b == 'B');1057  static_assert(d.c == 'C');1058  // During the construction of C, the dynamic type of B's A is B.1059  static_assert(d.ba == 'B'); // expected-error {{failed}} \1060                              // expected-note {{expression evaluates to}}1061  static_assert(d.d == 'D');1062  static_assert(d.f() == 'D');1063  constexpr const A &a = (B&)d;1064  constexpr const B &b = d;1065  static_assert(a.f() == 'D');1066  static_assert(b.f() == 'D');1067 1068 1069  class K {1070  public:1071    int a = f();1072 1073    virtual constexpr int f() const { return 10; }1074  };1075 1076  K k;1077  static_assert(k.f() == 10); // both-error {{not an integral constant expression}} \1078                              // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}1079 1080  void f() {1081    constexpr K k;1082    static_assert(k.f() == 10);1083  }1084 1085  void f2() {1086    K k;1087    static_assert(k.f() == 10); // both-error {{not an integral constant expression}} \1088                                // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}1089  }1090  1091  static_assert(K().f() == 10);1092 1093  void f3() {1094    static_assert(K().f() == 10);1095  }1096 1097  class L : public K {1098  public:1099    int b = f();1100    int c =((L*)this)->f();1101  };1102 1103  constexpr L l;1104  static_assert(l.a == 10);1105  static_assert(l.b == 10);1106  static_assert(l.c == 10);1107  static_assert(l.f() == 10);1108 1109  struct M {1110    K& mk = k;1111  };1112  static_assert(M{}.mk.f() == 10); // both-error {{not an integral constant expression}} \1113                                   // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}1114 1115  struct N {1116    K* mk = &k;1117  };1118  static_assert(N{}.mk->f() == 10); // both-error {{not an integral constant expression}} \1119                                    // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}1120 1121  extern K o;1122  static_assert(o.f() == 10); // both-error {{not an integral constant expression}} \1123                              // both-note {{virtual function called on object 'o' whose dynamic type is not constant}}1124  static K p;1125  static_assert(p.f() == 10); // both-error {{not an integral constant expression}} \1126                              // both-note {{virtual function called on object 'p' whose dynamic type is not constant}}1127  1128  void f4() {1129    static K p;1130    static_assert(p.f() == 10); // both-error {{not an integral constant expression}} \1131                                // both-note {{virtual function called on object 'p' whose dynamic type is not constant}}1132  }1133  1134  const K q;1135  static_assert(q.f() == 10); // both-error {{not an integral constant expression}} \1136                              // both-note {{virtual function called on object 'q' whose dynamic type is not constant}}1137 1138  void f5() {1139    const K q;1140    static_assert(q.f() == 10); // both-error {{not an integral constant expression}} \1141                                // both-note {{virtual function called on object 'q' whose dynamic type is not constant}}1142  }1143}1144 1145namespace DiscardedTrivialCXXConstructExpr {1146  struct S {1147    constexpr S(int a) : x(a) {}1148    int x;1149  };1150 1151  constexpr int foo(int x) { // ref-error {{never produces a constant expression}}1152    throw S(3); // both-note {{not valid in a constant expression}} \1153                // ref-note {{not valid in a constant expression}}1154    return 1;1155  }1156 1157  constexpr int y = foo(12); // both-error {{must be initialized by a constant expression}} \1158                             // both-note {{in call to}}1159}1160 1161namespace VirtualFunctionCallThroughArrayElem {1162  struct X {1163    constexpr virtual int foo() const {1164      return 3;1165    }1166  };1167  constexpr X xs[5];1168  static_assert(xs[3].foo() == 3);1169 1170  constexpr X xs2[1][2];1171  static_assert(xs2[0].foo() == 3); // both-error {{is not a structure or union}}1172  static_assert(xs2[0][0].foo() == 3);1173 1174  struct Y: public X {1175    constexpr int foo() const override {1176      return 1;1177    }1178  };1179  constexpr Y ys[20];1180  static_assert(ys[12].foo() == static_cast<const X&>(ys[12]).foo());1181 1182  X a[3][4];1183  static_assert(a[2][3].foo()); // both-error {{not an integral constant expression}} \1184                                // both-note {{virtual function called on object 'a[2][3]' whose dynamic type is not constant}}1185}1186 1187namespace NonPureVirtualCall {1188  struct A {1189    constexpr virtual void call(int) = 0;1190    constexpr void call2() { call(0); }1191  };1192 1193  struct B : A {1194    constexpr void call(int) override {}1195  };1196 1197  consteval void check() {1198    B b;1199    b.call2();1200  }1201 1202  int main() { check(); }1203}1204 1205namespace DyamicCast {1206  struct X {1207    virtual constexpr ~X() {}1208  };1209  struct Y : X {};1210  constexpr Y y;1211  constexpr const X *p = &y;1212  constexpr const Y *q = dynamic_cast<const Y*>(p);1213}1214