1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
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 
14 // C++ [temp.expl.spec]p1:
15 //   An explicit specialization of any of the following:
16 
17 //     -- function template
18 namespace N0 {
19   template<typename T> void f0(T) {
20     T t;
21   }
22 
23   template<> void f0(NonDefaultConstructible) { }
24 
25   void test_f0(NonDefaultConstructible NDC) {
26     f0(NDC);
27   }
28 
29   template<> void f0(int);
30   template<> void f0(long);
31 }
32 
33 template<> void N0::f0(int) { } // okay
34 
35 namespace N1 {
36   template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
37 }
38 
39 template<> void N0::f0(double) { }
40 
41 struct X1 {
42   template<typename T> void f(T);
43 
44   template<> void f(int); // expected-error{{in class scope}}
45 };
46 
47 //     -- class template
48 namespace N0 {
49 
50 template<typename T>
51 struct X0 { // expected-note {{here}}
52   static T member;
53 
54   void f1(T t) {
55     t = 17;
56   }
57 
58   struct Inner : public T { }; // expected-note 2{{here}}
59 
60   template<typename U>
61   struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \
62    // expected-error{{base specifier}}
63 
64   template<typename U>
65   void ft1(T t, U u);
66 };
67 
68 }
69 
70 template<typename T>
71 template<typename U>
72 void N0::X0<T>::ft1(T t, U u) {
73   t = u;
74 }
75 
76 template<typename T> T N0::X0<T>::member;
77 
78 template<> struct N0::X0<void> { };
79 N0::X0<void> test_X0;
80 
81 namespace N1 {
82   template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' must originally be declared in namespace 'N0'}}
83 }
84 
85 namespace N0 {
86   template<> struct X0<volatile void>;
87 }
88 
89 template<> struct N0::X0<volatile void> {
90   void f1(void *);
91 };
92 
93 //     -- member function of a class template
94 template<> void N0::X0<void*>::f1(void *) { }
95 
96 void test_spec(N0::X0<void*> xvp, void *vp) {
97   xvp.f1(vp);
98 }
99 
100 namespace N0 {
101   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
102 
103   template<> void X0<const volatile void*>::f1(const volatile void*);
104 }
105 
106 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
107   x0.f1(cvp); // okay: we've explicitly specialized
108 }
109 
110 //     -- static data member of a class template
111 namespace N0 {
112   // This actually tests p15; the following is a declaration, not a definition.
113   template<>
114   NonDefaultConstructible X0<NonDefaultConstructible>::member;
115 
116   template<> long X0<long>::member = 17;
117 
118   template<> float X0<float>::member;
119 
120   template<> double X0<double>::member;
121 }
122 
123 NonDefaultConstructible &get_static_member() {
124   return N0::X0<NonDefaultConstructible>::member;
125 }
126 
127 template<> int N0::X0<int>::member;
128 
129 template<> float N0::X0<float>::member = 3.14f;
130 
131 namespace N1 {
132   template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
133 }
134 
135 //    -- member class of a class template
136 namespace N0 {
137 
138   template<>
139   struct X0<void*>::Inner { };
140 
141   template<>
142   struct X0<int>::Inner { };
143 
144   template<>
145   struct X0<unsigned>::Inner;
146 
147   template<>
148   struct X0<float>::Inner;
149 
150   template<>
151   struct X0<double>::Inner; // expected-note{{forward declaration}}
152 }
153 
154 template<>
155 struct N0::X0<long>::Inner { };
156 
157 template<>
158 struct N0::X0<float>::Inner { };
159 
160 namespace N1 {
161   template<>
162   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
163 
164   template<>
165   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
166 };
167 
168 N0::X0<void*>::Inner inner0;
169 N0::X0<int>::Inner inner1;
170 N0::X0<long>::Inner inner2;
171 N0::X0<float>::Inner inner3;
172 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
173 
174 //    -- member class template of a class template
175 namespace N0 {
176   template<>
177   template<>
178   struct X0<void*>::InnerTemplate<int> { };
179 
180   template<> template<>
181   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
182 
183   template<> template<>
184   struct X0<int>::InnerTemplate<long>;
185 
186   template<> template<>
187   struct X0<int>::InnerTemplate<double>;
188 }
189 
190 template<> template<>
191 struct N0::X0<int>::InnerTemplate<long> { }; // okay
192 
193 template<> template<>
194 struct N0::X0<int>::InnerTemplate<float> { };
195 
196 namespace N1 {
197   template<> template<>
198   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
199 }
200 
201 N0::X0<void*>::InnerTemplate<int> inner_template0;
202 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
203 N0::X0<int>::InnerTemplate<long> inner_template2;
204 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
205 
206 //    -- member function template of a class template
207 namespace N0 {
208   template<>
209   template<>
210   void X0<void*>::ft1(void*, const void*) { }
211 
212   template<> template<>
213   void X0<void*>::ft1(void *, int);
214 
215   template<> template<>
216   void X0<void*>::ft1(void *, unsigned);
217 
218   template<> template<>
219   void X0<void*>::ft1(void *, long);
220 }
221 
222 template<> template<>
223 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
224 
225 template<> template<>
226 void N0::X0<void*>::ft1(void *, float) { }
227 
228 namespace N1 {
229   template<> template<>
230   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
231 }
232 
233 
234 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
235                         int i, unsigned u) {
236   xvp.ft1(vp, cvp);
237   xvp.ft1(vp, i);
238   xvp.ft1(vp, u);
239 }
240 
241 namespace has_inline_namespaces {
242   inline namespace inner {
243     template<class T> void f(T&);
244 
245     template<class T>
246     struct X0 {
247       struct MemberClass;
248 
249       void mem_func();
250 
251       template<typename U>
252       struct MemberClassTemplate;
253 
254       template<typename U>
255       void mem_func_template(U&);
256 
257       static int value;
258     };
259   }
260 
261   struct X1;
262   struct X2;
263 
264   // An explicit specialization whose declarator-id is not qualified
265   // shall be declared in the nearest enclosing namespace of the
266   // template, or, if the namespace is inline (7.3.1), any namespace
267   // from its enclosing namespace set.
268   template<> void f(X1&);
269   template<> void f<X2>(X2&);
270 
271   template<> struct X0<X1> { };
272 
273   template<> struct X0<X2>::MemberClass { };
274 
275   template<> void X0<X2>::mem_func();
276 
277   template<> template<typename T> struct X0<X2>::MemberClassTemplate { };
278 
279   template<> template<typename T> void X0<X2>::mem_func_template(T&) { }
280 
281   template<> int X0<X2>::value = 12;
282 }
283 
284 struct X3;
285 struct X4;
286 
287 template<> void has_inline_namespaces::f(X3&);
288 template<> void has_inline_namespaces::f<X4>(X4&);
289 
290 template<> struct has_inline_namespaces::X0<X3> { };
291 
292 template<> struct has_inline_namespaces::X0<X4>::MemberClass { };
293 
294 template<> void has_inline_namespaces::X0<X4>::mem_func();
295 
296 template<> template<typename T>
297 struct has_inline_namespaces::X0<X4>::MemberClassTemplate { };
298 
299 template<> template<typename T>
300 void has_inline_namespaces::X0<X4>::mem_func_template(T&) { }
301 
302 template<> int has_inline_namespaces::X0<X4>::value = 13;
303 
304 namespace PR12938 {
305   template<typename> [[noreturn]] void func();
306   template<> void func<int>();
307 }
308