xref: /llvm-project/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp (revision c660c8f5d2c76fe0cb18cd027057a58e2cb5de7b)
18fbe78f6SDaniel Dunbar // RUN: %clang_cc1 -fsyntax-only -verify %s
264a1a81eSCharles Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
364a1a81eSCharles Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
464a1a81eSCharles Li 
554888651SDouglas Gregor 
654888651SDouglas Gregor // This test creates cases where implicit instantiations of various entities
754888651SDouglas Gregor // would cause a diagnostic, but provides expliict specializations for those
854888651SDouglas Gregor // entities that avoid the diagnostic. The specializations are alternately
954888651SDouglas Gregor // declarations and definitions, and the intent of this test is to verify
1054888651SDouglas Gregor // that we allow specializations only in the appropriate namespaces (and
1154888651SDouglas Gregor // nowhere else).
1254888651SDouglas Gregor struct NonDefaultConstructible {
1354888651SDouglas Gregor   NonDefaultConstructible(int);
1454888651SDouglas Gregor };
1554888651SDouglas Gregor 
1654888651SDouglas Gregor 
1754888651SDouglas Gregor // C++ [temp.expl.spec]p1:
1854888651SDouglas Gregor //   An explicit specialization of any of the following:
1954888651SDouglas Gregor 
2054888651SDouglas Gregor //     -- function template
2154888651SDouglas Gregor namespace N0 {
f0(T)2264a1a81eSCharles Li   template<typename T> void f0(T) {
2354888651SDouglas Gregor     T t;
2454888651SDouglas Gregor   }
2554888651SDouglas Gregor 
f0(NonDefaultConstructible)2654888651SDouglas Gregor   template<> void f0(NonDefaultConstructible) { }
2754888651SDouglas Gregor 
test_f0(NonDefaultConstructible NDC)2854888651SDouglas Gregor   void test_f0(NonDefaultConstructible NDC) {
2954888651SDouglas Gregor     f0(NDC);
3054888651SDouglas Gregor   }
3154888651SDouglas Gregor 
3254888651SDouglas Gregor   template<> void f0(int);
3354888651SDouglas Gregor   template<> void f0(long);
3454888651SDouglas Gregor }
3554888651SDouglas Gregor 
f0(int)3654888651SDouglas Gregor template<> void N0::f0(int) { } // okay
3754888651SDouglas Gregor 
3854888651SDouglas Gregor namespace N1 {
f0(long)3982269841SRichard Smith   template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
4054888651SDouglas Gregor }
4154888651SDouglas Gregor 
4264a1a81eSCharles Li template<> void N0::f0(double);
4364a1a81eSCharles Li 
f0(double)44e434590bSRichard Smith template<> void N0::f0(double) { }
4554888651SDouglas Gregor 
4640fb7448SDouglas Gregor struct X1 {
4740fb7448SDouglas Gregor   template<typename T> void f(T);
4840fb7448SDouglas Gregor 
49*c660c8f5SRichard Smith   template<> void f(int);
5040fb7448SDouglas Gregor };
5140fb7448SDouglas Gregor 
5254888651SDouglas Gregor //     -- class template
53fbe6d079SDouglas Gregor namespace N0 {
54fbe6d079SDouglas Gregor 
5554888651SDouglas Gregor template<typename T>
5664a1a81eSCharles Li struct X0 { // expected-note {{explicitly specialized declaration is here}}
5764a1a81eSCharles Li   static T member;
5854888651SDouglas Gregor 
f1N0::X05964a1a81eSCharles Li   void f1(T t) {
6054888651SDouglas Gregor     t = 17;
6154888651SDouglas Gregor   }
6254888651SDouglas Gregor 
6364a1a81eSCharles Li   struct Inner : public T { }; // expected-note 2{{explicitly specialized declaration is here}}
6454888651SDouglas Gregor 
6554888651SDouglas Gregor   template<typename U>
6664a1a81eSCharles Li   struct InnerTemplate : public T { }; // expected-note {{explicitly specialized declaration is here}}
67*c660c8f5SRichard Smith   // expected-error@-1 {{base specifier must name a class}}
6854888651SDouglas Gregor 
6954888651SDouglas Gregor   template<typename U>
7064a1a81eSCharles Li   void ft1(T t, U u);
7154888651SDouglas Gregor };
7254888651SDouglas Gregor 
73fbe6d079SDouglas Gregor }
74fbe6d079SDouglas Gregor 
7554888651SDouglas Gregor template<typename T>
7654888651SDouglas Gregor template<typename U>
ft1(T t,U u)77fbe6d079SDouglas Gregor void N0::X0<T>::ft1(T t, U u) {
7854888651SDouglas Gregor   t = u;
7954888651SDouglas Gregor }
8054888651SDouglas Gregor 
81fbe6d079SDouglas Gregor template<typename T> T N0::X0<T>::member;
8254888651SDouglas Gregor 
8364a1a81eSCharles Li template<> struct N0::X0<void> { };
84fbe6d079SDouglas Gregor N0::X0<void> test_X0;
8554888651SDouglas Gregor 
86fbe6d079SDouglas Gregor namespace N1 {
87a98f8fc8SRichard Smith   template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}}
88fbe6d079SDouglas Gregor }
89fbe6d079SDouglas Gregor 
90fbe6d079SDouglas Gregor namespace N0 {
91fbe6d079SDouglas Gregor   template<> struct X0<volatile void>;
92fbe6d079SDouglas Gregor }
93fbe6d079SDouglas Gregor 
945c0405d4SDouglas Gregor template<> struct N0::X0<volatile void> {
955c0405d4SDouglas Gregor   void f1(void *);
965c0405d4SDouglas Gregor };
9754888651SDouglas Gregor 
9854888651SDouglas Gregor //     -- member function of a class template
f1(void *)9964a1a81eSCharles Li template<> void N0::X0<void*>::f1(void *) { }
10054888651SDouglas Gregor 
test_spec(N0::X0<void * > xvp,void * vp)101fbe6d079SDouglas Gregor void test_spec(N0::X0<void*> xvp, void *vp) {
10254888651SDouglas Gregor   xvp.f1(vp);
10354888651SDouglas Gregor }
10454888651SDouglas Gregor 
1055c0405d4SDouglas Gregor namespace N0 {
f1(void *)1065c0405d4SDouglas Gregor   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
107e3dfd482SDouglas Gregor 
108e3dfd482SDouglas Gregor   template<> void X0<const volatile void*>::f1(const volatile void*);
109e3dfd482SDouglas Gregor }
110e3dfd482SDouglas Gregor 
test_x0_cvvoid(N0::X0<const volatile void * > x0,const volatile void * cvp)111e3dfd482SDouglas Gregor void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
112e3dfd482SDouglas Gregor   x0.f1(cvp); // okay: we've explicitly specialized
1135c0405d4SDouglas Gregor }
1145c0405d4SDouglas Gregor 
11554888651SDouglas Gregor //     -- static data member of a class template
11686d142a8SDouglas Gregor namespace N0 {
11786d142a8SDouglas Gregor   // This actually tests p15; the following is a declaration, not a definition.
11854888651SDouglas Gregor   template<>
11986d142a8SDouglas Gregor   NonDefaultConstructible X0<NonDefaultConstructible>::member;
12054888651SDouglas Gregor 
12186d142a8SDouglas Gregor   template<> long X0<long>::member = 17;
12286d142a8SDouglas Gregor 
12386d142a8SDouglas Gregor   template<> float X0<float>::member;
124bbe8f466SDouglas Gregor 
125bbe8f466SDouglas Gregor   template<> double X0<double>::member;
12654888651SDouglas Gregor }
12754888651SDouglas Gregor 
get_static_member()12886d142a8SDouglas Gregor NonDefaultConstructible &get_static_member() {
12986d142a8SDouglas Gregor   return N0::X0<NonDefaultConstructible>::member;
13086d142a8SDouglas Gregor }
13186d142a8SDouglas Gregor 
13264a1a81eSCharles Li template<> int N0::X0<int>::member;
13386d142a8SDouglas Gregor 
13486d142a8SDouglas Gregor template<> float N0::X0<float>::member = 3.14f;
13586d142a8SDouglas Gregor 
136bbe8f466SDouglas Gregor namespace N1 {
13782269841SRichard Smith   template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
138bbe8f466SDouglas Gregor }
139bbe8f466SDouglas Gregor 
14054888651SDouglas Gregor //    -- member class of a class template
141bbe8f466SDouglas Gregor namespace N0 {
142bbe8f466SDouglas Gregor 
14354888651SDouglas Gregor   template<>
14454888651SDouglas Gregor   struct X0<void*>::Inner { };
14554888651SDouglas Gregor 
146bbe8f466SDouglas Gregor   template<>
147bbe8f466SDouglas Gregor   struct X0<int>::Inner { };
14854888651SDouglas Gregor 
149bbe8f466SDouglas Gregor   template<>
150bbe8f466SDouglas Gregor   struct X0<unsigned>::Inner;
151bbe8f466SDouglas Gregor 
152bbe8f466SDouglas Gregor   template<>
153bbe8f466SDouglas Gregor   struct X0<float>::Inner;
154bbe8f466SDouglas Gregor 
155bbe8f466SDouglas Gregor   template<>
156bbe8f466SDouglas Gregor   struct X0<double>::Inner; // expected-note{{forward declaration}}
157bbe8f466SDouglas Gregor }
158bbe8f466SDouglas Gregor 
159bbe8f466SDouglas Gregor template<>
16064a1a81eSCharles Li struct N0::X0<long>::Inner { };
161bbe8f466SDouglas Gregor 
162bbe8f466SDouglas Gregor template<>
163bbe8f466SDouglas Gregor struct N0::X0<float>::Inner { };
164bbe8f466SDouglas Gregor 
165bbe8f466SDouglas Gregor namespace N1 {
166bbe8f466SDouglas Gregor   template<>
167bbe8f466SDouglas Gregor   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
168bbe8f466SDouglas Gregor 
169bbe8f466SDouglas Gregor   template<>
170bbe8f466SDouglas Gregor   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
171bbe8f466SDouglas Gregor };
172bbe8f466SDouglas Gregor 
173bbe8f466SDouglas Gregor N0::X0<void*>::Inner inner0;
174bbe8f466SDouglas Gregor N0::X0<int>::Inner inner1;
175bbe8f466SDouglas Gregor N0::X0<long>::Inner inner2;
176bbe8f466SDouglas Gregor N0::X0<float>::Inner inner3;
177bbe8f466SDouglas Gregor N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
178bbe8f466SDouglas Gregor 
17954888651SDouglas Gregor //    -- member class template of a class template
1801e9b25caSDouglas Gregor namespace N0 {
18154888651SDouglas Gregor   template<>
18254888651SDouglas Gregor   template<>
18354888651SDouglas Gregor   struct X0<void*>::InnerTemplate<int> { };
18454888651SDouglas Gregor 
1851e9b25caSDouglas Gregor   template<> template<>
1861e9b25caSDouglas Gregor   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
18754888651SDouglas Gregor 
1881e9b25caSDouglas Gregor   template<> template<>
1891e9b25caSDouglas Gregor   struct X0<int>::InnerTemplate<long>;
1901e9b25caSDouglas Gregor 
1911e9b25caSDouglas Gregor   template<> template<>
1921e9b25caSDouglas Gregor   struct X0<int>::InnerTemplate<double>;
1931e9b25caSDouglas Gregor }
1941e9b25caSDouglas Gregor 
1951e9b25caSDouglas Gregor template<> template<>
1961e9b25caSDouglas Gregor struct N0::X0<int>::InnerTemplate<long> { }; // okay
1971e9b25caSDouglas Gregor 
1981e9b25caSDouglas Gregor template<> template<>
19964a1a81eSCharles Li struct N0::X0<int>::InnerTemplate<float> { };
2001e9b25caSDouglas Gregor 
2011e9b25caSDouglas Gregor namespace N1 {
2021e9b25caSDouglas Gregor   template<> template<>
2031e9b25caSDouglas Gregor   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
2041e9b25caSDouglas Gregor }
2051e9b25caSDouglas Gregor 
2061e9b25caSDouglas Gregor N0::X0<void*>::InnerTemplate<int> inner_template0;
2071e9b25caSDouglas Gregor N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
2081e9b25caSDouglas Gregor N0::X0<int>::InnerTemplate<long> inner_template2;
2091e9b25caSDouglas Gregor N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
2101e9b25caSDouglas Gregor 
21154888651SDouglas Gregor //    -- member function template of a class template
21219c52729SDouglas Gregor namespace N0 {
21354888651SDouglas Gregor   template<>
21454888651SDouglas Gregor   template<>
ft1(void *,const void *)21554888651SDouglas Gregor   void X0<void*>::ft1(void*, const void*) { }
21654888651SDouglas Gregor 
21719c52729SDouglas Gregor   template<> template<>
21819c52729SDouglas Gregor   void X0<void*>::ft1(void *, int);
21919c52729SDouglas Gregor 
22019c52729SDouglas Gregor   template<> template<>
22119c52729SDouglas Gregor   void X0<void*>::ft1(void *, unsigned);
22219c52729SDouglas Gregor 
22319c52729SDouglas Gregor   template<> template<>
22419c52729SDouglas Gregor   void X0<void*>::ft1(void *, long);
22554888651SDouglas Gregor }
22619c52729SDouglas Gregor 
22719c52729SDouglas Gregor template<> template<>
ft1(void *,unsigned)22819c52729SDouglas Gregor void N0::X0<void*>::ft1(void *, unsigned) { } // okay
22919c52729SDouglas Gregor 
23019c52729SDouglas Gregor template<> template<>
ft1(void *,float)23164a1a81eSCharles Li void N0::X0<void*>::ft1(void *, float) { }
23219c52729SDouglas Gregor 
23319c52729SDouglas Gregor namespace N1 {
23419c52729SDouglas Gregor   template<> template<>
ft1(void *,long)23582269841SRichard Smith   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
23619c52729SDouglas Gregor }
23719c52729SDouglas Gregor 
23819c52729SDouglas Gregor 
test_func_template(N0::X0<void * > xvp,void * vp,const void * cvp,int i,unsigned u)23919c52729SDouglas Gregor void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
24019c52729SDouglas Gregor                         int i, unsigned u) {
24119c52729SDouglas Gregor   xvp.ft1(vp, cvp);
24219c52729SDouglas Gregor   xvp.ft1(vp, i);
24319c52729SDouglas Gregor   xvp.ft1(vp, u);
24419c52729SDouglas Gregor }
24563fab344SDouglas Gregor 
24663fab344SDouglas Gregor namespace PR8979 {
24763fab344SDouglas Gregor   template<typename Z>
24863fab344SDouglas Gregor   struct X0 {
24963fab344SDouglas Gregor     template <class T, class U> class Inner;
25063fab344SDouglas Gregor     struct OtherInner;
25163fab344SDouglas Gregor     template<typename T, typename U> void f(Inner<T, U>&);
25263fab344SDouglas Gregor 
25363fab344SDouglas Gregor     typedef Inner<OtherInner, OtherInner> MyInner;
254*c660c8f5SRichard Smith     template<> void f(MyInner&);
25563fab344SDouglas Gregor   };
25663fab344SDouglas Gregor }
257