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