• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-c++1y-extensions
2 
3 // This test creates cases where implicit instantiations of various entities
4 // would cause a diagnostic, but provides expliict specializations for those
5 // entities that avoid the diagnostic. The specializations are alternately
6 // declarations and definitions, and the intent of this test is to verify
7 // that we allow specializations only in the appropriate namespaces (and
8 // nowhere else).
9 struct NonDefaultConstructible {
10   NonDefaultConstructible(int);
11 };
12 
13 // FIXME: The "must originally be declared in namespace" diagnostics throughout
14 // this file are wrong.
15 
16 // C++ [temp.expl.spec]p1:
17 //   An explicit specialization of any of the following:
18 
19 //     -- function template
20 namespace N0 {
f0(T)21   template<typename T> void f0(T) {
22     T t;
23   }
24 
f0(NonDefaultConstructible)25   template<> void f0(NonDefaultConstructible) { }
26 
test_f0(NonDefaultConstructible NDC)27   void test_f0(NonDefaultConstructible NDC) {
28     f0(NDC);
29   }
30 
31   template<> void f0(int);
32   template<> void f0(long);
33 }
34 
f0(int)35 template<> void N0::f0(int) { } // okay
36 
37 namespace N1 {
f0(long)38   template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
39 }
40 
f0(double)41 template<> void N0::f0(double) { }
42 
43 struct X1 {
44   template<typename T> void f(T);
45 
46   template<> void f(int); // expected-error{{in class scope}}
47 };
48 
49 //     -- class template
50 namespace N0 {
51 
52 template<typename T>
53 struct X0 { // expected-note {{here}}
54   static T member;
55 
f1N0::X056   void f1(T t) {
57     t = 17;
58   }
59 
60   struct Inner : public T { }; // expected-note 2{{here}}
61 
62   template<typename U>
63   struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \
64    // expected-error{{base specifier}}
65 
66   template<typename U>
67   void ft1(T t, U u);
68 };
69 
70 }
71 
72 template<typename T>
73 template<typename U>
ft1(T t,U u)74 void N0::X0<T>::ft1(T t, U u) {
75   t = u;
76 }
77 
78 template<typename T> T N0::X0<T>::member;
79 
80 template<> struct N0::X0<void> { };
81 N0::X0<void> test_X0;
82 
83 namespace N1 {
84   template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}}
85 }
86 
87 namespace N0 {
88   template<> struct X0<volatile void>;
89 }
90 
91 template<> struct N0::X0<volatile void> {
92   void f1(void *);
93 };
94 
95 //     -- variable template [C++1y]
96 namespace N0 {
97 template<typename T> int v0; // expected-note +{{here}}
98 template<> extern int v0<char[1]>;
99 template<> extern int v0<char[2]>;
100 template<> extern int v0<char[5]>;
101 template<> extern int v0<char[6]>;
102 }
103 using N0::v0;
104 
105 template<typename T> int v1; // expected-note +{{here}}
106 template<> extern int v1<char[3]>;
107 template<> extern int v1<char[4]>;
108 template<> extern int v1<char[7]>;
109 template<> extern int v1<char[8]>;
110 
111 template<> int N0::v0<int[1]>;
112 template<> int v0<int[2]>; // FIXME: ill-formed
113 template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}
114 template<> int v1<int[4]>;
115 
116 template<> int N0::v0<char[1]>;
117 template<> int v0<char[2]>; // FIXME: ill-formed
118 template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}
119 template<> int v1<char[4]>;
120 
121 namespace N1 {
122 template<> int N0::v0<int[5]>; // expected-error {{must originally be declared in namespace 'N0'}} expected-error {{does not enclose namespace}}
123 template<> int v0<int[6]>; // expected-error {{must originally be declared in namespace 'N0'}}
124 template<> int ::v1<int[7]>; // expected-error {{must originally be declared in the global scope}} expected-error {{cannot name the global scope}}
125 template<> int v1<int[8]>; // expected-error {{must originally be declared in the global scope}}
126 
127 template<> int N0::v0<char[5]>; // expected-error {{does not enclose namespace 'N0'}}
128 template<> int v0<char[6]>; // FIXME: ill-formed
129 template<> int ::v1<char[7]>; // expected-error {{cannot name the global scope}}
130 template<> int v1<char[8]>; // FIXME: ill-formed
131 }
132 
133 //     -- member function of a class template
f1(void *)134 template<> void N0::X0<void*>::f1(void *) { }
135 
test_spec(N0::X0<void * > xvp,void * vp)136 void test_spec(N0::X0<void*> xvp, void *vp) {
137   xvp.f1(vp);
138 }
139 
140 namespace N0 {
f1(void *)141   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
142 
143   template<> void X0<const volatile void*>::f1(const volatile void*);
144 }
145 
test_x0_cvvoid(N0::X0<const volatile void * > x0,const volatile void * cvp)146 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
147   x0.f1(cvp); // okay: we've explicitly specialized
148 }
149 
150 //     -- static data member of a class template
151 namespace N0 {
152   // This actually tests p15; the following is a declaration, not a definition.
153   template<>
154   NonDefaultConstructible X0<NonDefaultConstructible>::member;
155 
156   template<> long X0<long>::member = 17;
157 
158   template<> float X0<float>::member;
159 
160   template<> double X0<double>::member;
161 }
162 
get_static_member()163 NonDefaultConstructible &get_static_member() {
164   return N0::X0<NonDefaultConstructible>::member;
165 }
166 
167 template<> int N0::X0<int>::member;
168 
169 template<> float N0::X0<float>::member = 3.14f;
170 
171 namespace N1 {
172   template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
173 }
174 
175 //    -- member class of a class template
176 namespace N0 {
177 
178   template<>
179   struct X0<void*>::Inner { };
180 
181   template<>
182   struct X0<int>::Inner { };
183 
184   template<>
185   struct X0<unsigned>::Inner;
186 
187   template<>
188   struct X0<float>::Inner;
189 
190   template<>
191   struct X0<double>::Inner; // expected-note{{forward declaration}}
192 }
193 
194 template<>
195 struct N0::X0<long>::Inner { };
196 
197 template<>
198 struct N0::X0<float>::Inner { };
199 
200 namespace N1 {
201   template<>
202   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
203 
204   template<>
205   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
206 };
207 
208 N0::X0<void*>::Inner inner0;
209 N0::X0<int>::Inner inner1;
210 N0::X0<long>::Inner inner2;
211 N0::X0<float>::Inner inner3;
212 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
213 
214 //    -- member class template of a class template
215 namespace N0 {
216   template<>
217   template<>
218   struct X0<void*>::InnerTemplate<int> { };
219 
220   template<> template<>
221   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
222 
223   template<> template<>
224   struct X0<int>::InnerTemplate<long>;
225 
226   template<> template<>
227   struct X0<int>::InnerTemplate<double>;
228 }
229 
230 template<> template<>
231 struct N0::X0<int>::InnerTemplate<long> { }; // okay
232 
233 template<> template<>
234 struct N0::X0<int>::InnerTemplate<float> { };
235 
236 namespace N1 {
237   template<> template<>
238   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
239 }
240 
241 N0::X0<void*>::InnerTemplate<int> inner_template0;
242 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
243 N0::X0<int>::InnerTemplate<long> inner_template2;
244 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
245 
246 //    -- member function template of a class template
247 namespace N0 {
248   template<>
249   template<>
ft1(void *,const void *)250   void X0<void*>::ft1(void*, const void*) { }
251 
252   template<> template<>
253   void X0<void*>::ft1(void *, int);
254 
255   template<> template<>
256   void X0<void*>::ft1(void *, unsigned);
257 
258   template<> template<>
259   void X0<void*>::ft1(void *, long);
260 }
261 
262 template<> template<>
ft1(void *,unsigned)263 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
264 
265 template<> template<>
ft1(void *,float)266 void N0::X0<void*>::ft1(void *, float) { }
267 
268 namespace N1 {
269   template<> template<>
ft1(void *,long)270   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
271 }
272 
273 
test_func_template(N0::X0<void * > xvp,void * vp,const void * cvp,int i,unsigned u)274 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
275                         int i, unsigned u) {
276   xvp.ft1(vp, cvp);
277   xvp.ft1(vp, i);
278   xvp.ft1(vp, u);
279 }
280 
281 namespace has_inline_namespaces {
282   inline namespace inner {
283     template<class T> void f(T&);
284 
285     template<class T>
286     struct X0 {
287       struct MemberClass;
288 
289       void mem_func();
290 
291       template<typename U>
292       struct MemberClassTemplate;
293 
294       template<typename U>
295       void mem_func_template(U&);
296 
297       static int value;
298     };
299   }
300 
301   struct X1;
302   struct X2;
303 
304   // An explicit specialization whose declarator-id is not qualified
305   // shall be declared in the nearest enclosing namespace of the
306   // template, or, if the namespace is inline (7.3.1), any namespace
307   // from its enclosing namespace set.
308   template<> void f(X1&);
309   template<> void f<X2>(X2&);
310 
311   template<> struct X0<X1> { };
312 
313   template<> struct X0<X2>::MemberClass { };
314 
315   template<> void X0<X2>::mem_func();
316 
317   template<> template<typename T> struct X0<X2>::MemberClassTemplate { };
318 
mem_func_template(T &)319   template<> template<typename T> void X0<X2>::mem_func_template(T&) { }
320 
321   template<> int X0<X2>::value = 12;
322 }
323 
324 struct X3;
325 struct X4;
326 
327 template<> void has_inline_namespaces::f(X3&);
328 template<> void has_inline_namespaces::f<X4>(X4&);
329 
330 template<> struct has_inline_namespaces::X0<X3> { };
331 
332 template<> struct has_inline_namespaces::X0<X4>::MemberClass { };
333 
334 template<> void has_inline_namespaces::X0<X4>::mem_func();
335 
336 template<> template<typename T>
337 struct has_inline_namespaces::X0<X4>::MemberClassTemplate { };
338 
339 template<> template<typename T>
mem_func_template(T &)340 void has_inline_namespaces::X0<X4>::mem_func_template(T&) { }
341 
342 template<> int has_inline_namespaces::X0<X4>::value = 13;
343 
344 namespace PR12938 {
345   template<typename> [[noreturn]] void func();
346   template<> void func<int>();
347 }
348