xref: /llvm-project/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp (revision ae9d89d53e64bad514171c99f16d553febfbac12)
1 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,beforecxx14,beforecxx20,beforecxx23 -std=c++11 %s
2 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23,cxx14_20 -std=c++14 %s
3 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23,cxx14_20 -std=c++20  %s
4 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20 -std=c++23 %s
5 
6 namespace N {
7   typedef char C;
8 }
9 
10 namespace M {
11   typedef double D;
12 }
13 
14 struct NonLiteral { // beforecxx23-note 2{{no constexpr constructors}}
NonLiteralNonLiteral15   NonLiteral() {}
NonLiteralNonLiteral16   NonLiteral(int) {}
17 };
18 struct Literal {
LiteralLiteral19   constexpr Literal() {}
operator intLiteral20   operator int() const { return 0; }
21 };
22 
23 struct S {
24   virtual int ImplicitlyVirtual() const = 0; // beforecxx20-note {{overridden virtual function}}
25 };
26 struct SS : S {
27   int ImplicitlyVirtual() const;
28 };
29 
30 // The definition of a constexpr function shall satisfy the following
31 // constraints:
32 struct T : SS, NonLiteral {
33   constexpr T();
34   constexpr int f() const;
35 
36   //  - it shall not be virtual; [until C++20]
ExplicitlyVirtualT37   virtual constexpr int ExplicitlyVirtual() const { return 0; } // beforecxx20-error {{virtual function cannot be constexpr}}
38 
ImplicitlyVirtualT39   constexpr int ImplicitlyVirtual() const { return 0; } // beforecxx20-error {{virtual function cannot be constexpr}}
40 
41   virtual constexpr int OutOfLineVirtual() const; // beforecxx20-error {{virtual function cannot be constexpr}}
42 
43   //  - its return type shall be a literal type;
44   // Once we support P2448R2 constexpr functions will be allowd to return non-literal types
45   // The destructor will also be allowed
NonLiteralReturnT46   constexpr NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
VoidReturnT47   constexpr void VoidReturn() const { return; }                // beforecxx14-error {{constexpr function's return type 'void' is not a literal type}}
48   constexpr ~T();                                              // beforecxx20-error {{destructor cannot be declared constexpr}}
49 
50   typedef NonLiteral F() const;
51   constexpr F NonLiteralReturn2; // ok until definition
52 
53   //  - each of its parameter types shall be a literal type;
54   // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types
NonLiteralParamT55   constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
56   typedef int G(NonLiteral) const;
57   constexpr G NonLiteralParam2; // ok until definition
58 
59   //  - its function-body shall be = delete, = default,
60   constexpr int Deleted() const = delete;
61   // It's not possible for the function-body to legally be "= default" here
62   // (that is, for a non-constructor function) in C++11.
63   // Other than constructors, only the copy- and move-assignment operators and
64   // destructor can be defaulted. Destructors can't be constexpr since they
65   // don't have a literal return type. Defaulted assignment operators can't be
66   // constexpr since they can't be const.
67   constexpr T &operator=(const T &) = default; // beforecxx14-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} \
68                                                // beforecxx14-warning {{C++14}} \
69                                                // cxx14_20-error{{defaulted definition of copy assignment operator cannot be marked constexpr}}
70 };
71 
OutOfLineVirtual() const72 constexpr int T::OutOfLineVirtual() const { return 0; }
73 #if __cplusplus >= 201402L
74 struct T2 {
75   int n = 0;
76   constexpr T2 &operator=(const T2&) = default; // ok
77 };
78 struct T3 {
79   constexpr T3 &operator=(const T3 &) const = default; // beforecxx20-error {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}} \
80                                                        // aftercxx20-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} \
81                                                        // aftercxx20-note {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
82 };
83 #endif
84 struct U {
85   constexpr U SelfReturn() const;
86   constexpr int SelfParam(U) const;
87 };
88 
89 struct V : virtual U { // expected-note {{here}}
FV90   constexpr int F() const { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}}
91 };
92 
93 //  or a compound-statememt that contains only [CXX11]
AllowedStmtsCXX11()94 constexpr int AllowedStmtsCXX11() {
95   //  - null statements
96   ;
97 
98   //  - static_assert-declarations
99   static_assert(true, "the impossible happened!");
100 
101   //  - typedef declarations and alias-declarations that do not define classes
102   //    or enumerations
103   typedef int I;
104   typedef struct S T;
105   using J = int;
106   using K = int[sizeof(I) + sizeof(J)];
107   // Note, the standard requires we reject this.
108   struct U;
109 
110   //  - using-declarations
111   using N::C;
112 
113   //  - using-directives
114   using namespace N;
115 
116   //  - and exactly one return statement
117   return sizeof(K) + sizeof(C) + sizeof(K);
118 }
119 
120 //  or a compound-statement that does not contain [C++14]
DisallowedStmtsCXX14_1(bool b)121 constexpr int DisallowedStmtsCXX14_1(bool b) {
122   //  - an asm-definition
123   if (b)
124     asm("int3"); // beforecxx20-warning {{use of this statement in a constexpr function is a C++20 extension}}
125   return 0;
126 }
DisallowedStmtsCXX14_2()127 constexpr int DisallowedStmtsCXX14_2() {
128   return 0; // beforecxx14-note {{previous}}
129   //  - a goto statement
130   goto x; // beforecxx23-warning {{use of this statement in a constexpr function is a C++23 extension}}
131   x:;
132     return 0; // beforecxx14-warning {{multiple return}}
133 }
DisallowedStmtsCXX14_2_1()134 constexpr int DisallowedStmtsCXX14_2_1() {
135 merp: // beforecxx23-warning {{use of this statement in a constexpr function is a C++23 extension}}
136   return 0;
137 }
DisallowedStmtsCXX14_3()138 constexpr int DisallowedStmtsCXX14_3() {
139   //  - a try-block,
140   try {  }  // beforecxx20-warning {{use of this statement in a constexpr function is a C++20 extension}}
141   catch (...) {}
142   return 0;
143 }
DisallowedStmtsCXX14_4()144 constexpr int DisallowedStmtsCXX14_4() {
145   //  - a definition of a variable of non-literal type
146   return 0;
147   NonLiteral nl; // beforecxx23-error {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function before C++23}} \
148                  // beforecxx23-note@14  {{'NonLiteral' is not literal}}
149 }
150 
DisallowedStmtsCXX14_5()151 constexpr int DisallowedStmtsCXX14_5() {
152   return 0;
153   //  - a definition of a variable of static storage duration
154   static constexpr int n = 123; // beforecxx23-warning {{definition of a static variable in a constexpr function is a C++23 extension}} \
155                                //  beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}}
156 }
157 
DisallowedStmtsCXX14_6()158 constexpr int DisallowedStmtsCXX14_6() {
159   //  - a definition of a variable of thread storage duration
160   return 0;
161   thread_local constexpr int n = 123; // beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}} \
162                                       // beforecxx23-warning {{definition of a thread_local variable in a constexpr function is a C++23 extension}}
163 }
DisallowedStmtsCXX14_7()164 constexpr int DisallowedStmtsCXX14_7() {
165   //  - a definition of a variable for which no initialization is performed
166   return 0;
167   int n; // beforecxx20-warning {{uninitialized variable in a constexpr function}}
168 }
169 
ForStmt()170 constexpr int ForStmt() {
171   for (int n = 0; n < 10; ++n) {} // beforecxx14-error {{statement not allowed in constexpr function}}
172     return 0;
173 }
174 
VarDecl()175 constexpr int VarDecl() {
176   int a = 0; // beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}}
177   return 0;
178 }
ConstexprVarDecl()179 constexpr int ConstexprVarDecl() {
180   constexpr int a = 0; // beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}}
181   return 0;
182 }
VarWithCtorDecl()183 constexpr int VarWithCtorDecl() {
184   Literal a; // beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}}
185   return 0;
186 }
187 
188 NonLiteral nl;
ExternNonLiteralVarDecl()189 constexpr NonLiteral &ExternNonLiteralVarDecl() {
190   extern NonLiteral nl; // beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}}
191   return nl;
192 }
193 static_assert(&ExternNonLiteralVarDecl() == &nl, "");
194 
FuncDecl()195 constexpr int FuncDecl() {
196   constexpr int ForwardDecl(int); // beforecxx14-warning {{use of this statement in a constexpr function is a C++14 extension}}
197   return ForwardDecl(42);
198 }
199 
ClassDecl1()200 constexpr int ClassDecl1() {
201   typedef struct {} S1; // beforecxx14-warning {{type definition in a constexpr function is a C++14 extension}}
202   return 0;
203 }
204 
ClassDecl2()205 constexpr int ClassDecl2() {
206   using S2 = struct {}; // beforecxx14-warning {{type definition in a constexpr function is a C++14 extension}}
207   return 0;
208 }
209 
ClassDecl3()210 constexpr int ClassDecl3() {
211   struct S3 {}; // beforecxx14-warning {{type definition in a constexpr function is a C++14 extension}}
212   return 0;
213 }
214 
NoReturn()215 constexpr int NoReturn() {} // beforecxx23-error {{no return statement in constexpr function}}
MultiReturn()216 constexpr int MultiReturn() {
217   return 0; // beforecxx14-note {{return statement}}
218   return 0; // beforecxx14-warning {{multiple return statements in constexpr function}}
219 }
220 
221 //  - every constructor call and implicit conversion used in initializing the
222 //    return value shall be one of those allowed in a constant expression.
223 //
224 // We implement the proposed resolution of DR1364 and ignore this bullet.
225 // However, we implement the spirit of the check as part of the p5 checking that
226 // a constexpr function must be able to produce a constant expression.
227 namespace DR1364 {
f(int k)228   constexpr int f(int k) {
229     return k; // ok, even though lvalue-to-rvalue conversion of a function
230               // parameter is not allowed in a constant expression.
231   }
232   int kGlobal; // beforecxx23-note {{here}}
f()233   constexpr int f() { // beforecxx23-error {{constexpr function never produces a constant expression}}
234     return kGlobal;   // beforecxx23-note {{read of non-const}}
235   }
236 }
237 
238 namespace rdar13584715 {
239   typedef __PTRDIFF_TYPE__ ptrdiff_t;
240 
241   template<typename T> struct X {
valuerdar13584715::X242     static T value() {};
243   };
244 
foo(ptrdiff_t id)245   void foo(ptrdiff_t id) {
246     switch (id) {
247     case reinterpret_cast<ptrdiff_t>(&X<long>::value):  // expected-error{{case value is not a constant expression}} \
248       // expected-note{{reinterpret_cast is not allowed in a constant expression}}
249       break;
250     }
251   }
252 }
253 
254 namespace std_example {
square(int x)255   constexpr int square(int x) {
256     return x * x;
257   }
long_max()258   constexpr long long_max() {
259     return 2147483647;
260   }
abs(int x)261   constexpr int abs(int x) {
262     if (x < 0) // beforecxx14-warning {{C++14}}
263       x = -x;
264     return x;
265   }
first(int n)266   constexpr int first(int n) {
267     return 0;
268     static int value = n; // beforecxx23-warning {{definition of a static variable in a constexpr function is a C++23 extension}} \
269                           // beforecxx14-warning {{variable declaration in a constexpr function is a C++14 extension}}
270   }
uninit()271   constexpr int uninit() {
272     int a; // beforecxx20-warning {{uninitialized}}
273     return a;
274   }
prev(int x)275   constexpr int prev(int x) { // beforecxx14-error {{never produces a constant expression}}
276     return --x;               // beforecxx14-note {{subexpression}}
277   }
278 
g(int x,int n)279   constexpr int g(int x, int n) {
280     int r = 1; // beforecxx14-warning{{C++14}}
281     while (--n > 0) // beforecxx14-error {{statement not allowed in constexpr function}}
282       r *= x;
283     return r;
284   }
285 }
286 
287 struct Base {
288  constexpr Base() = default;
289 };
290 struct Derived : virtual Base { // expected-note 3{{virtual base class declared here}}
291   constexpr Derived() = default; // expected-error {{default constructor cannot be 'constexpr' in a class with virtual base class}}
292   constexpr Derived(const Derived&) = default; // expected-error {{copy constructor cannot be 'constexpr' in a class with virtual base class}}
293   constexpr Derived(Derived&&) = default; // expected-error {{move constructor cannot be 'constexpr' in a class with virtual base class}}
294 };
295