155 lines
3.7 KiB
C++
155 lines
3.7 KiB
C++
// 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}}
|
|
}
|
|
}
|