// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s // This test covers modifications made by P2448R2. // Check that there is no error when a constexpr function that never produces a // constant expression, but still an error if such function is called from // constexpr context. constexpr int F(int N) { double D = 2.0 / 0.0; // expected-note {{division by zero}} return 1; } constexpr int F0(int N) { if (N == 0) double d2 = 2.0 / 0.0; // expected-note {{division by zero}} return 1; } template constexpr int FT(T N) { double D = 2.0 / 0.0; // expected-note {{division by zero}} return 1; } class NonLiteral { // expected-note {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}} public: NonLiteral() {} ~NonLiteral() {} // expected-note {{declared here}} }; constexpr NonLiteral F1() { return NonLiteral{}; } constexpr int F2(NonLiteral N) { // expected-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} return 8; } class Derived : public NonLiteral { constexpr ~Derived() {}; }; class Derived1 : public NonLiteral { constexpr Derived1() : NonLiteral () {} }; struct X { X(); // expected-note 2{{declared here}} X(const X&); X(X&&); X& operator=(X&); X& operator=(X&& other); bool operator==(X const&) const; }; template struct Wrapper { constexpr Wrapper() = default; constexpr Wrapper(Wrapper const&) = default; constexpr Wrapper(T const& t) : t(t) { } constexpr Wrapper(Wrapper &&) = default; constexpr X get() const { return t; } constexpr bool operator==(Wrapper const&) const = default; private: T t; }; struct WrapperNonT { constexpr WrapperNonT() = default; constexpr WrapperNonT(WrapperNonT const&) = default; constexpr WrapperNonT(X const& t) : t(t) { } constexpr WrapperNonT(WrapperNonT &&) = default; constexpr WrapperNonT& operator=(WrapperNonT &) = default; constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; constexpr X get() const { return t; } constexpr bool operator==(WrapperNonT const&) const = default; private: X t; }; struct NonDefaultMembers { constexpr NonDefaultMembers() {}; // expected-note 2{{non-constexpr constructor 'X' cannot be used in a constant expression}} constexpr NonDefaultMembers(NonDefaultMembers const&) {}; constexpr NonDefaultMembers(NonDefaultMembers &&) {}; constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;} constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;} constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;} X t; }; int Glob = 0; class C1 { public: constexpr C1() : D(Glob) {}; private: int D; }; void test() { constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}} // expected-note@-1 {{in call}} F(3); constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}} // expected-note@-1 {{in call}} F0(0); constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}} F1(); NonLiteral L; constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}} constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}} // expected-note@-1 {{in call}} F2(L); Wrapper x; WrapperNonT x1; NonDefaultMembers x2; // TODO these produce notes with an invalid source location. // static_assert((Wrapper(), true)); // static_assert((WrapperNonT(), true),""); static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \ // expected-note {{in call to}} constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error {{must be initialized by a constant expression}} \ // expected-note {{in call to 'NonDefaultMembers()'}} } struct A { A (); ~A(); }; template struct opt { union { char c; T data; }; constexpr opt() {} constexpr ~opt() { if (engaged) data.~T(); } bool engaged = false; }; consteval void foo() { opt a; } void bar() { foo(); }