xref: /llvm-project/clang/test/CXX/drs/cwg7xx.cpp (revision 14ba3f9d07ea1664497c5d117120fb243ca221aa)
1 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify=expected,cxx98,cxx98-14,cxx98-11 -fexceptions -fcxx-exceptions -pedantic-errors
2 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify=expected,cxx98-14,cxx98-11,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
3 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify=expected,cxx98-14,since-cxx14,since-cxx11,cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
4 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
5 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
6 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
7 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2c %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
8 
9 #if __cplusplus == 199711L
10 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
11 // cxx98-error@-1 {{variadic macros are a C99 feature}}
12 #endif
13 
14 namespace cwg705 { // cwg705: 2.7
15   namespace N {
16     struct S {};
17     void f(S); // #cwg705-f
18   }
19 
20   void g() {
21     N::S s;
22     f(s);      // ok
23     (f)(s);
24     // expected-error@-1 {{use of undeclared identifier 'f'}}
25     //   expected-note@#cwg705-f {{'N::f' declared here}}
26   }
27 } // namespace cwg705
28 
29 namespace cwg712 { // cwg712: partial
30   void use(int);
31   void f() {
32     const int a = 0; // #cwg712-f-a
33     struct X {
34       void g(bool cond) {
35         use(a);
36         use((a));
37         use(cond ? a : a);
38         use((cond, a));
39         // expected-warning@-1 {{left operand of comma operator has no effect}}
40 
41         (void)a;
42         // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg712::f'}} FIXME
43         //   expected-note@#cwg712-f-a {{'a' declared here}}
44         (void)(a);
45         // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg712::f'}} FIXME
46         //   expected-note@#cwg712-f-a {{'a' declared here}}
47         (void)(cond ? a : a); // #cwg712-ternary
48         // expected-error@#cwg712-ternary {{reference to local variable 'a' declared in enclosing function 'cwg712::f'}} FIXME
49         //   expected-note@#cwg712-f-a {{'a' declared here}}
50         // expected-error@#cwg712-ternary {{reference to local variable 'a' declared in enclosing function 'cwg712::f'}} FIXME
51         //   expected-note@#cwg712-f-a {{'a' declared here}}
52         (void)(cond, a); // #cwg712-comma
53         // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg712::f'}} FIXME
54         //   expected-note@#cwg712-f-a {{'a' declared here}}
55         // expected-warning@#cwg712-comma {{left operand of comma operator has no effect}}
56       }
57     };
58   }
59 
60 #if __cplusplus >= 201103L
61   void g() {
62     struct A { int n; };
63     constexpr A a = {0};  // #cwg712-g-a
64     struct X {
65       void g(bool cond) {
66         use(a.n);
67         use(a.*&A::n);
68 
69         (void)a.n;
70         // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg712::g'}} FIXME
71         //   since-cxx11-note@#cwg712-g-a {{'a' declared here}}
72         (void)(a.*&A::n);
73         // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg712::g'}} FIXME
74         //   since-cxx11-note@#cwg712-g-a {{'a' declared here}}
75       }
76     };
77   }
78 #endif
79 } // namespace cwg712
80 
81 namespace cwg713 { // cwg713: 3.0
82 template<typename T>
83 struct is_const {
84     static const bool value = __is_const(T);
85 };
86 template<typename T>
87 struct is_volatile {
88     static const bool value = __is_volatile(T);
89 };
90 
91 static_assert(!is_const<void()const>::value, "");
92 static_assert(!is_const<void()const volatile>::value, "");
93 static_assert(!is_volatile<void()volatile>::value, "");
94 static_assert(!is_volatile<void()const volatile>::value, "");
95 #if __cplusplus >= 201103L
96 static_assert(!is_const<void()const&>::value, "");
97 static_assert(!is_volatile<void()volatile&>::value, "");
98 #endif
99 } // namespace cwg713
100 
101 // cwg722 is in cwg722.cpp
102 
103 namespace cwg727 { // cwg727: partial
104   struct A {
105     template<typename T> struct C; // #cwg727-C
106     template<typename T> void f(); // #cwg727-f
107     template<typename T> static int N; // #cwg727-N
108     // cxx98-11-error@-1 {{variable templates are a C++14 extension}}
109 
110     template<> struct C<int>;
111     template<> void f<int>();
112     template<> int N<int>;
113 
114     template<typename T> struct C<T*>;
115     template<typename T> static int N<T*>;
116 
117     struct B {
118       template<> struct C<float>;
119       // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}}
120       //   expected-note@#cwg727-C {{explicitly specialized declaration is here}}
121       template<> void f<float>();
122       // expected-error@-1 {{no function template matches function template specialization 'f'}}
123       template<> int N<float>;
124       // expected-error@-1 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}}
125       //   expected-note@#cwg727-N {{explicitly specialized declaration is here}}
126 
127       template<typename T> struct C<T**>;
128       // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}}
129       //   expected-note@#cwg727-C {{explicitly specialized declaration is here}}
130       template<typename T> static int N<T**>;
131       // expected-error@-1 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}}
132       //   expected-note@#cwg727-N {{explicitly specialized declaration is here}}
133 
134       template<> struct A::C<double>;
135       // expected-error@-1 {{non-friend class member 'C' cannot have a qualified name}}
136       // expected-error@-2 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}}
137       //   expected-note@#cwg727-C {{explicitly specialized declaration is here}}
138       template<> void A::f<double>();
139       // expected-error@-1 {{o function template matches function template specialization 'f'}}
140       // expected-error@-2 {{non-friend class member 'f' cannot have a qualified name}}
141       template<> int A::N<double>;
142       // expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}}
143       // expected-error@-2 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}}
144       //   expected-note@#cwg727-N {{explicitly specialized declaration is here}}
145 
146       template<typename T> struct A::C<T***>;
147       // expected-error@-1 {{non-friend class member 'C' cannot have a qualified name}}
148       // expected-error@-2 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}}
149       //   expected-note@#cwg727-C {{explicitly specialized declaration is here}}
150       template<typename T> static int A::N<T***>;
151       // expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}}
152       // expected-error@-2 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}}
153       //   expected-note@#cwg727-N {{explicitly specialized declaration is here}}
154     };
155   };
156 
157   template<> struct A::C<char>;
158   template<> void A::f<char>();
159   template<> int A::N<char>;
160 
161   template<typename T> struct A::C<T****>;
162   template<typename T> int A::N<T****>;
163 
164   namespace C {
165     template<> struct A::C<long>;
166     // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}}
167     //   expected-note@#cwg727-C {{explicitly specialized declaration is here}}
168     template<> void A::f<long>();
169     // expected-error@-1 {{function template specialization of 'f' not in class 'A' or an enclosing namespace}}
170     //   expected-note@#cwg727-f {{explicitly specialized declaration is here}}
171     template<> int A::N<long>;
172     // expected-error@-1 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}}
173     //   expected-note@#cwg727-N {{explicitly specialized declaration is here}}
174 
175     template<typename T> struct A::C<T*****>;
176     // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}}
177     //   expected-note@#cwg727-C {{explicitly specialized declaration is here}}
178     template<typename T> int A::N<T*****>;
179     // expected-error@-1 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}}
180     //   expected-note@#cwg727-N {{explicitly specialized declaration is here}}
181   }
182 
183   template<typename>
184   struct D {
185     template<typename T> struct C { typename T::error e; };
186     // expected-error@-1 {{type 'float' cannot be used prior to '::' because it has no members}}
187     //   expected-note@#cwg727-C-float {{in instantiation of template class 'cwg727::D<int>::C<float>' requested here}}
188     template<typename T> void f() { T::error; }
189     // expected-error@-1 {{type 'float' cannot be used prior to '::' because it has no members}}
190     //   expected-note@#cwg727-f-float {{in instantiation of function template specialization 'cwg727::D<int>::f<float>' requested here}}
191     template<typename T> static const int N = T::error;
192     // cxx98-11-error@-1 {{variable templates are a C++14 extension}}
193     // expected-error@-2 {{type 'float' cannot be used prior to '::' because it has no members}}
194     //   expected-note@#cwg727-N-float {{in instantiation of static data member 'cwg727::D<int>::N<float>' requested here}}
195 
196     template<> struct C<int> {};
197     template<> void f<int>() {}
198     template<> const int N<int>;
199 
200     template<typename T> struct C<T*> {};
201     template<typename T> static const int N<T*>;
202 
203     template<typename>
204     struct E {
205       template<> void f<void>() {}
206       // expected-error@-1 {{no candidate function template was found for dependent member function template specialization}}
207     };
208   };
209 
210   void d(D<int> di) {
211     D<int>::C<int>();
212     di.f<int>();
213     int a = D<int>::N<int>;
214 
215     D<int>::C<int*>();
216     int b = D<int>::N<int*>;
217 
218     D<int>::C<float>(); // #cwg727-C-float
219     di.f<float>(); // #cwg727-f-float
220     int c = D<int>::N<float>; // #cwg727-N-float
221   }
222 
223   namespace mixed_inner_outer_specialization {
224 #if __cplusplus >= 201103L
225     template<int> struct A {
226       template<int> constexpr int f() const { return 1; }
227       template<> constexpr int f<0>() const { return 2; }
228     };
229     template<> template<int> constexpr int A<0>::f() const { return 3; }
230     template<> template<> constexpr int A<0>::f<0>() const { return 4; }
231     static_assert(A<1>().f<1>() == 1, "");
232     static_assert(A<1>().f<0>() == 2, "");
233     static_assert(A<0>().f<1>() == 3, "");
234     static_assert(A<0>().f<0>() == 4, "");
235 #endif
236 
237 #if __cplusplus >= 201402L
238     template<int> struct B {
239       template<int> static const int u = 1;
240       template<> const int u<0> = 2; // #cwg727-u0
241 
242       // Note that in C++17 onwards, these are implicitly inline, and so the
243       // initializer of v<0> is not instantiated with the declaration. In
244       // C++14, v<0> is a non-defining declaration and its initializer is
245       // instantiated with the class.
246       template<int> static constexpr int v = 1;
247       template<> constexpr int v<0> = 2; // #cwg727-v0
248 
249       template<int> static const inline int w = 1;
250       // cxx14-error@-1 {{inline variables are a C++17 extension}}
251       template<> const inline int w<0> = 2;
252       // cxx14-error@-1 {{inline variables are a C++17 extension}}
253     };
254 
255     template<> template<int> constexpr int B<0>::u = 3;
256     template<> template<> constexpr int B<0>::u<0> = 4;
257     // since-cxx14-error@-1 {{static data member 'u' already has an initializer}}
258     //   since-cxx14-note@#cwg727-u0 {{previous initialization is here}}
259 
260     template<> template<int> constexpr int B<0>::v = 3;
261     template<> template<> constexpr int B<0>::v<0> = 4;
262     // cxx14-error@-1 {{static data member 'v' already has an initializer}}
263     //   cxx14-note@#cwg727-v0 {{previous initialization is here}}
264 
265     template<> template<int> constexpr int B<0>::w = 3;
266     template<> template<> constexpr int B<0>::w<0> = 4;
267 
268     static_assert(B<1>().u<1> == 1, "");
269     static_assert(B<1>().u<0> == 2, "");
270     static_assert(B<0>().u<1> == 3, "");
271 
272     static_assert(B<1>().v<1> == 1, "");
273     static_assert(B<1>().v<0> == 2, "");
274     static_assert(B<0>().v<1> == 3, "");
275     static_assert(B<0>().v<0> == 4, "");
276     // cxx14-error@-1 {{static assertion failed due to requirement 'cwg727::mixed_inner_outer_specialization::B<0>().v<0> == 4'}}
277     //   cxx14-note@-2 {{expression evaluates to '2 == 4'}}
278 
279     static_assert(B<1>().w<1> == 1, "");
280     static_assert(B<1>().w<0> == 2, "");
281     static_assert(B<0>().w<1> == 3, "");
282     static_assert(B<0>().w<0> == 4, "");
283 #endif
284   }
285 
286   template<typename T, typename U> struct Collision {
287     // FIXME: Missing diagnostic for duplicate function explicit specialization declaration.
288     template<typename> int f1();
289     template<> int f1<T>();
290     template<> int f1<U>();
291 
292     // FIXME: Missing diagnostic for fucntion redefinition!
293     template<typename> int f2();
294     template<> int f2<T>() {}
295     template<> int f2<U>() {}
296 
297     template<typename> static int v1;
298     // cxx98-11-error@-1 {{variable templates are a C++14 extension}}
299     template<> int v1<T>; // #cwg727-v1-T
300     template<> int v1<U>;
301     // expected-error@-1 {{duplicate member 'v1'}}
302     //   expected-note@#cwg727-Collision-int-int {{in instantiation of template class 'cwg727::Collision<int, int>' requested here}}
303     //   expected-note@#cwg727-v1-T {{previous}}
304 
305     template<typename> static inline int v2;
306     // cxx98-11-error@-1 {{variable templates are a C++14 extension}}
307     // cxx98-14-error@-2 {{inline variables are a C++17 extension}}
308     template<> inline int v2<T>; // #cwg727-v2-T
309     // cxx98-14-error@-1 {{inline variables are a C++17 extension}}
310     template<> inline int v2<U>;
311     // cxx98-14-error@-1 {{inline variables are a C++17 extension}}
312     // expected-error@-2 {{duplicate member 'v2'}}
313     //   expected-note@#cwg727-v2-T {{previous declaration is here}}
314 
315     // FIXME: Missing diagnostic for duplicate class explicit specialization.
316     template<typename> struct S1;
317     template<> struct S1<T>;
318     template<> struct S1<U>;
319 
320     template<typename> struct S2;
321     template<> struct S2<T> {}; // #cwg727-S2-T
322     template<> struct S2<U> {};
323     // expected-error@-1 {{redefinition of 'S2<int>'}}
324     //   expected-note@#cwg727-S2-T {{previous}}
325   };
326   Collision<int, int> c; // #cwg727-Collision-int-int
327 } // namespace cwg727
328 
329 namespace cwg777 { // cwg777: 3.7
330 #if __cplusplus >= 201103L
331 template <typename... T>
332 void f(int i = 0, T ...args) {}
333 void ff() { f(); }
334 
335 template <typename... T>
336 void g(int i = 0, T ...args, T ...args2) {}
337 
338 template <typename... T>
339 void h(int i = 0, T ...args, int j = 1) {}
340 #endif
341 } // namespace cwg777
342 
343 namespace cwg794 { // cwg794: 2.7
344 struct B {};
345 struct D : B {};
346 struct X {
347   D d;
348 };
349 struct Y : X {};
350 B Y::*pm = &X::d;
351 // expected-error@-1 {{cannot initialize a variable of type 'B Y::*' with an rvalue of type 'D cwg794::X::*': different classes ('Y' vs 'cwg794::X')}}
352 // FIXME: why diagnostic says just `Y` and not `cwg794::Y`, like `cwg794::X`?
353 } // namespace cwg794
354