1 // RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s 2 3 // This test covers modifications made by P2448R2. 4 5 // Check that there is no error when a constexpr function that never produces a 6 // constant expression, but still an error if such function is called from 7 // constexpr context. 8 constexpr int F(int N) { 9 double D = 2.0 / 0.0; // expected-note {{division by zero}} 10 return 1; 11 } 12 13 constexpr int F0(int N) { 14 if (N == 0) 15 double d2 = 2.0 / 0.0; // expected-note {{division by zero}} 16 return 1; 17 } 18 19 template <typename T> 20 constexpr int FT(T N) { 21 double D = 2.0 / 0.0; // expected-note {{division by zero}} 22 return 1; 23 } 24 25 class NonLiteral { // expected-note {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}} 26 public: 27 NonLiteral() {} 28 ~NonLiteral() {} // expected-note {{declared here}} 29 }; 30 31 constexpr NonLiteral F1() { 32 return NonLiteral{}; 33 } 34 35 constexpr int F2(NonLiteral N) { // expected-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} 36 return 8; 37 } 38 39 class Derived : public NonLiteral { 40 constexpr ~Derived() {}; 41 }; 42 43 class Derived1 : public NonLiteral { 44 constexpr Derived1() : NonLiteral () {} 45 }; 46 47 48 struct X { 49 X(); // expected-note 2{{declared here}} 50 X(const X&); 51 X(X&&); 52 X& operator=(X&); 53 X& operator=(X&& other); 54 bool operator==(X const&) const; 55 }; 56 57 template <typename T> 58 struct Wrapper { 59 constexpr Wrapper() = default; 60 constexpr Wrapper(Wrapper const&) = default; 61 constexpr Wrapper(T const& t) : t(t) { } 62 constexpr Wrapper(Wrapper &&) = default; 63 constexpr X get() const { return t; } 64 constexpr bool operator==(Wrapper const&) const = default; 65 private: 66 T t; 67 }; 68 69 struct WrapperNonT { 70 constexpr WrapperNonT() = default; 71 constexpr WrapperNonT(WrapperNonT const&) = default; 72 constexpr WrapperNonT(X const& t) : t(t) { } 73 constexpr WrapperNonT(WrapperNonT &&) = default; 74 constexpr WrapperNonT& operator=(WrapperNonT &) = default; 75 constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; 76 constexpr X get() const { return t; } 77 constexpr bool operator==(WrapperNonT const&) const = default; 78 private: 79 X t; 80 }; 81 82 struct NonDefaultMembers { 83 constexpr NonDefaultMembers() {}; // expected-note 2{{non-constexpr constructor 'X' cannot be used in a constant expression}} 84 constexpr NonDefaultMembers(NonDefaultMembers const&) {}; 85 constexpr NonDefaultMembers(NonDefaultMembers &&) {}; 86 constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;} 87 constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;} 88 constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;} 89 X t; 90 }; 91 92 int Glob = 0; 93 class C1 { 94 public: 95 constexpr C1() : D(Glob) {}; 96 private: 97 int D; 98 }; 99 100 void test() { 101 102 constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}} 103 // expected-note@-1 {{in call}} 104 F(3); 105 constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}} 106 // expected-note@-1 {{in call}} 107 F0(0); 108 constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}} 109 F1(); 110 NonLiteral L; 111 constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}} 112 113 constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}} 114 // expected-note@-1 {{in call}} 115 F2(L); 116 117 Wrapper<X> x; 118 WrapperNonT x1; 119 NonDefaultMembers x2; 120 121 // TODO these produce notes with an invalid source location. 122 // static_assert((Wrapper<X>(), true)); 123 // static_assert((WrapperNonT(), true),""); 124 125 static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \ 126 // expected-note {{in call to}} 127 constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error {{must be initialized by a constant expression}} \ 128 // expected-note {{in call to 'NonDefaultMembers()'}} 129 } 130 131 struct A { 132 A (); 133 ~A(); 134 }; 135 136 template <class T> 137 struct opt 138 { 139 union { 140 char c; 141 T data; 142 }; 143 144 constexpr opt() {} 145 146 constexpr ~opt() { 147 if (engaged) 148 data.~T(); 149 } 150 151 bool engaged = false; 152 }; 153 154 consteval void foo() { 155 opt<A> a; 156 } 157 158 void bar() { foo(); } 159