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 { |
22 | template<typename T> void f0(T) { |
23 | T t; |
24 | } |
25 | |
26 | template<> void f0(NonDefaultConstructible) { } |
27 | |
28 | void test_f0(NonDefaultConstructible NDC) { |
29 | f0(NDC); |
30 | } |
31 | |
32 | template<> void f0(int); |
33 | template<> void f0(long); |
34 | } |
35 | |
36 | template<> void N0::f0(int) { } // okay |
37 | |
38 | namespace N1 { |
39 | template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} |
40 | } |
41 | |
42 | template<> void N0::f0(double); |
43 | |
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 | |
59 | 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> |
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 |
99 | template<> void N0::X0<void*>::f1(void *) { } |
100 | |
101 | void test_spec(N0::X0<void*> xvp, void *vp) { |
102 | xvp.f1(vp); |
103 | } |
104 | |
105 | namespace N0 { |
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 | |
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 | |
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<> |
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<> |
228 | void N0::X0<void*>::ft1(void *, unsigned) { } // okay |
229 | |
230 | template<> template<> |
231 | void N0::X0<void*>::ft1(void *, float) { } |
232 | |
233 | namespace N1 { |
234 | template<> template<> |
235 | void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} |
236 | } |
237 | |
238 | |
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 | |