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