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