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