brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.3 KiB · 21283c0 Raw
434 lines · cpp
1// RUN: %clang_cc1 -std=c++23 -verify=expected,nointerpreter -Winvalid-constexpr %s2// RUN: %clang_cc1 -std=c++23 -verify=expected,interpreter %s -fexperimental-new-constant-interpreter -Winvalid-constexpr3 4using size_t = decltype(sizeof(0));5 6namespace std {7struct type_info {8  const char* name() const noexcept(true);9};10}11 12template <typename T, size_t N>13constexpr size_t array_size(T (&)[N]) {14  return N;15}16 17void use_array(int const (&gold_medal_mel)[2]) {18  constexpr auto gold = array_size(gold_medal_mel); // ok19}20 21constexpr auto olympic_mile() {22  const int ledecky = 1500;23  return []{ return ledecky; };24}25static_assert(olympic_mile()() == 1500); // ok26 27struct Swim {28  constexpr int phelps() { return 28; }29  virtual constexpr int lochte() { return 12; }30  int coughlin = 12;31};32 33constexpr int how_many(Swim& swam) {34  Swim* p = &swam;35  return (p + 1 - 1)->phelps();36}37 38void splash(Swim& swam) {                 // nointerpreter-note {{declared here}}39  static_assert(swam.phelps() == 28);     // ok40  static_assert((&swam)->phelps() == 28); // ok41  Swim* pswam = &swam;                    // expected-note {{declared here}}42  static_assert(pswam->phelps() == 28);   // expected-error {{static assertion expression is not an integral constant expression}} \43                                          // expected-note {{read of non-constexpr variable 'pswam' is not allowed in a constant expression}}44  static_assert(how_many(swam) == 28);    // ok45  static_assert(Swim().lochte() == 12);   // ok46  static_assert(swam.lochte() == 12);     // expected-error {{static assertion expression is not an integral constant expression}} \47                                          // expected-note {{virtual function called on object 'swam' whose dynamic type is not constant}}48  static_assert(swam.coughlin == 12);     // expected-error {{static assertion expression is not an integral constant expression}} \49                                          // nointerpreter-note {{read of variable 'swam' whose value is not known}}50}51 52extern Swim dc;53extern Swim& trident; // interpreter-note {{declared here}}54 55constexpr auto& sandeno   = typeid(dc);         // ok: can only be typeid(Swim)56constexpr auto& gallagher = typeid(trident);    // expected-error {{constexpr variable 'gallagher' must be initialized by a constant expression}} \57                                                // nointerpreter-note {{typeid applied to object 'trident' whose dynamic type is not constant}} \58                                                // interpreter-note {{initializer of 'trident' is unknown}}59 60namespace explicitThis {61struct C {62  constexpr int b()  { return 0; };63 64  constexpr int f(this C &c) {65    return c.b();     // ok66  }67 68   constexpr int g() {69    return f();       // ok70  }71};72 73void g() {74  C c;75  constexpr int x = c.f();76  constexpr int y = c.g();77}78}79 80namespace GH64376 {81template<int V>82struct Test {83    static constexpr int value = V;84};85 86int main() {87    Test<124> test;88    auto& test2 = test;89 90    if constexpr(test2.value > 3) {91       return 1;92    }93 94    return 0;95}96}97 98namespace GH30060 {99template<int V>100struct A {101  static constexpr int value = V;102};103 104template<class T>105static void test1(T &f) {106    A<f.value> bar;107}108 109void g() {110    A<42> f;111 112    test1(f);113}114}115 116namespace GH26067 {117struct A {118    constexpr operator int() const { return 42; }119};120 121template <int>122void f() {}123 124void test(const A& value) {125    f<value>();126}127 128int main() {129    A a{};130    test(a);131}132}133 134namespace GH34365 {135void g() {136  auto f = []() { return 42; };137  constexpr int x = f();138  [](auto f) { constexpr int x = f(); }(f);139  [](auto &f) { constexpr int x = f(); }(f);140  (void)[&]() { constexpr int x = f(); };141}142}143 144namespace GH118063 {145template <unsigned int N>146struct array {147    constexpr auto size() const -> unsigned int {148        return N;149    }150};151 152constexpr auto f(array<5> const& arr) {153    return array<arr.size()>{}.size();154}155 156int g() {157    array<5> arr {};158    static_assert(f(arr) == 5);159}160}161 162namespace GH128409 {163  int &ff();164  int &x = ff(); // expected-note {{declared here}}165  constinit int &z = x; // expected-error {{variable does not have a constant initializer}} \166                        // expected-note {{required by 'constinit' specifier here}} \167                        // expected-note {{initializer of 'x' is not a constant expression}}168}169 170namespace GH129845 {171  int &ff();172  int &x = ff(); // expected-note {{declared here}}173  struct A { int& x; };174  constexpr A g = {x}; // expected-error {{constexpr variable 'g' must be initialized by a constant expression}} \175                       // expected-note {{initializer of 'x' is not a constant expression}}176  const A* gg = &g;177}178 179namespace extern_reference_used_as_unknown {180  extern int &x;181  int y;182  constinit int& g = (x,y); // expected-warning {{left operand of comma operator has no effect}}183}184 185namespace GH139452 {186struct Dummy {187  explicit operator bool() const noexcept { return true; }188};189 190struct Base { int error; };191struct Derived : virtual Base { };192 193template <class R>194constexpr R get_value() {195    const auto& derived_val = Derived{};196    if (derived_val.error != 0)197        /* nothing */;198    return R{};199}200 201int f() {202    return !get_value<Dummy>(); // contextually convert the function call result to bool203}204}205 206namespace uninit_reference_used {207  int y;208  constexpr int &r = r; // expected-error {{must be initialized by a constant expression}} \209  // expected-note {{initializer of 'r' is not a constant expression}} \210  // expected-note {{declared here}}211  constexpr int &rr = (rr, y);212  constexpr int &g() {213    int &x = x; // expected-warning {{reference 'x' is not yet bound to a value when used within its own initialization}} \214    // nointerpreter-note {{use of reference outside its lifetime is not allowed in a constant expression}} \215    // interpreter-note {{read of uninitialized object is not allowed in a constant expression}}216    return x;217  }218  constexpr int &gg = g(); // expected-error {{must be initialized by a constant expression}} \219  // expected-note {{in call to 'g()'}}220  constexpr int g2() {221    int &x = x; // expected-warning {{reference 'x' is not yet bound to a value when used within its own initialization}} \222    // nointerpreter-note {{use of reference outside its lifetime is not allowed in a constant expression}} \223    // interpreter-note {{read of uninitialized object is not allowed in a constant expression}}224    return x;225  }226  constexpr int gg2 = g2(); // expected-error {{must be initialized by a constant expression}} \227  // expected-note {{in call to 'g2()'}}228  constexpr int &g3() {229    int &x = (x,y); // expected-warning{{left operand of comma operator has no effect}} \230    // expected-warning {{reference 'x' is not yet bound to a value when used within its own initialization}} \231    // nointerpreter-note {{use of reference outside its lifetime is not allowed in a constant expression}}232    return x;233  }234  constexpr int &gg3 = g3(); // nointerpreter-error {{must be initialized by a constant expression}} \235  // nointerpreter-note {{in call to 'g3()'}}236  typedef decltype(sizeof(1)) uintptr_t;237  constexpr uintptr_t g4() {238    uintptr_t * &x = x; // expected-warning {{reference 'x' is not yet bound to a value when used within its own initialization}} \239    // nointerpreter-note {{use of reference outside its lifetime is not allowed in a constant expression}} \240    // interpreter-note {{read of uninitialized object is not allowed in a constant expression}}241    *(uintptr_t*)x = 10;242    return 3;243  }244  constexpr uintptr_t gg4 = g4(); // expected-error {{must be initialized by a constant expression}} \245  // expected-note {{in call to 'g4()'}}246  constexpr int g5() {247    int &x = x; // expected-warning {{reference 'x' is not yet bound to a value when used within its own initialization}} \248    // nointerpreter-note {{use of reference outside its lifetime is not allowed in a constant expression}} \249    // interpreter-note {{read of uninitialized object is not allowed in a constant expression}}250    return 3;251  }252  constexpr uintptr_t gg5 = g5(); // expected-error {{must be initialized by a constant expression}} \253  // expected-note {{in call to 'g5()'}}254 255}256 257namespace param_reference {258  constexpr int arbitrary = -12345;259  constexpr void f(const int &x = arbitrary) { // nointerpreter-note 3 {{declared here}} interpreter-note {{declared here}}260    constexpr const int &v1 = x; // expected-error {{must be initialized by a constant expression}} \261    // expected-note {{reference to 'x' is not a constant expression}}262    constexpr const int &v2 = (x, arbitrary); // expected-warning {{left operand of comma operator has no effect}}263    constexpr int v3 = x; // expected-error {{must be initialized by a constant expression}} \264                          // nointerpreter-note {{read of variable 'x' whose value is not known}}265    static_assert(x==arbitrary); // expected-error {{static assertion expression is not an integral constant expression}} \266                                 // nointerpreter-note {{read of variable 'x' whose value is not known}}267    static_assert(&x - &x == 0);268  }269}270 271namespace dropped_note {272  extern int &x; // expected-note {{declared here}}273  constexpr int f() { return x; } // nointerpreter-note {{read of non-constexpr variable 'x'}} \274                                  // interpreter-note {{initializer of 'x' is unknown}}275  constexpr int y = f(); // expected-error {{constexpr variable 'y' must be initialized by a constant expression}} expected-note {{in call to 'f()'}}276}277 278namespace dynamic {279  struct A {virtual ~A();};280  struct B : A {};281  void f(A& a) { // interpreter-note 2{{declared here}}282    constexpr B* b = dynamic_cast<B*>(&a); // expected-error {{must be initialized by a constant expression}} \283                                           // nointerpreter-note {{dynamic_cast applied to object 'a' whose dynamic type is not constant}} \284                                           // interpreter-note {{pointer to 'a' is not a constant expression}}285    constexpr void* b2 = dynamic_cast<void*>(&a); // expected-error {{must be initialized by a constant expression}} \286                                                  // nointerpreter-note {{dynamic_cast applied to object 'a' whose dynamic type is not constant}} \287                                                  // interpreter-note {{pointer to 'a' is not a constant expression}}288  }289}290 291namespace unsized_array {292  void f(int (&a)[], int (&b)[], int (&c)[4]) {293    constexpr int t1 = a - a;294    constexpr int t2 = a - b; // expected-error {{constexpr variable 't2' must be initialized by a constant expression}} \295                              // nointerpreter-note {{arithmetic involving unrelated objects '&a[0]' and '&b[0]' has unspecified value}} \296                              // interpreter-note {{arithmetic involving unrelated objects 'a' and 'b' has unspecified value}}297    constexpr int t3 = a - &c[2];  // expected-error {{constexpr variable 't3' must be initialized by a constant expression}} \298                              // nointerpreter-note {{arithmetic involving unrelated objects '&a[0]' and '&c[2]' has unspecified value}} \299                              // interpreter-note {{arithmetic involving unrelated objects 'a' and '*((char*)&c + 8)' has unspecified value}}300  }301}302 303namespace casting {304  struct A {};305  struct B : A {};306  struct C : A {};307  extern A &a; // interpreter-note {{declared here}}308  extern B &b; // expected-note {{declared here}} interpreter-note 2 {{declared here}}309  constexpr B &t1 = (B&)a; // expected-error {{must be initialized by a constant expression}} \310                           // nointerpreter-note {{cannot cast object of dynamic type 'A' to type 'B'}} \311                           // interpreter-note {{initializer of 'a' is unknown}}312  constexpr B &t2 = (B&)(A&)b; // expected-error {{must be initialized by a constant expression}} \313                               // nointerpreter-note {{initializer of 'b' is not a constant expression}} \314                               // interpreter-note {{initializer of 'b' is unknown}}315  // FIXME: interpreter incorrectly rejects.316  constexpr bool t3 = &b + 1 == &(B&)(A&)b; // interpreter-error {{must be initialized by a constant expression}} \317                                            // interpreter-note {{initializer of 'b' is unknown}}318  constexpr C &t4 = (C&)(A&)b; // expected-error {{must be initialized by a constant expression}} \319                               // nointerpreter-note {{cannot cast object of dynamic type 'B' to type 'C'}} \320                               // interpreter-note {{initializer of 'b' is unknown}}321}322 323namespace pointer_comparisons {324  extern int &extern_n; // interpreter-note 4 {{declared here}}325  extern int &extern_n2;326  constexpr int f1(bool b, int& n) {327    if (b) {328      return &extern_n == &n;329    }330    return f1(true, n);331  }332  // FIXME: interpreter incorrectly rejects; both sides are the same constexpr-unknown value.333  static_assert(f1(false, extern_n)); // interpreter-error {{static assertion expression is not an integral constant expression}} \334                                      // interpreter-note {{initializer of 'extern_n' is unknown}}335  static_assert(&extern_n != &extern_n2); // expected-error {{static assertion expression is not an integral constant expression}} \336                                          // nointerpreter-note {{comparison between pointers to unrelated objects '&extern_n' and '&extern_n2' has unspecified value}} \337                                          // interpreter-note {{initializer of 'extern_n' is unknown}}338  void f2(const int &n) {339    constexpr int x = &x == &n; // nointerpreter-error {{must be initialized by a constant expression}} \340                                // nointerpreter-note {{comparison between pointers to unrelated objects '&x' and '&n' has unspecified value}}341    // Distinct variables are not equal, even if they're local variables.342    constexpr int y = &x == &y;343    static_assert(!y);344  }345  constexpr int f3() {346    int x;347    return &x == &extern_n; // nointerpreter-note {{comparison between pointers to unrelated objects '&x' and '&extern_n' has unspecified value}} \348                            // interpreter-note {{initializer of 'extern_n' is unknown}}349  }350  static_assert(!f3()); // expected-error {{static assertion expression is not an integral constant expression}} \351                        // expected-note {{in call to 'f3()'}}352  constexpr int f4() {353    int *p = new int;354    bool b = p == &extern_n; // nointerpreter-note {{comparison between pointers to unrelated objects '&{*new int#0}' and '&extern_n' has unspecified value}} \355                             // interpreter-note {{initializer of 'extern_n' is unknown}}356    delete p;357    return b;358  }359  static_assert(!f4()); // expected-error {{static assertion expression is not an integral constant expression}} \360                        // expected-note {{in call to 'f4()'}}361}362 363namespace GH149188 {364namespace enable_if_1 {365  template <__SIZE_TYPE__ N>366  constexpr void foo(const char (&Str)[N])367  __attribute((enable_if(__builtin_strlen(Str), ""))) {}368 369  void x() {370      foo("1234");371  }372}373 374namespace enable_if_2 {375  constexpr const char (&f())[];376  extern const char (&Str)[];377  constexpr int foo()378  __attribute((enable_if(__builtin_strlen(Str), "")))379  {return __builtin_strlen(Str);}380 381  constexpr const char (&f())[] {return "a";}382  constexpr const char (&Str)[] = f();383  void x() {384      constexpr int x = foo();385  }386}387}388 389namespace GH150015 {390  extern int (& c)[8]; // interpreter-note {{declared here}}391  constexpr int x = c <= c+8; // interpreter-error {{constexpr variable 'x' must be initialized by a constant expression}} \392                              // interpreter-note {{initializer of 'c' is unknown}}393 394  struct X {};395  struct Y {};396  struct Z : X, Y {};397  extern Z &z; // interpreter-note{{declared here}}398  constexpr int bases = (void*)(X*)&z <= (Y*)&z; // expected-error {{constexpr variable 'bases' must be initialized by a constant expression}} \399                                                 // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}} \400                                                 // interpreter-note {{initializer of 'z' is unknown}}401}402 403namespace InvalidConstexprFn {404  // Make sure we don't trigger -Winvalid-constexpr incorrectly.405  constexpr bool same_address(const int &a, const int &b) { return &a == &b; }406  constexpr int next_element(const int &p) { return (&p)[2]; }407 408  struct Base {};409  struct Derived : Base { int n; };410  constexpr int get_derived_member(const Base& b) { return static_cast<const Derived&>(b).n; }411 412  struct PolyBase {413    constexpr virtual int get() const { return 0; }414  };415  struct PolyDerived : PolyBase {416    constexpr int get() const override { return 1; }417  };418  constexpr int virtual_call(const PolyBase& b) { return b.get(); }419  constexpr auto* type(const PolyBase& b) { return &typeid(b); }420  constexpr const void* dyncast(const PolyBase& b) { return dynamic_cast<const void*>(&b); }421  constexpr int sub(const int (&a)[], const int (&b)[]) { return a-b; }422  constexpr const int* add(const int &a) { return &a+3; }423 424  constexpr int arr[3]{0, 1, 2};425  static_assert(same_address(arr[1], arr[1]));426  static_assert(next_element(arr[0]) == 2);427  static_assert(get_derived_member(Derived{}) == 0);428  static_assert(virtual_call(PolyDerived{}) == 1);429  static_assert(type(PolyDerived{}) != nullptr);430  static_assert(dyncast(PolyDerived{}) != nullptr);431  static_assert(sub(arr, arr) == 0);432  static_assert(add(arr[0]) == &arr[3]);433}434