xref: /llvm-project/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp (revision dbe308c000f3401cbf6bb55f2b8d606fe091dcfe)
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