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