Clang Project

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