// RUN: %clang_cc1 -std=c++2a -emit-llvm-only -Wno-unused-value %s -verify typedef __SIZE_TYPE__ size_t; namespace basic_sema { consteval int f1(int i) { return i; } consteval constexpr int f2(int i) { //expected-error@-1 {{cannot combine}} return i; } constexpr auto l_eval = [](int i) consteval { // expected-note@-1+ {{declared here}} return i; }; constexpr consteval int f3(int i) { //expected-error@-1 {{cannot combine}} return i; } struct A { consteval int f1(int i) const { // expected-note@-1 {{declared here}} return i; } consteval A(int i); consteval A() = default; consteval ~A() = default; // expected-error {{destructor cannot be declared consteval}} }; consteval struct B {}; // expected-error {{struct cannot be marked consteval}} consteval typedef B b; // expected-error {{typedef cannot be consteval}} consteval int redecl() {return 0;} // expected-note {{previous declaration is here}} constexpr int redecl() {return 0;} // expected-error {{constexpr declaration of 'redecl' follows consteval declaration}} consteval int i = 0; // expected-error {{consteval can only be used in function declarations}} consteval int; // expected-error {{consteval can only be used in function declarations}} consteval int f1() {} // expected-error {{no return statement in consteval function}} struct C { C() {} ~C() {} }; struct D { C c; consteval D() = default; // expected-error {{cannot be consteval}} consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}} }; struct E : C { consteval ~E() {} // expected-error {{cannot be declared consteval}} }; } consteval int main() { // expected-error {{'main' is not allowed to be declared consteval}} return 0; } consteval int f_eval(int i) { // expected-note@-1+ {{declared here}} return i; } namespace taking_address { using func_type = int(int); func_type* p1 = (&f_eval); // expected-error@-1 {{take address}} func_type* p7 = __builtin_addressof(f_eval); // expected-error@-1 {{take address}} auto p = f_eval; // expected-error@-1 {{take address}} auto m1 = &basic_sema::A::f1; // expected-error@-1 {{take address}} auto l1 = &decltype(basic_sema::l_eval)::operator(); // expected-error@-1 {{take address}} consteval int f(int i) { // expected-note@-1+ {{declared here}} return i; } auto ptr = &f; // expected-error@-1 {{take address}} auto f1() { return &f; // expected-error@-1 {{take address}} } } namespace invalid_function { struct A { consteval void *operator new(size_t count); // expected-error@-1 {{'operator new' cannot be declared consteval}} consteval void *operator new[](size_t count); // expected-error@-1 {{'operator new[]' cannot be declared consteval}} consteval void operator delete(void* ptr); // expected-error@-1 {{'operator delete' cannot be declared consteval}} consteval void operator delete[](void* ptr); // expected-error@-1 {{'operator delete[]' cannot be declared consteval}} consteval ~A() {} // expected-error@-1 {{destructor cannot be declared consteval}} }; } namespace nested { consteval int f() { return 0; } consteval int f1(...) { return 1; } enum E {}; using T = int(&)(); consteval auto operator+ (E, int(*a)()) { return 0; } void d() { auto i = f1(E() + &f); } auto l0 = [](auto) consteval { return 0; }; int i0 = l0(&f1); int i1 = f1(l0(4)); int i2 = f1(&f1, &f1, &f1, &f1, &f1, &f1, &f1); int i3 = f1(f1(f1(&f1, &f1), f1(&f1, &f1), f1(f1(&f1, &f1), &f1))); } namespace user_defined_literal { consteval int operator"" _test(unsigned long long i) { // expected-note@-1+ {{declared here}} return 0; } int i = 0_test; auto ptr = &operator"" _test; // expected-error@-1 {{take address}} consteval auto operator"" _test1(unsigned long long i) { return &f_eval; } auto i1 = 0_test1; // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} } namespace return_address { consteval int f() { // expected-note@-1 {{declared here}} return 0; } consteval int(*ret1(int i))() { return &f; } auto ptr = ret1(0); // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{pointer to a consteval}} struct A { consteval int f(int) { // expected-note@-1+ {{declared here}} return 0; } }; using mem_ptr_type = int (A::*)(int); template struct C {}; C<&A::f> c; // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{pointer to a consteval}} consteval mem_ptr_type ret2() { return &A::f; } C c1; // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{pointer to a consteval}} } namespace context { int g_i; // expected-note@-1 {{declared here}} consteval int f(int) { return 0; } constexpr int c_i = 0; int t1 = f(g_i); // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{read of non-const variable}} int t3 = f(c_i); constexpr int f_c(int i) { // expected-note@-1 {{declared here}} int t = f(i); // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{function parameter}} return f(0); } consteval int f_eval(int i) { return f(i); } auto l0 = [](int i) consteval { return f(i); }; auto l1 = [](int i) constexpr { // expected-note@-1 {{declared here}} int t = f(i); // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{function parameter}} return f(0); }; } namespace std { template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template constexpr typename std::remove_reference::type&& move(T &&t) noexcept { return static_cast::type &&>(t); } } namespace temporaries { struct A { consteval int ret_i() const { return 0; } consteval A ret_a() const { return A{}; } constexpr ~A() { } }; consteval int by_value_a(A a) { return a.ret_i(); } consteval int const_a_ref(const A &a) { return a.ret_i(); } consteval int rvalue_ref(const A &&a) { return a.ret_i(); } consteval const A &to_lvalue_ref(const A &&a) { return a; } void test() { constexpr A a {}; { int k = A().ret_i(); } { A k = A().ret_a(); } { A k = to_lvalue_ref(A()); }// expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} { A k = to_lvalue_ref(A().ret_a()); } // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} { int k = A().ret_a().ret_i(); } { int k = by_value_a(A()); } { int k = const_a_ref(A()); } { int k = const_a_ref(a); } { int k = rvalue_ref(A()); } { int k = rvalue_ref(std::move(a)); } { int k = const_a_ref(A().ret_a()); } { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } { int k = const_a_ref(to_lvalue_ref(std::move(a))); } { int k = by_value_a(A().ret_a()); } { int k = by_value_a(to_lvalue_ref(std::move(a))); } { int k = (A().ret_a(), A().ret_i()); } { int k = (const_a_ref(A().ret_a()), A().ret_i()); }// } } namespace alloc { consteval int f() { int *A = new int(0); // expected-note@-1+ {{allocation performed here was not deallocated}} return *A; } int i1 = f(); // expected-error {{is not a constant expression}} struct A { int* p = new int(42); // expected-note@-1+ {{heap allocation performed here}} consteval int ret_i() const { return p ? *p : 0; } consteval A ret_a() const { return A{}; } constexpr ~A() { delete p; } }; consteval int by_value_a(A a) { return a.ret_i(); } consteval int const_a_ref(const A &a) { return a.ret_i(); } consteval int rvalue_ref(const A &&a) { return a.ret_i(); } consteval const A &to_lvalue_ref(const A &&a) { return a; } void test() { constexpr A a{ nullptr }; { int k = A().ret_i(); } { A k = A().ret_a(); } // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} { A k = to_lvalue_ref(A()); } // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} { A k = to_lvalue_ref(A().ret_a()); } // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} { int k = A().ret_a().ret_i(); } { int k = by_value_a(A()); } { int k = const_a_ref(A()); } { int k = const_a_ref(a); } { int k = rvalue_ref(A()); } { int k = rvalue_ref(std::move(a)); } { int k = const_a_ref(A().ret_a()); } { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } { int k = const_a_ref(to_lvalue_ref(std::move(a))); } { int k = by_value_a(A().ret_a()); } { int k = by_value_a(to_lvalue_ref(static_cast(a))); } { int k = (A().ret_a(), A().ret_i()); }// expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} { int k = (const_a_ref(A().ret_a()), A().ret_i()); } } } namespace self_referencing { struct S { S* ptr = nullptr; constexpr S(int i) : ptr(this) { if (this == ptr && i) ptr = nullptr; } constexpr ~S() {} }; consteval S f(int i) { return S(i); } void test() { S s(1); s = f(1); s = f(0); // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} } struct S1 { S1* ptr = nullptr; consteval S1(int i) : ptr(this) { if (this == ptr && i) ptr = nullptr; } constexpr ~S1() {} }; void test1() { S1 s(1); s = S1(1); s = S1(0); // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} } } namespace ctor { consteval int f_eval() { // expected-note+ {{declared here}} return 0; } namespace std { struct strong_ordering { int n; static const strong_ordering less, equal, greater; }; constexpr strong_ordering strong_ordering::less = {-1}; constexpr strong_ordering strong_ordering::equal = {0}; constexpr strong_ordering strong_ordering::greater = {1}; constexpr bool operator!=(strong_ordering, int); } namespace override { struct A { virtual consteval void f(); // expected-note {{overridden}} virtual void g(); // expected-note {{overridden}} }; struct B : A { consteval void f(); void g(); }; struct C : A { void f(); // expected-error {{non-consteval function 'f' cannot override a consteval function}} consteval void g(); // expected-error {{consteval function 'g' cannot override a non-consteval function}} }; namespace implicit_equals_1 { struct Y; struct X { std::strong_ordering operator<=>(const X&) const; constexpr bool operator==(const X&) const; virtual consteval bool operator==(const Y&) const; // expected-note {{here}} }; struct Y : X { std::strong_ordering operator<=>(const Y&) const = default; // expected-error@-1 {{non-consteval function 'operator==' cannot override a consteval function}} }; } namespace implicit_equals_2 { struct Y; struct X { constexpr std::strong_ordering operator<=>(const X&) const; constexpr bool operator==(const X&) const; virtual bool operator==(const Y&) const; // expected-note {{here}} }; struct Y : X { consteval std::strong_ordering operator<=>(const Y&) const = default; // expected-error@-1 {{consteval function 'operator==' cannot override a non-consteval function}} }; } } namespace operator_rewrite { struct A { friend consteval int operator<=>(const A&, const A&) { return 0; } }; const bool k = A() < A(); static_assert(!k); A a; bool k2 = A() < a; // OK, does not access 'a'. struct B { friend consteval int operator<=>(const B &l, const B &r) { return r.n - l.n; } // expected-note {{read of }} int n; }; static_assert(B() >= B()); B b; // expected-note {{here}} bool k3 = B() < b; // expected-error-re {{call to consteval function '{{.*}}::operator<=>' is not a constant expression}} expected-note {{in call}} } struct A { int(*ptr)(); consteval A(int(*p)() = nullptr) : ptr(p) {} }; struct B { int(*ptr)(); B() : ptr(nullptr) {} consteval B(int(*p)(), int) : ptr(p) {} }; void test() { { A a; } { A a(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B b(nullptr, 0); } { B b(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A a{}; } { A a{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B b{nullptr, 0}; } { B b{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A a = A(); } { A a = A(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B b = B(nullptr, 0); } { B b = B(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A a = A{}; } { A a = A{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B b = B{nullptr, 0}; } { B b = B{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A a; a = A(); } { A a; a = A(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B b; b = B(nullptr, 0); } { B b; b = B(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A a; a = A{}; } { A a; a = A{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B b; b = B{nullptr, 0}; } { B b; b = B{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A* a; a = new A(); } { A* a; a = new A(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B* b; b = new B(nullptr, 0); } { B* b; b = new B(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { A* a; a = new A{}; } { A* a; a = new A{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} { B* b; b = new B{nullptr, 0}; } { B* b; b = new B{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} } } namespace copy_ctor { consteval int f_eval() { // expected-note+ {{declared here}} return 0; } struct Copy { int(*ptr)(); constexpr Copy(int(*p)() = nullptr) : ptr(p) {} consteval Copy(const Copy&) = default; }; constexpr const Copy &to_lvalue_ref(const Copy &&a) { return a; } void test() { constexpr const Copy C; // there is no the copy constructor call when its argument is a prvalue because of garanteed copy elision. // so we need to test with both prvalue and xvalues. { Copy c(C); } { Copy c((Copy(&f_eval))); }// expected-error {{cannot take address of consteval}} { Copy c(std::move(C)); } { Copy c(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c(to_lvalue_ref((Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c(to_lvalue_ref(std::move(C))); } { Copy c(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c = Copy(C); } { Copy c = Copy(Copy(&f_eval)); }// expected-error {{cannot take address of consteval}} { Copy c = Copy(std::move(C)); } { Copy c = Copy(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c = Copy(to_lvalue_ref(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c = Copy(to_lvalue_ref(std::move(C))); } { Copy c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c; c = Copy(C); } { Copy c; c = Copy(Copy(&f_eval)); }// expected-error {{cannot take address of consteval}} { Copy c; c = Copy(std::move(C)); } { Copy c; c = Copy(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c; c = Copy(to_lvalue_ref(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy c; c = Copy(to_lvalue_ref(std::move(C))); } { Copy c; c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy* c; c = new Copy(C); } { Copy* c; c = new Copy(Copy(&f_eval)); }// expected-error {{cannot take address of consteval}} { Copy* c; c = new Copy(std::move(C)); } { Copy* c; c = new Copy(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy* c; c = new Copy(to_lvalue_ref(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} { Copy* c; c = new Copy(to_lvalue_ref(std::move(C))); } { Copy* c; c = new Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} } } // namespace special_ctor