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).
9struct 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
20namespace N0 {
21  template<typename T> void f0(T) {
22    T t;
23  }
24
25  template<> void f0(NonDefaultConstructible) { }
26
27  void test_f0(NonDefaultConstructible NDC) {
28    f0(NDC);
29  }
30
31  template<> void f0(int);
32  template<> void f0(long);
33}
34
35template<> void N0::f0(int) { } // okay
36
37namespace N1 {
38  template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
39}
40
41template<> void N0::f0(double) { }
42
43struct X1 {
44  template<typename T> void f(T);
45
46  template<> void f(int); // expected-error{{in class scope}}
47};
48
49//     -- class template
50namespace N0 {
51
52template<typename T>
53struct X0 { // expected-note {{here}}
54  static T member;
55
56  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
72template<typename T>
73template<typename U>
74void N0::X0<T>::ft1(T t, U u) {
75  t = u;
76}
77
78template<typename T> T N0::X0<T>::member;
79
80template<> struct N0::X0<void> { };
81N0::X0<void> test_X0;
82
83namespace N1 {
84  template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}}
85}
86
87namespace N0 {
88  template<> struct X0<volatile void>;
89}
90
91template<> struct N0::X0<volatile void> {
92  void f1(void *);
93};
94
95//     -- variable template [C++1y]
96namespace N0 {
97template<typename T> int v0; // expected-note +{{here}}
98template<> extern int v0<char[1]>;
99template<> extern int v0<char[2]>;
100template<> extern int v0<char[5]>;
101template<> extern int v0<char[6]>;
102}
103using N0::v0;
104
105template<typename T> int v1; // expected-note +{{here}}
106template<> extern int v1<char[3]>;
107template<> extern int v1<char[4]>;
108template<> extern int v1<char[7]>;
109template<> extern int v1<char[8]>;
110
111template<> int N0::v0<int[1]>;
112template<> int v0<int[2]>; // FIXME: ill-formed
113template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}
114template<> int v1<int[4]>;
115
116template<> int N0::v0<char[1]>;
117template<> int v0<char[2]>; // FIXME: ill-formed
118template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}
119template<> int v1<char[4]>;
120
121namespace N1 {
122template<> int N0::v0<int[5]>; // expected-error {{must originally be declared in namespace 'N0'}} expected-error {{does not enclose namespace}}
123template<> int v0<int[6]>; // expected-error {{must originally be declared in namespace 'N0'}}
124template<> int ::v1<int[7]>; // expected-error {{must originally be declared in the global scope}} expected-error {{cannot name the global scope}}
125template<> int v1<int[8]>; // expected-error {{must originally be declared in the global scope}}
126
127template<> int N0::v0<char[5]>; // expected-error {{does not enclose namespace 'N0'}}
128template<> int v0<char[6]>; // FIXME: ill-formed
129template<> int ::v1<char[7]>; // expected-error {{cannot name the global scope}}
130template<> int v1<char[8]>; // FIXME: ill-formed
131}
132
133//     -- member function of a class template
134template<> void N0::X0<void*>::f1(void *) { }
135
136void test_spec(N0::X0<void*> xvp, void *vp) {
137  xvp.f1(vp);
138}
139
140namespace N0 {
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
146void 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
151namespace 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
163NonDefaultConstructible &get_static_member() {
164  return N0::X0<NonDefaultConstructible>::member;
165}
166
167template<> int N0::X0<int>::member;
168
169template<> float N0::X0<float>::member = 3.14f;
170
171namespace 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
176namespace 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
194template<>
195struct N0::X0<long>::Inner { };
196
197template<>
198struct N0::X0<float>::Inner { };
199
200namespace 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
208N0::X0<void*>::Inner inner0;
209N0::X0<int>::Inner inner1;
210N0::X0<long>::Inner inner2;
211N0::X0<float>::Inner inner3;
212N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
213
214//    -- member class template of a class template
215namespace 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
230template<> template<>
231struct N0::X0<int>::InnerTemplate<long> { }; // okay
232
233template<> template<>
234struct N0::X0<int>::InnerTemplate<float> { };
235
236namespace N1 {
237  template<> template<>
238  struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
239}
240
241N0::X0<void*>::InnerTemplate<int> inner_template0;
242N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
243N0::X0<int>::InnerTemplate<long> inner_template2;
244N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
245
246//    -- member function template of a class template
247namespace N0 {
248  template<>
249  template<>
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
262template<> template<>
263void N0::X0<void*>::ft1(void *, unsigned) { } // okay
264
265template<> template<>
266void N0::X0<void*>::ft1(void *, float) { }
267
268namespace N1 {
269  template<> template<>
270  void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
271}
272
273
274void 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
281namespace 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
319  template<> template<typename T> void X0<X2>::mem_func_template(T&) { }
320
321  template<> int X0<X2>::value = 12;
322}
323
324struct X3;
325struct X4;
326
327template<> void has_inline_namespaces::f(X3&);
328template<> void has_inline_namespaces::f<X4>(X4&);
329
330template<> struct has_inline_namespaces::X0<X3> { };
331
332template<> struct has_inline_namespaces::X0<X4>::MemberClass { };
333
334template<> void has_inline_namespaces::X0<X4>::mem_func();
335
336template<> template<typename T>
337struct has_inline_namespaces::X0<X4>::MemberClassTemplate { };
338
339template<> template<typename T>
340void has_inline_namespaces::X0<X4>::mem_func_template(T&) { }
341
342template<> int has_inline_namespaces::X0<X4>::value = 13;
343
344namespace PR12938 {
345  template<typename> [[noreturn]] void func();
346  template<> void func<int>();
347}
348