brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.1 KiB · 328bd7f Raw
738 lines · cpp
1// RUN: %clang_cc1            -pedantic -verify=expected,both %s -fexperimental-new-constant-interpreter2// RUN: %clang_cc1 -std=c++14 -pedantic -verify=expected,both %s -fexperimental-new-constant-interpreter3// RUN: %clang_cc1 -std=c++20 -pedantic -verify=expected,both %s -fexperimental-new-constant-interpreter4// RUN: %clang_cc1            -pedantic -verify=ref,both      %s5// RUN: %clang_cc1 -std=c++14 -pedantic -verify=ref,both      %s6// RUN: %clang_cc1 -std=c++20 -pedantic -verify=ref,both      %s7 8#define fold(x) (__builtin_constant_p(0) ? (x) : (x))9 10constexpr void doNothing() {}11constexpr int gimme5() {12  doNothing();13  return 5;14}15static_assert(gimme5() == 5, "");16 17 18template<typename T> constexpr T identity(T t) {19  static_assert(true, "");20  return t;21}22static_assert(identity(true), "");23static_assert(identity(true), ""); /// Compiled bytecode should be cached24static_assert(!identity(false), "");25 26template<typename A, typename B>27constexpr bool sameSize() {28  static_assert(sizeof(A) == sizeof(B), ""); // both-error {{static assertion failed}} \29                                             // both-note {{evaluates to}}30  return true;31}32static_assert(sameSize<int, int>(), "");33static_assert(sameSize<unsigned int, int>(), "");34static_assert(sameSize<char, long>(), ""); // both-note {{in instantiation of function template specialization}}35 36 37constexpr auto add(int a, int b) -> int {38  return identity(a) + identity(b);39}40 41constexpr int sub(int a, int b) {42  return a - b;43}44static_assert(sub(5, 2) == 3, "");45static_assert(sub(0, 5) == -5, "");46 47constexpr int norm(int n) {48  if (n >= 0) {49    return identity(n);50  }51  return -identity(n);52}53static_assert(norm(5) == norm(-5), "");54 55constexpr int square(int n) {56  return norm(n) * norm(n);57}58static_assert(square(2) == 4, "");59 60constexpr int add_second(int a, int b, bool doAdd = true) {61  if (doAdd)62    return a + b;63  return a;64}65static_assert(add_second(10, 3, true) == 13, "");66static_assert(add_second(10, 3) == 13, "");67static_assert(add_second(300, -20, false) == 300, "");68 69 70constexpr int sub(int a, int b, int c) {71  return a - b - c;72}73static_assert(sub(10, 8, 2) == 0, "");74 75 76constexpr int recursion(int i) {77  doNothing();78  i = i - 1;79  if (i == 0)80    return identity(0);81 82  return recursion(i);83}84static_assert(recursion(10) == 0, "");85 86template<int N = 5>87constexpr decltype(N) getNum() {88  return N;89}90static_assert(getNum<-2>() == -2, "");91static_assert(getNum<10>() == 10, "");92static_assert(getNum() == 5, "");93 94constexpr int f(); // both-note {{declared here}}95static_assert(f() == 5, ""); // both-error {{not an integral constant expression}} \96                             // both-note {{undefined function 'f'}}97constexpr int a() {98  return f();99}100constexpr int f() {101  return 5;102}103static_assert(a() == 5, "");104 105constexpr int invalid() {106  // Invalid expression in visit().107  while(huh) {} // both-error {{use of undeclared identifier}}108  return 0;109}110 111constexpr void invalid2() {112  int i = 0;113  // Invalid expression in discard().114  huh(); // both-error {{use of undeclared identifier}}115}116 117namespace FunctionPointers {118  constexpr int add(int a, int b) {119    return a + b;120  }121 122  struct S { int a; };123  constexpr S getS() {124    return S{12};125  }126 127  constexpr int applyBinOp(int a, int b, int (*op)(int, int)) {128    return op(a, b); // both-note {{evaluates to a null function pointer}}129  }130  static_assert(applyBinOp(1, 2, add) == 3, "");131  static_assert(applyBinOp(1, 2, nullptr) == 3, ""); // both-error {{not an integral constant expression}} \132                                                     // both-note {{in call to}}133 134 135  constexpr int ignoreReturnValue() {136    int (*foo)(int, int) = add;137 138    foo(1, 2);139    return 1;140  }141  static_assert(ignoreReturnValue() == 1, "");142 143  constexpr int createS(S (*gimme)()) {144    gimme(); // Ignored return value145    return gimme().a;146  }147  static_assert(createS(getS) == 12, "");148 149namespace FunctionReturnType {150  typedef int (*ptr)(int*);151  typedef ptr (*pm)();152 153  constexpr int fun1(int* y) {154      return *y + 10;155  }156  constexpr ptr fun() {157      return &fun1;158  }159  static_assert(fun() == nullptr, ""); // both-error {{static assertion failed}}160 161  constexpr int foo() {162    int (*f)(int *) = fun();163    int m = 0;164 165    m = f(&m);166 167    return m;168  }169  static_assert(foo() == 10, "");170 171  struct S {172    int i;173    void (*fp)();174  };175 176  constexpr S s{ 12 };177  static_assert(s.fp == nullptr, ""); // zero-initialized function pointer.178 179  constexpr int (*op)(int, int) = add;180  constexpr bool b = op;181  static_assert(op, "");182  static_assert(!!op, "");183  constexpr int (*op2)(int, int) = nullptr;184  static_assert(!op2, "");185 186  int m() { return 5;} // both-note {{declared here}}187  constexpr int (*invalidFnPtr)() = m;188  static_assert(invalidFnPtr() == 5, ""); // both-error {{not an integral constant expression}} \189                                          // both-note {{non-constexpr function 'm'}}190 191 192namespace ToBool {193  void mismatched(int x) {}194  typedef void (*callback_t)(int);195  void foo() {196    callback_t callback = (callback_t)mismatched; // warns197    /// Casts a function pointer to a boolean and then back to a function pointer.198    /// This is extracted from test/Sema/callingconv-cast.c199    callback = (callback_t)!mismatched; // both-warning {{address of function 'mismatched' will always evaluate to 'true'}} \200                                        // both-note {{prefix with the address-of operator to silence this warning}}201  }202}203 204 205}206 207namespace Comparison {208  void f(), g();209  constexpr void (*pf)() = &f, (*pg)() = &g;210 211  constexpr bool u13 = pf < pg; // both-warning {{ordered comparison of function pointers}} \212                                // both-error {{must be initialized by a constant expression}} \213                                // both-note {{comparison between pointers to unrelated objects '&f' and '&g' has unspecified value}}214 215  constexpr bool u14 = pf < (void(*)())nullptr; // both-warning {{ordered comparison of function pointers}} \216                                                // both-error {{must be initialized by a constant expression}} \217                                                // both-note {{comparison between pointers to unrelated objects '&f' and 'nullptr' has unspecified value}}218 219 220 221  static_assert(pf != pg, "");222  static_assert(pf == &f, "");223  static_assert(pg == &g, "");224}225 226  constexpr int Double(int n) { return 2 * n; }227  constexpr int Triple(int n) { return 3 * n; }228  constexpr int Twice(int (*F)(int), int n) { return F(F(n)); }229  constexpr int Quadruple(int n) { return Twice(Double, n); }230  constexpr auto Select(int n) -> int (*)(int) {231    return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;232  }233  constexpr int Apply(int (*F)(int), int n) { return F(n); } // both-note {{'F' evaluates to a null function pointer}}234 235  constexpr int Invalid = Apply(Select(0), 0); // both-error {{must be initialized by a constant expression}} \236                                               // both-note {{in call to 'Apply(nullptr, 0)'}}237}238 239struct F {240  constexpr bool ok() const {241    return okRecurse();242  }243  constexpr bool okRecurse() const {244    return true;245  }246};247 248struct BodylessMemberFunction {249  constexpr int first() const {250    return second();251  }252  constexpr int second() const {253    return 1;254  }255};256 257constexpr int nyd(int m);258constexpr int doit() { return nyd(10); }259constexpr int nyd(int m) { return m; }260static_assert(doit() == 10, "");261 262namespace InvalidCall {263  struct S {264    constexpr int a() const { // both-error {{never produces a constant expression}}265      return 1 / 0; // both-note 2{{division by zero}} \266                    // both-warning {{is undefined}}267    }268  };269  constexpr S s;270  static_assert(s.a() == 1, ""); // both-error {{not an integral constant expression}} \271                                 // both-note {{in call to}}272 273  /// This used to cause an assertion failure in the new constant interpreter.274  constexpr void func(); // both-note {{declared here}}275  struct SS {276    constexpr SS() { func(); } // both-note {{undefined function }}277  };278  constexpr SS ss; // both-error {{must be initialized by a constant expression}} \279                   // both-note {{in call to 'SS()'}}280 281 282  /// This should not emit a diagnostic.283  constexpr int f();284  constexpr int a() {285    return f();286  }287  constexpr int f() {288    return 5;289  }290  static_assert(a() == 5, "");291 292}293 294namespace CallWithArgs {295  /// This used to call problems during checkPotentialConstantExpression() runs.296  constexpr void g(int a) {}297  constexpr void f() {298    g(0);299  }300}301 302namespace ReturnLocalPtr {303  constexpr int *p() {304    int a = 12;305    return &a; // both-warning {{address of stack memory}}306  }307 308  /// FIXME: Both interpreters should diagnose this. We're returning a pointer to a local309  /// variable.310  static_assert(p() == nullptr, ""); // both-error {{static assertion failed}}311 312  constexpr const int &p2() {313    int a = 12; // both-note {{declared here}}314    return a; // both-warning {{reference to stack memory associated with local variable}}315  }316 317  static_assert(p2() == 12, ""); // both-error {{not an integral constant expression}} \318                                 // both-note {{read of variable whose lifetime has ended}}319}320 321namespace VoidReturn {322  /// ReturnStmt with an expression in a void function used to cause problems.323  constexpr void bar() {}324  constexpr void foo() {325    return bar();326  }327  static_assert((foo(),1) == 1, "");328}329 330namespace InvalidReclRefs {331  void param(bool b) { // both-note {{declared here}}332    static_assert(b, ""); // both-error {{not an integral constant expression}} \333                          // both-note {{function parameter 'b' with unknown value}}334    static_assert(true ? true : b, "");335  }336 337#if __cplusplus >= 202002L338  consteval void param2(bool b) { // both-note {{declared here}}339    static_assert(b, ""); // both-error {{not an integral constant expression}} \340                          // both-note {{function parameter 'b' with unknown value}}341  }342#endif343}344 345namespace TemplateUndefined {346  template<typename T> constexpr int consume(T);347  // ok, not a constant expression.348  const int k = consume(0);349 350  template<typename T> constexpr int consume(T) { return 0; }351  // ok, constant expression.352  constexpr int l = consume(0);353  static_assert(l == 0, "");354}355 356namespace PtrReturn {357  constexpr void *a() {358    return nullptr;359  }360  static_assert(a() == nullptr, "");361}362 363namespace Variadic {364  struct S { int a; bool b; };365 366  constexpr void variadic_function(int a, ...) {}367  constexpr int f1() {368    variadic_function(1, S{'a', false});369    return 1;370  }371  static_assert(f1() == 1, "");372 373  constexpr int variadic_function2(...) {374    return 12;375  }376  static_assert(variadic_function2() == 12, "");377  static_assert(variadic_function2(1, 2, 3, 4, 5) == 12, "");378  static_assert(variadic_function2(1, variadic_function2()) == 12, "");379 380  constexpr int (*VFP)(...) = variadic_function2;381  static_assert(VFP() == 12, "");382 383  /// Member functions384  struct Foo {385    int a = 0;386    constexpr void bla(...) {}387    constexpr S bla2(...) {388      return S{12, true};389    }390    constexpr Foo(...) : a(1337) {}391    constexpr Foo(void *c, bool b, void*p, ...) : a('a' + b) {}392    constexpr Foo(int a, const S* s, ...) : a(a) {}393  };394 395  constexpr int foo2() {396    Foo f(1, nullptr);397    auto s = f.bla2(1, 2, S{1, false});398    return s.a + s.b;399  }400  static_assert(foo2() == 13, "");401 402  constexpr Foo _f = 123;403  static_assert(_f.a == 1337, "");404 405  constexpr Foo __f(nullptr, false, nullptr, nullptr, 'a', Foo());406  static_assert(__f.a ==  'a', "");407 408 409#if __cplusplus >= 202002L410namespace VariadicVirtual {411  class A {412  public:413    constexpr virtual void foo(int &a, ...) {414      a = 1;415    }416  };417 418  class B : public A {419  public:420    constexpr void foo(int &a, ...) override {421      a = 2;422    }423  };424 425  constexpr int foo() {426    B b;427    int a;428    b.foo(a, 1,2,nullptr);429    return a;430  }431  static_assert(foo() == 2, "");432} // VariadicVirtual433 434namespace VariadicQualified {435  class A {436      public:437      constexpr virtual int foo(...) const {438          return 5;439      }440  };441  class B : public A {};442  class C : public B {443      public:444      constexpr int foo(...) const override {445          return B::foo(1,2,3); // B doesn't have a foo(), so this should call A::foo().446      }447      constexpr int foo2() const {448        return this->A::foo(1,2,3,this);449      }450  };451  constexpr C c;452  static_assert(c.foo() == 5);453  static_assert(c.foo2() == 5);454} // VariadicQualified455#endif456 457}458 459namespace Packs {460  template<typename...T>461  constexpr int foo() { return sizeof...(T); }462  static_assert(foo<int, char>() == 2, "");463  static_assert(foo<>() == 0, "");464}465 466namespace AddressOf {467  struct S {} s;468  static_assert(__builtin_addressof(s) == &s, "");469 470  struct T { constexpr T *operator&() const { return nullptr; } int n; } t;471  constexpr T *pt = __builtin_addressof(t);472  static_assert(&pt->n == &t.n, "");473 474  struct U { int n : 5; } u;475  int *pbf = __builtin_addressof(u.n); // both-error {{address of bit-field requested}}476 477  S *ptmp = __builtin_addressof(S{}); // both-error {{taking the address of a temporary}} \478                                      // both-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}}479 480  constexpr int foo() {return 1;}481  static_assert(__builtin_addressof(foo) == foo, "");482 483  constexpr _Complex float F = {3, 4}; // both-warning {{'_Complex' is a C99 extension}}484  static_assert(__builtin_addressof(F) == &F, "");485 486  void testAddressof(int x) {487    static_assert(&x == __builtin_addressof(x), "");488  }489 490  struct TS {491    constexpr bool f(TS s) const {492      /// The addressof call has a CXXConstructExpr as a parameter.493      return this != __builtin_addressof(s);494    }495  };496  constexpr bool exprAddressOf() {497    TS s;498    return s.f(s);499  }500  static_assert(exprAddressOf(), "");501}502 503namespace std {504template <typename T> struct remove_reference { using type = T; };505template <typename T> struct remove_reference<T &> { using type = T; };506template <typename T> struct remove_reference<T &&> { using type = T; };507template <typename T>508constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {509  return static_cast<typename std::remove_reference<T>::type &&>(t);510}511}512/// The std::move declaration above gets translated to a builtin function.513namespace Move {514#if __cplusplus >= 202002L515  consteval int f_eval() { // both-note 12{{declared here}}516    return 0;517  }518 519  /// From test/SemaCXX/cxx2a-consteval.520  struct Copy {521    int(*ptr)();522    constexpr Copy(int(*p)() = nullptr) : ptr(p) {}523    consteval Copy(const Copy&) = default;524  };525 526  constexpr const Copy &to_lvalue_ref(const Copy &&a) {527    return a;528  }529 530  void test() {531    constexpr const Copy C;532    // there is no the copy constructor call when its argument is a prvalue because of garanteed copy elision.533    // so we need to test with both prvalue and xvalues.534    { Copy c(C); }535    { Copy c((Copy(&f_eval))); } // both-error {{cannot take address of consteval}}536    { Copy c(std::move(C)); }537    { Copy c(std::move(Copy(&f_eval))); } // both-error {{is not a constant expression}} \538                                          // both-note {{to a consteval}}539    { Copy c(to_lvalue_ref((Copy(&f_eval)))); } // both-error {{is not a constant expression}} \540                                                // both-note {{to a consteval}}541    { Copy c(to_lvalue_ref(std::move(C))); }542    { Copy c(to_lvalue_ref(std::move(Copy(&f_eval)))); } // both-error {{is not a constant expression}} \543                                                         // both-note {{to a consteval}}544    { Copy c = Copy(C); }545    { Copy c = Copy(Copy(&f_eval)); } // both-error {{cannot take address of consteval}}546    { Copy c = Copy(std::move(C)); }547    { Copy c = Copy(std::move(Copy(&f_eval))); } // both-error {{is not a constant expression}} \548                                                 // both-note {{to a consteval}}549    { Copy c = Copy(to_lvalue_ref(Copy(&f_eval))); } // both-error {{is not a constant expression}} \550                                                     // both-note {{to a consteval}}551    { Copy c = Copy(to_lvalue_ref(std::move(C))); }552    { Copy c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); } // both-error {{is not a constant expression}} \553                                                                // both-note {{to a consteval}}554    { Copy c; c = Copy(C); }555    { Copy c; c = Copy(Copy(&f_eval)); } // both-error {{cannot take address of consteval}}556    { Copy c; c = Copy(std::move(C)); }557    { Copy c; c = Copy(std::move(Copy(&f_eval))); } // both-error {{is not a constant expression}} \558                                                    // both-note {{to a consteval}}559    { Copy c; c = Copy(to_lvalue_ref(Copy(&f_eval))); } // both-error {{is not a constant expression}} \560                                                        // both-note {{to a consteval}}561    { Copy c; c = Copy(to_lvalue_ref(std::move(C))); }562    { Copy c; c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); } // both-error {{is not a constant expression}} \563                                                                   // both-note {{to a consteval}}564  }565#endif566  constexpr int A = std::move(5);567  static_assert(A == 5, "");568}569 570namespace StaticLocals {571  void test() {572    static int j; // both-note {{declared here}}573    static_assert(&j != nullptr, ""); // both-warning {{always true}}574 575    static_assert(j == 0, ""); // both-error {{not an integral constant expression}} \576                               // both-note {{read of non-const variable 'j'}}577 578    static int k = 0; // both-note {{declared here}}579    static_assert(k == 0, ""); // both-error {{not an integral constant expression}} \580                               // both-note {{read of non-const variable 'k'}}581 582    static const int l = 12;583    static_assert(l == 12, "");584 585    static const int m; // both-error {{default initialization}}586    static_assert(m == 0, "");587  }588}589 590namespace Local {591  /// We used to run into infinite recursin here because we were592  /// trying to evaluate t's initializer while evaluating t's initializer.593  int a() {594    const int t=t;595    return t;596  }597}598 599namespace VariadicOperator {600  struct Callable {601    float& operator()(...);602  };603 604  void test_callable(Callable c) {605    float &fr = c(10);606  }607}608 609namespace WeakCompare {610  [[gnu::weak]]void weak_method();611  static_assert(weak_method != nullptr, ""); // both-error {{not an integral constant expression}} \612                                             // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}}613 614  constexpr auto A = &weak_method;615  static_assert(A != nullptr, ""); // both-error {{not an integral constant expression}} \616                                   // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}}617}618 619namespace FromIntegral {620#if __cplusplus >= 202002L621  typedef double (*DoubleFn)();622  int a[(int)DoubleFn((void*)-1)()]; // both-error {{not allowed at file scope}} \623                                    // both-warning {{variable length arrays}}624  int b[(int)DoubleFn((void*)(-1 + 1))()]; // both-error {{not allowed at file scope}} \625                                           // both-note {{evaluates to a null function pointer}} \626                                           // both-warning {{variable length arrays}}627#endif628}629 630namespace {631  template <typename T> using id = T;632  template <typename T>633  constexpr void g() {634    constexpr id<void (T)> f;635  }636 637  static_assert((g<int>(), true), "");638}639 640namespace {641  /// The InitListExpr here is of void type.642  void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // both-error {{'clang::annotate' attribute requires parameter 1 to be a constant expression}} \643                                                      // both-note {{subexpression not valid in a constant expression}}644}645 646namespace FuncPtrParam {647  void foo(int(&a)()) {648    *a; // both-warning {{expression result unused}}649  }650}651 652namespace {653  void f() noexcept;654  void (&r)() = f;655  void (&cond3)() = r;656}657 658namespace FunctionCast {659  // When folding, we allow functions to be cast to different types. We only660  // allow calls if the dynamic type of the pointer matches the type of the661  // call.662  constexpr int f() { return 1; }663  constexpr void* f2() { return nullptr; }664  constexpr int f3(int a) { return a; }665  typedef double (*DoubleFn)();666  typedef int (*IntFn)();667  typedef int* (*IntPtrFn)();668  constexpr int test1 = (int)DoubleFn(f)(); // both-error {{constant expression}} both-note {{reinterpret_cast}}669  // FIXME: We should print a note explaining the error.670  constexpr int test2 = (int)fold(DoubleFn(f))(); // both-error {{constant expression}}671  constexpr int test3 = (int)IntFn(f)();    // no-op cast672  constexpr int test4 = fold(IntFn(DoubleFn(f)))();673  constexpr int test5 = IntFn(fold(DoubleFn(f)))(); // both-error {{constant expression}} \674                                                    // both-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}675  constexpr int test6 = fold(IntPtrFn(f2))() == nullptr; // both-error {{constant expression}}676  constexpr int test7 = fold(IntFn(f3)()); // both-error {{must be initialized by a constant expression}}677}678 679#if __cplusplus >= 202002L680namespace StableAddress {681  template<unsigned N> struct str {682    char arr[N];683  };684  // FIXME: Deduction guide not needed with P1816R0.685  template<unsigned N> str(const char (&)[N]) -> str<N>;686 687  template<str s> constexpr int sum() {688    int n = 0;689    for (char c : s.arr)690      n += c;691    return n;692  }693  static_assert(sum<str{"$hello $world."}>() == 1234, "");694}695#endif696 697namespace NoDiags {698  void huh();699  template <unsigned>700  constexpr void hd_fun() {701    huh();702  }703 704  constexpr bool foo() {705    hd_fun<1>();706    return true;707  }708}709 710namespace EnableIfWithTemporary {711  struct A { ~A(); };712  int &h() __attribute__((enable_if((A(), true), ""))); // both-warning {{clang extension}}713}714 715namespace LocalVarForParmVarDecl {716  struct Iter {717    void *p;718  };719  constexpr bool bar2(Iter A) {720    return true;721  }722  constexpr bool bar(Iter A, bool b) {723    if (b)724      return true;725 726    return bar(A, true);727  }728  constexpr int foo() {729    return bar(Iter(), false);730  }731  static_assert(foo(), "");732}733 734namespace PtrPtrCast {735  void foo() { ; }736  void bar(int *a) { a = (int *)(void *)(foo); }737}738