1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-c++1y-extensions
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
9 struct NonDefaultConstructible
{
10 NonDefaultConstructible(int);
13 // C++ [temp.expl.spec]p1:
14 // An explicit specialization of any of the following:
16 // -- function template
18 template<typename T
> void f0(T
) {
22 template<> void f0(NonDefaultConstructible
) { }
24 void test_f0(NonDefaultConstructible NDC
) {
28 template<> void f0(int);
29 template<> void f0(long);
32 template<> void N0::f0(int) { } // okay
35 template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
38 template<> void N0::f0(double) { }
41 template<typename T
> void f(T
);
43 template<> void f(int); // OK (DR727)
50 struct X0
{ // expected-note {{here}}
57 struct Inner
: public T
{ }; // expected-note 2{{here}}
60 struct InnerTemplate
: public T
{ }; // expected-note 1{{explicitly specialized}} \
61 // expected-error{{base specifier}}
71 void N0::X0
<T
>::ft1(T t
, U u
) {
75 template<typename T
> T
N0::X0
<T
>::member
;
77 template<> struct N0::X0
<void> { };
81 template<> struct N0::X0
<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}}
85 template<> struct X0
<volatile void>;
88 template<> struct N0::X0
<volatile void> {
92 // -- variable template [C++1y]
94 template<typename T
> int v0
; // expected-note 4{{explicitly specialized declaration is here}}
95 template<> int v0
<char[1]>; // expected-note {{previous definition is here}}
96 template<> int v0
<char[2]>;
97 template<> int v0
<char[5]>; // expected-note {{previous definition is here}}
98 template<> int v0
<char[6]>;
102 template<typename T
> int v1
; // expected-note 4{{explicitly specialized declaration is here}}
103 template<> int v1
<char[3]>; // expected-note {{previous definition is here}}
104 template<> int v1
<char[4]>; // expected-note {{previous definition is here}}
105 template<> int v1
<char[7]>; // expected-note {{previous definition is here}}
106 template<> int v1
<char[8]>;
108 template<> int N0::v0
<int[1]>;
109 template<> int v0
<int[2]>;
110 template<> int ::v1
<int[3]>; // expected-warning {{extra qualification}}
111 template<> int v1
<int[4]>;
113 template<> int N0::v0
<char[1]>; // expected-error {{redefinition of 'v0<char[1]>'}}
114 template<> int v0
<char[2]>;
115 template<> int ::v1
<char[3]>; // expected-warning {{extra qualification}}
116 // expected-error@-1 {{redefinition of 'v1<char[3]>'}}
117 template<> int v1
<char[4]>; // expected-error {{redefinition of 'v1<char[4]>'}}
120 template<> int N0::v0
<int[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
121 template<> int v0
<int[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
122 template<> int ::v1
<int[7]>; // expected-error {{must occur at global scope}}
123 template<> int v1
<int[8]>; // expected-error {{must occur at global scope}}
125 template<> int N0::v0
<char[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
126 // expected-error@-1 {{redefinition of 'v0<char[5]>'}}
127 template<> int v0
<char[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
128 template<> int ::v1
<char[7]>; // expected-error {{must occur at global scope}}
129 // expected-error@-1 {{redefinition of 'v1<char[7]>'}}
130 template<> int v1
<char[8]>; // expected-error {{must occur at global scope}}
133 // -- member function of a class template
134 template<> void N0::X0
<void*>::f1(void *) { }
136 void test_spec(N0::X0
<void*> xvp
, void *vp
) {
141 template<> void X0
<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
143 template<> void X0
<const volatile void*>::f1(const volatile void*);
146 void test_x0_cvvoid(N0::X0
<const volatile void*> x0
, const volatile void *cvp
) {
147 x0
.f1(cvp
); // okay: we've explicitly specialized
150 // -- static data member of a class template
152 // This actually tests p15; the following is a declaration, not a definition.
154 NonDefaultConstructible X0
<NonDefaultConstructible
>::member
;
156 template<> long X0
<long>::member
= 17;
158 template<> float X0
<float>::member
;
160 template<> double X0
<double>::member
;
163 NonDefaultConstructible
&get_static_member() {
164 return N0::X0
<NonDefaultConstructible
>::member
;
167 template<> int N0::X0
<int>::member
;
169 template<> float N0::X0
<float>::member
= 3.14f
;
172 template<> double N0::X0
<double>::member
= 3.14; // expected-error{{does not enclose namespace}}
175 // -- member class of a class template
179 struct X0
<void*>::Inner
{ };
182 struct X0
<int>::Inner
{ };
185 struct X0
<unsigned>::Inner
;
188 struct X0
<float>::Inner
;
191 struct X0
<double>::Inner
; // expected-note{{forward declaration}}
195 struct N0::X0
<long>::Inner
{ };
198 struct N0::X0
<float>::Inner
{ };
202 struct N0::X0
<unsigned>::Inner
{ }; // expected-error{{member class specialization}}
205 struct N0::X0
<unsigned long>::Inner
{ }; // expected-error{{member class specialization}}
208 N0::X0
<void*>::Inner inner0
;
209 N0::X0
<int>::Inner inner1
;
210 N0::X0
<long>::Inner inner2
;
211 N0::X0
<float>::Inner inner3
;
212 N0::X0
<double>::Inner inner4
; // expected-error{{incomplete}}
214 // -- member class template of a class template
218 struct X0
<void*>::InnerTemplate
<int> { };
220 template<> template<>
221 struct X0
<int>::InnerTemplate
<int>; // expected-note{{forward declaration}}
223 template<> template<>
224 struct X0
<int>::InnerTemplate
<long>;
226 template<> template<>
227 struct X0
<int>::InnerTemplate
<double>;
230 template<> template<>
231 struct N0::X0
<int>::InnerTemplate
<long> { }; // okay
233 template<> template<>
234 struct N0::X0
<int>::InnerTemplate
<float> { };
237 template<> template<>
238 struct N0::X0
<int>::InnerTemplate
<double> { }; // expected-error{{enclosing}}
241 N0::X0
<void*>::InnerTemplate
<int> inner_template0
;
242 N0::X0
<int>::InnerTemplate
<int> inner_template1
; // expected-error{{incomplete}}
243 N0::X0
<int>::InnerTemplate
<long> inner_template2
;
244 N0::X0
<int>::InnerTemplate
<unsigned long> inner_template3
; // expected-note{{instantiation}}
246 // -- member function template of a class template
250 void X0
<void*>::ft1(void*, const void*) { }
252 template<> template<>
253 void X0
<void*>::ft1(void *, int);
255 template<> template<>
256 void X0
<void*>::ft1(void *, unsigned);
258 template<> template<>
259 void X0
<void*>::ft1(void *, long);
262 template<> template<>
263 void N0::X0
<void*>::ft1(void *, unsigned) { } // okay
265 template<> template<>
266 void N0::X0
<void*>::ft1(void *, float) { }
269 template<> template<>
270 void N0::X0
<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
274 void test_func_template(N0::X0
<void *> xvp
, void *vp
, const void *cvp
,
281 namespace has_inline_namespaces
{
282 inline namespace inner
{
283 template<class T
> void f(T
&);
292 struct MemberClassTemplate
;
295 void mem_func_template(U
&);
304 // An explicit specialization whose declarator-id is not qualified
305 // shall be declared in the nearest enclosing namespace of the
306 // template, or, if the namespace is inline (7.3.1), any namespace
307 // from its enclosing namespace set.
308 template<> void f(X1
&);
309 template<> void f
<X2
>(X2
&);
311 template<> struct X0
<X1
> { };
313 template<> struct X0
<X2
>::MemberClass
{ };
315 template<> void X0
<X2
>::mem_func();
317 template<> template<typename T
> struct X0
<X2
>::MemberClassTemplate
{ };
319 template<> template<typename T
> void X0
<X2
>::mem_func_template(T
&) { }
321 template<> int X0
<X2
>::value
= 12;
327 template<> void has_inline_namespaces::f(X3
&);
328 template<> void has_inline_namespaces::f
<X4
>(X4
&);
330 template<> struct has_inline_namespaces::X0
<X3
> { };
332 template<> struct has_inline_namespaces::X0
<X4
>::MemberClass
{ };
334 template<> void has_inline_namespaces::X0
<X4
>::mem_func();
336 template<> template<typename T
>
337 struct has_inline_namespaces::X0
<X4
>::MemberClassTemplate
{ };
339 template<> template<typename T
>
340 void has_inline_namespaces::X0
<X4
>::mem_func_template(T
&) { }
342 template<> int has_inline_namespaces::X0
<X4
>::value
= 13;
345 template<typename
> [[noreturn
]] void func();
346 template<> void func
<int>();