Clang Project

clang_source_code/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
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).
12struct 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
21namespace 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
36template<> void N0::f0(int) { } // okay
37
38namespace N1 {
39  template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
40}
41
42template<> void N0::f0(double);
43
44template<> void N0::f0(double) { }
45
46struct X1 {
47  template<typename T> void f(T);
48  
49  template<> void f(int);
50};
51
52//     -- class template
53namespace N0 {
54  
55template<typename T>
56struct 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
75template<typename T> 
76template<typename U>
77void N0::X0<T>::ft1(T t, U u) {
78  t = u;
79}
80
81template<typename T> T N0::X0<T>::member;
82
83template<> struct N0::X0<void> { };
84N0::X0<void> test_X0;
85
86namespace N1 {
87  template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}}
88}
89
90namespace N0 {
91  template<> struct X0<volatile void>;
92}
93
94template<> struct N0::X0<volatile void> { 
95  void f1(void *);
96};
97
98//     -- member function of a class template
99template<> void N0::X0<void*>::f1(void *) { }
100
101void test_spec(N0::X0<void*> xvp, void *vp) {
102  xvp.f1(vp);
103}
104
105namespace 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
111void 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
116namespace 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
128NonDefaultConstructible &get_static_member() {
129  return N0::X0<NonDefaultConstructible>::member;
130}
131
132template<> int N0::X0<int>::member;
133
134template<> float N0::X0<float>::member = 3.14f;
135
136namespace 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
141namespace 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
159template<>
160struct N0::X0<long>::Inner { };
161
162template<>
163struct N0::X0<float>::Inner { };
164
165namespace 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
173N0::X0<void*>::Inner inner0;
174N0::X0<int>::Inner inner1;
175N0::X0<long>::Inner inner2;
176N0::X0<float>::Inner inner3;
177N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
178
179//    -- member class template of a class template
180namespace 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
195template<> template<>
196struct N0::X0<int>::InnerTemplate<long> { }; // okay
197
198template<> template<>
199struct N0::X0<int>::InnerTemplate<float> { };
200
201namespace N1 {
202  template<> template<>
203  struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
204}
205
206N0::X0<void*>::InnerTemplate<int> inner_template0;
207N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
208N0::X0<int>::InnerTemplate<long> inner_template2;
209N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
210
211//    -- member function template of a class template
212namespace 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
227template<> template<>
228void N0::X0<void*>::ft1(void *, unsigned) { } // okay
229
230template<> template<>
231void N0::X0<void*>::ft1(void *, float) { }
232
233namespace N1 {
234  template<> template<>
235  void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
236}
237
238
239void 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
246namespace 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