xref: /llvm-project/clang/test/CXX/drs/cwg25xx.cpp (revision eff126501efc3981727ef0e918c4dca0fa2eb778)
1 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
2 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
3 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
4 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
5 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
6 // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors
7 // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors
8 
9 namespace std {
10 struct type_info{};
11 } // namespace std
12 
13 // cwg2504 is in cwg2504.cpp
14 
15 namespace cwg2512 { // cwg2512: 2.7
16 struct A; // #cwg2512-A
17 void foo(A* p) {
18   typeid(*p);
19   // expected-error@-1 {{'typeid' of incomplete type 'A'}}
20   //   expected-note@#cwg2512-A {{forward declaration of 'cwg2512::A'}}
21 }
22 } // namespace cwg2512
23 
24 namespace cwg2516 { // cwg2516: 3.0
25                    // NB: reusing 1482 test
26 #if __cplusplus >= 201103L
27 template <typename T> struct S {
28   typedef char I;
29 };
30 enum E2 : S<E2>::I { e };
31 // since-cxx11-error@-1 {{use of undeclared identifier 'E2'}}
32 #endif
33 } // namespace cwg2516
34 
35 namespace cwg2518 { // cwg2518: 17
36 
37 #if __cplusplus >= 201103L
38 template <class T>
39 void f(T t) {
40   if constexpr (sizeof(T) != sizeof(int)) {
41   // cxx11-14-error@-1 {{constexpr if is a C++17 extension}}
42     static_assert(false, "must be int-sized");
43     // since-cxx11-error@-1 {{static assertion failed: must be int-sized}}
44     //   since-cxx11-note@#cwg2518-f-c {{in instantiation of function template specialization 'cwg2518::f<char>' requested here}}
45   }
46 }
47 
48 void g(char c) {
49   f(0);
50   f(c); // #cwg2518-f-c
51 }
52 
53 template <typename Ty>
54 struct S {
55   static_assert(false);
56   // cxx11-14-error@-1 {{'static_assert' with no message is a C++17 extension}}
57   // since-cxx11-error@-2 {{static assertion failed}}
58   //   since-cxx11-note@#cwg2518-S-double {{in instantiation of template class 'cwg2518::S<double>' requested here}}
59 };
60 
61 template <>
62 struct S<int> {};
63 
64 template <>
65 struct S<float> {};
66 
67 int test_specialization() {
68   S<int> s1;
69   S<float> s2;
70   S<double> s3; // #cwg2518-S-double
71 }
72 #endif
73 
74 } // namespace cwg2518
75 
76 namespace cwg2521 { // cwg2521: 17
77 #if __cplusplus >= 201103L
78 #pragma clang diagnostic push
79 #pragma clang diagnostic warning "-Wdeprecated-literal-operator"
80 long double operator""      _\u03C0___(long double);
81 // since-cxx11-warning@-1 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}}
82 // since-cxx11-warning@-2 {{user-defined literal suffixes containing '__' are reserved}}
83 
84 template <char... Chars> decltype(sizeof 0)
85 operator""  _div();
86 // since-cxx11-warning@-1 {{identifier '_div' preceded by whitespace in a literal operator declaration is deprecated}}
87 
88 using ::cwg2521::operator"" _\u03C0___;
89 // since-cxx11-warning@-1 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}}
90 using ::cwg2521::operator""_div;
91 
92 long double operator"" _RESERVED(long double);
93 // since-cxx11-warning@-1 {{identifier '_RESERVED' preceded by whitespace in a literal operator declaration is deprecated}}
94 #pragma clang diagnostic pop
95 #endif
96 } // namespace cwg2521
97 
98 namespace cwg2547 { // cwg2547: 20
99 #if __cplusplus >= 202302L
100 struct S;
101 // since-cxx23-note@-1 {{forward declaration of 'cwg2547::S'}}
102 // since-cxx23-note@-2 {{forward declaration of 'cwg2547::S'}}
103 // since-cxx23-note@-3 {{forward declaration of 'cwg2547::S'}}
104 bool operator==(S, S) = default;  // error: S is not complete
105 // since-cxx23-error@-1 {{variable has incomplete type 'S'}}
106 // since-cxx23-error@-2 {{variable has incomplete type 'S'}}
107 // since-cxx23-error@-3 {{equality comparison operator is not a friend of incomplete class 'cwg2547::S'}}
108 struct S {
109   friend bool operator==(S, const S&) = default; // error: parameters of different types
110   // since-cxx23-error@-1 {{parameters for defaulted equality comparison operator must have the same type (found 'S' vs 'const S &')}}
111 };
112 enum E { };
113 bool operator==(E, E) = default;  // error: not a member or friend of a class
114 // since-cxx23-error@-1 {{invalid parameter type for non-member defaulted equality comparison operator; found 'E', expected class or reference to a constant class}}
115 
116 struct S2 {
117   bool operator==(this int, S2) = default;
118   // since-cxx23-error@-1 {{invalid parameter type for defaulted equality comparison operator; found 'int', expected 'const cwg2547::S2 &'}}
119 };
120 #endif
121 } // namespace cwg2547
122 
123 namespace cwg2553 { // cwg2553: 18 review 2023-07-14
124 #if __cplusplus >= 202302L
125 struct B {
126   virtual void f(this B&);
127   // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}}
128   static void f(this B&);
129   // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a static function}}
130   virtual void g(); // #cwg2553-g
131 };
132 struct D : B {
133   void g(this D&);
134   // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}}
135   //   since-cxx23-note@#cwg2553-g {{overridden virtual function is here}}
136 };
137 #endif
138 } // namespace cwg2553
139 
140 namespace cwg2554 { // cwg2554: 18 review 2021-12-10
141 #if __cplusplus >= 202302L
142 struct B {
143   virtual void f(); // #cwg2554-g
144 };
145 
146 struct D : B {
147   void f(this D&);
148   // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}}
149   //   since-cxx23-note@#cwg2554-g {{overridden virtual function is here}}
150 };
151 
152 struct D2 : B {
153   void f(this B&);
154   // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}}
155   //   since-cxx23-note@#cwg2554-g {{overridden virtual function is here}}
156 };
157 struct T {};
158 struct D3 : B {
159   void f(this T&);
160   // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}}
161   //   since-cxx23-note@#cwg2554-g {{overridden virtual function is here}}
162 };
163 #endif
164 } // namespace cwg2554
165 
166 namespace cwg2561 { // cwg2561: no
167 #if __cplusplus >= 202302L
168 struct C {
169     constexpr C(auto) { }
170 };
171 void foo() {
172     constexpr auto b = [](this C) { return 1; };
173     // FIXME: closure type shouldn't have a conversion function to function
174     //        pointer, because explicit object parameter is present.
175     constexpr int (*fp)(C) = b;
176     static_assert(fp(1) == 1);
177     static_assert((&decltype(b)::operator())(1) == 1);
178 }
179 #endif
180 } // namespace cwg2561
181 
182 namespace cwg2565 { // cwg2565: 16 open 2023-06-07
183 #if __cplusplus >= 202002L
184   template<typename T>
185     concept C = requires (typename T::type x) {
186       x + 1;
187     };
188   static_assert(!C<int>);
189 
190   // Variant of this as reported in GH57487.
191   template<bool B> struct bool_constant
192   { static constexpr bool value = B; };
193 
194   template<typename T>
195     using is_referenceable
196        = bool_constant<requires (T&) { true; }>;
197 
198   static_assert(!is_referenceable<void>::value);
199   static_assert(is_referenceable<int>::value);
200 
201   template<typename T, typename U>
202   concept TwoParams = requires (T *a, U b){ true;}; // #cwg2565-TPC
203 
204   template<typename T, typename U>
205     requires TwoParams<T, U> // #cwg2565-TPSREQ
206   struct TwoParamsStruct{};
207 
208   using TPSU = TwoParamsStruct<void, void>;
209   // since-cxx20-error@-1 {{constraints not satisfied for class template 'TwoParamsStruct' [with T = void, U = void]}}
210   //   since-cxx20-note@#cwg2565-TPSREQ {{because 'TwoParams<void, void>' evaluated to false}}
211   //   since-cxx20-note@#cwg2565-TPC {{because 'b' would be invalid: argument may not have 'void' type}}
212 
213   template<typename T, typename ...U>
214   concept Variadic = requires (U* ... a, T b){ true;}; // #cwg2565-VC
215 
216   template<typename T, typename ...U>
217     requires Variadic<T, U...> // #cwg2565-VSREQ
218   struct VariadicStruct{};
219 
220   using VSU = VariadicStruct<void, int, char, double>;
221   // since-cxx20-error@-1 {{constraints not satisfied for class template 'VariadicStruct' [with T = void, U = <int, char, double>]}}
222   //   since-cxx20-note@#cwg2565-VSREQ {{because 'Variadic<void, int, char, double>' evaluated to false}}
223   //   since-cxx20-note@#cwg2565-VC {{because 'b' would be invalid: argument may not have 'void' type}}
224 
225   template<typename T>
226   concept ErrorRequires = requires (ErrorRequires auto x) {
227   // since-cxx20-error@-1 {{a concept definition cannot refer to itself}}
228   //   since-cxx20-note@-2 {{declared here}}
229   // since-cxx20-error@-3 {{'auto' not allowed in requires expression parameter}}
230     x;
231   };
232   static_assert(ErrorRequires<int>);
233   // since-cxx20-error@-1 {{static assertion failed}}
234   //   since-cxx20-note@-2 {{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
235 
236   template<typename T>
237   concept NestedErrorInRequires = requires (T x) { // #cwg2565-NEIR
238     requires requires (NestedErrorInRequires auto y) {
239     // since-cxx20-error@-1 {{a concept definition cannot refer to itself}}
240     //   since-cxx20-note@#cwg2565-NEIR {{declared here}}
241     // since-cxx20-error@-3 {{'auto' not allowed in requires expression parameter}}
242       y;
243     };
244   };
245   static_assert(NestedErrorInRequires<int>);
246   // since-cxx20-error@-1 {{static assertion failed}}
247   //   since-cxx20-note@-2 {{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
248 
249 #endif
250 } // namespace cwg2565
251 
252 namespace cwg2583 { // cwg2583: 19
253 #if __cplusplus >= 201103L
254 struct A {
255   int i;
256   char c;
257 };
258 
259 struct B {
260   int i;
261   alignas(8) char c;
262 };
263 
264 union U {
265   A a;
266   B b;
267 };
268 
269 union V {
270   A a;
271   alignas(64) B b;
272 };
273 
274 static_assert(!__is_layout_compatible(A, B), "");
275 static_assert(__is_layout_compatible(U, V), "");
276 #endif
277 } // namespace cwg2583
278 
279 namespace cwg2586 { // cwg2586: 20
280 #if __cplusplus >= 202302L
281 struct X {
282   X& operator=(this X&, const X&) = default;
283   X& operator=(this X&, X&) = default;
284   X& operator=(this X&&, X&&) = default;
285   // FIXME: The notes could be clearer on *how* the type differs
286   // e.g., "if an explicit object parameter is used it must be of type reference to 'X'"
287   X& operator=(this int, const X&) = default;
288   // since-cxx23-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}}
289   //   since-cxx23-note@-2 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
290   X& operator=(this X, const X&) = default;
291   // since-cxx23-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}}
292   //   since-cxx23-note@-2 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
293 };
294 struct Y {
295   void operator=(this int, const Y&); // This is copy constructor, suppresses implicit declaration
296 };
297 static_assert([]<typename T = Y>{
298   return !requires(T t, const T& ct) { t = ct; };
299 }());
300 
301 struct Z {
302   bool operator==(this const Z&, const Z&) = default;
303   bool operator==(this Z, Z) = default;
304   bool operator==(this Z, const Z&) = default;
305   // since-cxx23-error@-1 {{parameters for defaulted equality comparison operator must have the same type (found 'Z' vs 'const Z &')}}
306   bool operator==(this const Z&, Z) = default;
307   // since-cxx23-error@-1 {{parameters for defaulted equality comparison operator must have the same type (found 'const Z &' vs 'Z')}}
308   bool operator==(this int, Z) = default;
309   // since-cxx23-error@-1 {{invalid parameter type for defaulted equality comparison operator; found 'int', expected 'const cwg2586::Z &'}}
310 };
311 #endif
312 } // namespace cwg2586
313 
314 namespace cwg2598 { // cwg2598: 18
315 #if __cplusplus >= 201103L
316 struct NonLiteral {
317     NonLiteral();
318 };
319 
320 struct anonymous1 {
321     union {} a;
322 };
323 static_assert(__is_literal(anonymous1), "");
324 
325 struct anonymous2 {
326     union { char c; };
327 };
328 static_assert(__is_literal(anonymous2), "");
329 
330 struct anonymous3 {
331     union { char c; NonLiteral NL; };
332 };
333 static_assert(__is_literal(anonymous3), "");
334 
335 struct anonymous4 {
336     union { NonLiteral NL; };
337 };
338 static_assert(!__is_literal(anonymous4), "");
339 
340 union empty {};
341 static_assert(__is_literal(empty), "");
342 
343 union union1 { char c; };
344 static_assert(__is_literal(union1), "");
345 
346 union union2 { char c; NonLiteral NL;};
347 static_assert(__is_literal(union2), "");
348 
349 union union3 { NonLiteral NL;};
350 static_assert(!__is_literal(union3), "");
351 
352 union union4 { union4(); };
353 static_assert(!__is_literal(union4), "");
354 
355 union union5 { static NonLiteral NL; };
356 static_assert(__is_literal(union5), "");
357 
358 struct Literal { constexpr Literal() {} };
359 union union6 { NonLiteral NL; Literal L; };
360 static_assert(__is_literal(union6), "");
361 
362 #if __cplusplus >= 202003L
363 struct A { A(); };
364 union U {
365   A a;
366   constexpr U() {}
367   constexpr ~U() {}
368 };
369 static_assert(!__is_literal(U), "");
370 #endif
371 #endif
372 } // namespace cwg2598
373