18fbe78f6SDaniel Dunbar // RUN: %clang_cc1 -fsyntax-only -verify %s 200bb0cbfSDouglas Gregor 300bb0cbfSDouglas Gregor template<typename T> 400bb0cbfSDouglas Gregor struct X0 { 500bb0cbfSDouglas Gregor void f(); 600bb0cbfSDouglas Gregor 700bb0cbfSDouglas Gregor template<typename U> 800bb0cbfSDouglas Gregor void g(U); 900bb0cbfSDouglas Gregor 1000bb0cbfSDouglas Gregor struct Nested { 1100bb0cbfSDouglas Gregor }; 1200bb0cbfSDouglas Gregor 1300bb0cbfSDouglas Gregor static T member; 1400bb0cbfSDouglas Gregor }; 1500bb0cbfSDouglas Gregor use_X0_int(X0<int> x0i,int i)1600bb0cbfSDouglas Gregorint &use_X0_int(X0<int> x0i, // expected-note{{implicit instantiation first required here}} 1700bb0cbfSDouglas Gregor int i) { 1800bb0cbfSDouglas Gregor x0i.f(); // expected-note{{implicit instantiation first required here}} 1900bb0cbfSDouglas Gregor x0i.g(i); // expected-note{{implicit instantiation first required here}} 2000bb0cbfSDouglas Gregor X0<int>::Nested nested; // expected-note{{implicit instantiation first required here}} 2100bb0cbfSDouglas Gregor return X0<int>::member; // expected-note{{implicit instantiation first required here}} 2200bb0cbfSDouglas Gregor } 2300bb0cbfSDouglas Gregor 2400bb0cbfSDouglas Gregor template<> f()2500bb0cbfSDouglas Gregorvoid X0<int>::f() { // expected-error{{after instantiation}} 2600bb0cbfSDouglas Gregor } 2700bb0cbfSDouglas Gregor 2800bb0cbfSDouglas Gregor template<> template<> g(int)2900bb0cbfSDouglas Gregorvoid X0<int>::g(int) { // expected-error{{after instantiation}} 3000bb0cbfSDouglas Gregor } 3100bb0cbfSDouglas Gregor 3200bb0cbfSDouglas Gregor template<> 3300bb0cbfSDouglas Gregor struct X0<int>::Nested { }; // expected-error{{after instantiation}} 3400bb0cbfSDouglas Gregor 3500bb0cbfSDouglas Gregor template<> 3600bb0cbfSDouglas Gregor int X0<int>::member = 17; // expected-error{{after instantiation}} 3700bb0cbfSDouglas Gregor 3800bb0cbfSDouglas Gregor template<> 3900bb0cbfSDouglas Gregor struct X0<int> { }; // expected-error{{after instantiation}} 4000bb0cbfSDouglas Gregor 4100bb0cbfSDouglas Gregor // Example from the standard 4200bb0cbfSDouglas Gregor template<class T> class Array { /* ... */ }; 4300bb0cbfSDouglas Gregor sort(Array<T> & v)4400bb0cbfSDouglas Gregortemplate<class T> void sort(Array<T>& v) { /* ... */ } 4500bb0cbfSDouglas Gregor 4600bb0cbfSDouglas Gregor struct String {}; 4700bb0cbfSDouglas Gregor f(Array<String> & v)4800bb0cbfSDouglas Gregorvoid f(Array<String>& v) { 4900bb0cbfSDouglas Gregor 5000bb0cbfSDouglas Gregor sort(v); // expected-note{{required}} 5100bb0cbfSDouglas Gregor // use primary template 5200bb0cbfSDouglas Gregor // sort(Array<T>&), T is String 5300bb0cbfSDouglas Gregor } 5400bb0cbfSDouglas Gregor 5500bb0cbfSDouglas Gregor template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}} 5600bb0cbfSDouglas Gregor template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used 57*c854c665SDouglas Gregor 58*c854c665SDouglas Gregor namespace PR6160 { 59*c854c665SDouglas Gregor template<typename T> void f(T); 60*c854c665SDouglas Gregor template<> void f(int); 61*c854c665SDouglas Gregor extern template void f(int); f(int)62*c854c665SDouglas Gregor template<> void f(int) { } 63*c854c665SDouglas Gregor } 64