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     T t;
24   }
25 
f0(NonDefaultConstructible)26   template<> void f0(NonDefaultConstructible) { }
27 
test_f0(NonDefaultConstructible NDC)28   void test_f0(NonDefaultConstructible NDC) {
29     f0(NDC);
30   }
31 
32   template<> void f0(int);
33   template<> void f0(long);
34 }
35 
f0(int)36 template<> void N0::f0(int) { } // okay
37 
38 namespace N1 {
f0(long)39   template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
40 }
41 
42 template<> void N0::f0(double);
43 
f0(double)44 template<> void N0::f0(double) { }
45 
46 struct X1 {
47   template<typename T> void f(T);
48 
49   template<> void f(int);
50 };
51 
52 //     -- class template
53 namespace N0 {
54 
55 template<typename T>
56 struct X0 { // expected-note {{explicitly specialized declaration is here}}
57   static T member;
58 
f1N0::X059   void f1(T t) {
60     t = 17;
61   }
62 
63   struct Inner : public T { }; // expected-note 2{{explicitly specialized declaration is here}}
64 
65   template<typename U>
66   struct InnerTemplate : public T { }; // expected-note {{explicitly specialized declaration is here}}
67   // expected-error@-1 {{base specifier must name a class}}
68 
69   template<typename U>
70   void ft1(T t, U u);
71 };
72 
73 }
74 
75 template<typename T>
76 template<typename U>
ft1(T t,U u)77 void N0::X0<T>::ft1(T t, U u) {
78   t = u;
79 }
80 
81 template<typename T> T N0::X0<T>::member;
82 
83 template<> struct N0::X0<void> { };
84 N0::X0<void> test_X0;
85 
86 namespace N1 {
87   template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}}
88 }
89 
90 namespace N0 {
91   template<> struct X0<volatile void>;
92 }
93 
94 template<> struct N0::X0<volatile void> {
95   void f1(void *);
96 };
97 
98 //     -- member function of a class template
f1(void *)99 template<> void N0::X0<void*>::f1(void *) { }
100 
test_spec(N0::X0<void * > xvp,void * vp)101 void test_spec(N0::X0<void*> xvp, void *vp) {
102   xvp.f1(vp);
103 }
104 
105 namespace N0 {
f1(void *)106   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
107 
108   template<> void X0<const volatile void*>::f1(const volatile void*);
109 }
110 
test_x0_cvvoid(N0::X0<const volatile void * > x0,const volatile void * cvp)111 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
112   x0.f1(cvp); // okay: we've explicitly specialized
113 }
114 
115 //     -- static data member of a class template
116 namespace N0 {
117   // This actually tests p15; the following is a declaration, not a definition.
118   template<>
119   NonDefaultConstructible X0<NonDefaultConstructible>::member;
120 
121   template<> long X0<long>::member = 17;
122 
123   template<> float X0<float>::member;
124 
125   template<> double X0<double>::member;
126 }
127 
get_static_member()128 NonDefaultConstructible &get_static_member() {
129   return N0::X0<NonDefaultConstructible>::member;
130 }
131 
132 template<> int N0::X0<int>::member;
133 
134 template<> float N0::X0<float>::member = 3.14f;
135 
136 namespace N1 {
137   template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
138 }
139 
140 //    -- member class of a class template
141 namespace N0 {
142 
143   template<>
144   struct X0<void*>::Inner { };
145 
146   template<>
147   struct X0<int>::Inner { };
148 
149   template<>
150   struct X0<unsigned>::Inner;
151 
152   template<>
153   struct X0<float>::Inner;
154 
155   template<>
156   struct X0<double>::Inner; // expected-note{{forward declaration}}
157 }
158 
159 template<>
160 struct N0::X0<long>::Inner { };
161 
162 template<>
163 struct N0::X0<float>::Inner { };
164 
165 namespace N1 {
166   template<>
167   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
168 
169   template<>
170   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
171 };
172 
173 N0::X0<void*>::Inner inner0;
174 N0::X0<int>::Inner inner1;
175 N0::X0<long>::Inner inner2;
176 N0::X0<float>::Inner inner3;
177 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
178 
179 //    -- member class template of a class template
180 namespace N0 {
181   template<>
182   template<>
183   struct X0<void*>::InnerTemplate<int> { };
184 
185   template<> template<>
186   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
187 
188   template<> template<>
189   struct X0<int>::InnerTemplate<long>;
190 
191   template<> template<>
192   struct X0<int>::InnerTemplate<double>;
193 }
194 
195 template<> template<>
196 struct N0::X0<int>::InnerTemplate<long> { }; // okay
197 
198 template<> template<>
199 struct N0::X0<int>::InnerTemplate<float> { };
200 
201 namespace N1 {
202   template<> template<>
203   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
204 }
205 
206 N0::X0<void*>::InnerTemplate<int> inner_template0;
207 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
208 N0::X0<int>::InnerTemplate<long> inner_template2;
209 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
210 
211 //    -- member function template of a class template
212 namespace N0 {
213   template<>
214   template<>
ft1(void *,const void *)215   void X0<void*>::ft1(void*, const void*) { }
216 
217   template<> template<>
218   void X0<void*>::ft1(void *, int);
219 
220   template<> template<>
221   void X0<void*>::ft1(void *, unsigned);
222 
223   template<> template<>
224   void X0<void*>::ft1(void *, long);
225 }
226 
227 template<> template<>
ft1(void *,unsigned)228 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
229 
230 template<> template<>
ft1(void *,float)231 void N0::X0<void*>::ft1(void *, float) { }
232 
233 namespace N1 {
234   template<> template<>
ft1(void *,long)235   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
236 }
237 
238 
test_func_template(N0::X0<void * > xvp,void * vp,const void * cvp,int i,unsigned u)239 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
240                         int i, unsigned u) {
241   xvp.ft1(vp, cvp);
242   xvp.ft1(vp, i);
243   xvp.ft1(vp, u);
244 }
245 
246 namespace PR8979 {
247   template<typename Z>
248   struct X0 {
249     template <class T, class U> class Inner;
250     struct OtherInner;
251     template<typename T, typename U> void f(Inner<T, U>&);
252 
253     typedef Inner<OtherInner, OtherInner> MyInner;
254     template<> void f(MyInner&);
255   };
256 }
257