1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | |
3 | template<typename T> |
4 | struct X0 { |
5 | void f(); |
6 | |
7 | template<typename U> |
8 | void g(U); |
9 | |
10 | struct Nested { |
11 | }; |
12 | |
13 | static T member; |
14 | }; |
15 | |
16 | int &use_X0_int(X0<int> x0i, // expected-note{{implicit instantiation first required here}} |
17 | int i) { |
18 | x0i.f(); // expected-note{{implicit instantiation first required here}} |
19 | x0i.g(i); // expected-note{{implicit instantiation first required here}} |
20 | X0<int>::Nested nested; // expected-note{{implicit instantiation first required here}} |
21 | return X0<int>::member; // expected-note{{implicit instantiation first required here}} |
22 | } |
23 | |
24 | template<> |
25 | void X0<int>::f() { // expected-error{{after instantiation}} |
26 | } |
27 | |
28 | template<> template<> |
29 | void X0<int>::g(int) { // expected-error{{after instantiation}} |
30 | } |
31 | |
32 | template<> |
33 | struct X0<int>::Nested { }; // expected-error{{after instantiation}} |
34 | |
35 | template<> |
36 | int X0<int>::member = 17; // expected-error{{after instantiation}} |
37 | |
38 | template<> |
39 | struct X0<int> { }; // expected-error{{after instantiation}} |
40 | |
41 | // Example from the standard |
42 | template<class T> class Array { /* ... */ }; |
43 | |
44 | template<class T> void sort(Array<T>& v) { /* ... */ } |
45 | |
46 | struct String {}; |
47 | |
48 | void f(Array<String>& v) { |
49 | |
50 | sort(v); // expected-note{{required}} |
51 | // use primary template |
52 | // sort(Array<T>&), T is String |
53 | } |
54 | |
55 | template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}} |
56 | template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used |
57 | |
58 | namespace PR6160 { |
59 | template<typename T> void f(T); |
60 | template<> void f(int); |
61 | extern template void f(int); |
62 | template<> void f(int) { } |
63 | } |
64 | |