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