p2.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
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{{does not enclose namespace}}
37}
38
39template<> void N0::f0(double); // expected-warning{{C++11 extension}}
40template<> void N0::f0(double) { }
41
42struct X1 {
43  template<typename T> void f(T);
44
45  template<> void f(int); // expected-error{{in class scope}}
46};
47
48//     -- class template
49namespace N0 {
50
51template<typename T>
52struct X0 { // expected-note 2{{here}}
53  static T member; // expected-note{{here}}
54
55  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
71template<typename T>
72template<typename U>
73void N0::X0<T>::ft1(T t, U u) {
74  t = u;
75}
76
77template<typename T> T N0::X0<T>::member;
78
79template<> struct N0::X0<void> { }; // expected-warning{{C++11 extension}}
80N0::X0<void> test_X0;
81
82namespace N1 {
83  template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}}
84}
85
86namespace N0 {
87  template<> struct X0<volatile void>;
88}
89
90template<> struct N0::X0<volatile void> {
91  void f1(void *);
92};
93
94//     -- member function of a class template
95template<> void N0::X0<void*>::f1(void *) { } // expected-warning{{member function specialization}}
96
97void test_spec(N0::X0<void*> xvp, void *vp) {
98  xvp.f1(vp);
99}
100
101namespace N0 {
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
107void 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
112namespace 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
124NonDefaultConstructible &get_static_member() {
125  return N0::X0<NonDefaultConstructible>::member;
126}
127
128template<> int N0::X0<int>::member;  // expected-warning{{C++11 extension}}
129
130template<> float N0::X0<float>::member = 3.14f;
131
132namespace 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
137namespace 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
155template<>
156struct N0::X0<long>::Inner { }; // expected-warning{{C++11 extension}}
157
158template<>
159struct N0::X0<float>::Inner { };
160
161namespace 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
169N0::X0<void*>::Inner inner0;
170N0::X0<int>::Inner inner1;
171N0::X0<long>::Inner inner2;
172N0::X0<float>::Inner inner3;
173N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
174
175//    -- member class template of a class template
176namespace 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
191template<> template<>
192struct N0::X0<int>::InnerTemplate<long> { }; // okay
193
194template<> template<>
195struct N0::X0<int>::InnerTemplate<float> { }; // expected-warning{{class template specialization}}
196
197namespace N1 {
198  template<> template<>
199  struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
200}
201
202N0::X0<void*>::InnerTemplate<int> inner_template0;
203N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
204N0::X0<int>::InnerTemplate<long> inner_template2;
205N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
206
207//    -- member function template of a class template
208namespace N0 {
209  template<>
210  template<>
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
223template<> template<>
224void N0::X0<void*>::ft1(void *, unsigned) { } // okay
225
226template<> template<>
227void N0::X0<void*>::ft1(void *, float) { } // expected-warning{{function template specialization}}
228
229namespace N1 {
230  template<> template<>
231  void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
232}
233
234
235void 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
242namespace 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