1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2
3 namespace N {
4 enum { C };
5 template<class T> class B {
6 void f(T);
7 };
8 }
9
f(C)10 template<class C> void N::B<C>::f(C) {
11 C b;
12 }
13
14 namespace N {
15 enum { D };
16 namespace M {
17 enum { C , D };
18 template<typename C> class X {
19 template<typename U> void f(C, U);
20
g(C,D)21 template<typename D> void g(C, D) {
22 C c;
23 D d;
24 }
25 };
26
27 struct Y {
28 template<typename U> void f(U);
29 };
30 }
31
32 struct Y {
33 template<typename D> void f(D);
34 };
35 }
36
37 template<typename C>
38 template<typename D>
f(C,D)39 void N::M::X<C>::f(C, D) {
40 C c;
41 D d;
42 }
43
44 template<typename C>
f(C)45 void N::M::Y::f(C) {
46 C c;
47 }
48
49 template<typename D>
f(D)50 void N::Y::f(D) {
51 D d;
52 }
53
54 // Ensure we properly interleave the searches within classes and template parameter lists.
55 namespace SearchClassBetweenTemplateParameterLists {
56 int AA, BB; // none of the below lookups should ever consider these
57
58 struct Base {
59 using AA = void;
60 using BB = void;
61 };
62 struct BaseT : Base {
63 using T = void;
64 };
65 struct BaseU : Base {
66 using U = void;
67 };
68
69 template<typename T> struct A {
70 using AA = void;
71 template<typename U> struct B {
72 using BB = void;
73 void f(U);
74 void g(U);
75 void h(T);
76 void i(T);
77 template<typename V> void j(V);
78 template<typename V> void k(U);
79
80 // OK: these find the template parameter not the member.
lSearchClassBetweenTemplateParameterLists::A::B81 template<typename AA> void l(AA x) { AA aa; }
mSearchClassBetweenTemplateParameterLists::A::B82 template<typename BB> void m(BB x) { BB bb; }
83
84 struct C : Base {
85 // All OK; these find the template parameters.
fSearchClassBetweenTemplateParameterLists::A::B::C86 template<typename> void f(T x) { T t; }
gSearchClassBetweenTemplateParameterLists::A::B::C87 template<typename> void g(U x) { U u; }
hSearchClassBetweenTemplateParameterLists::A::B::C88 template<typename AA> void h(AA x) { AA aa; }
iSearchClassBetweenTemplateParameterLists::A::B::C89 template<typename BB> void i(BB x) { BB bb; }
90 };
91
92 struct CT : BaseT {
fSearchClassBetweenTemplateParameterLists::A::B::CT93 template<typename> void f(T x) { // expected-error {{void}}
94 T t; // expected-error {{incomplete}}
95 }
gSearchClassBetweenTemplateParameterLists::A::B::CT96 template<typename> void g(U x) { U u; }
hSearchClassBetweenTemplateParameterLists::A::B::CT97 template<typename AA> void h(AA x) { AA aa; }
iSearchClassBetweenTemplateParameterLists::A::B::CT98 template<typename BB> void i(BB x) { BB bb; }
99 };
100
101 struct CU : BaseU {
fSearchClassBetweenTemplateParameterLists::A::B::CU102 template<typename> void f(T x) { T t; }
gSearchClassBetweenTemplateParameterLists::A::B::CU103 template<typename> void g(U x) { // expected-error {{void}}
104 U u; // expected-error {{incomplete}}
105 }
hSearchClassBetweenTemplateParameterLists::A::B::CU106 template<typename AA> void h(AA x) { AA aa; }
iSearchClassBetweenTemplateParameterLists::A::B::CU107 template<typename BB> void i(BB x) { BB bb; }
108 };
109 };
110 };
111
112 // Search order for the below is:
113 // 1) template parameter scope of the function itself (if any)
114 // 2) class of which function is a member
115 // 3) template parameter scope of inner class
116 // 4) class of which class is a member
117 // 5) template parameter scope of outer class
118
119 // OK, 'AA' found in (3)
120 template<typename T> template<typename AA>
f(AA)121 void A<T>::B<AA>::f(AA) {
122 AA aa;
123 }
124
125 // error, 'BB' found in (2)
126 template<typename T> template<typename BB>
g(BB)127 void A<T>::B<BB>::g(BB) { // expected-error {{does not match}}
128 BB bb; // expected-error {{incomplete type}}
129 }
130
131 // error, 'AA' found in (4)
132 template<typename AA> template<typename U>
h(AA)133 void A<AA>::B<U>::h(AA) { // expected-error {{does not match}}
134 AA aa; // expected-error {{incomplete type}}
135 }
136
137 // error, 'BB' found in (2)
138 template<typename BB> template<typename U>
i(BB)139 void A<BB>::B<U>::i(BB) { // expected-error {{does not match}}
140 BB bb; // expected-error {{incomplete type}}
141 }
142
143 // OK, 'BB' found in (1)
144 template<typename T> template<typename U> template<typename BB>
j(BB)145 void A<T>::B<U>::j(BB) {
146 BB bb;
147 }
148
149 // error, 'BB' found in (2)
150 template<typename T> template<typename BB> template<typename V>
k(V)151 void A<T>::B<BB>::k(V) { // expected-error {{does not match}}
152 BB bb; // expected-error {{incomplete type}}
153 }
154 }
155