// RUN: %clang_cc1 -fsyntax-only -verify %s namespace N { enum { C }; template class B { void f(T); }; } template void N::B::f(C) { C b; } namespace N { enum { D }; namespace M { enum { C , D }; template class X { template void f(C, U); template void g(C, D) { C c; D d; } }; struct Y { template void f(U); }; } struct Y { template void f(D); }; } template template void N::M::X::f(C, D) { C c; D d; } template void N::M::Y::f(C) { C c; } template 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 struct A { using AA = void; template struct B { using BB = void; void f(U); void g(U); void h(T); void i(T); template void j(V); template void k(U); // OK: these find the template parameter not the member. template void l(AA x) { AA aa; } template void m(BB x) { BB bb; } struct C : Base { // All OK; these find the template parameters. template void f(T x) { T t; } template void g(U x) { U u; } template void h(AA x) { AA aa; } template void i(BB x) { BB bb; } }; struct CT : BaseT { template void f(T x) { // expected-error {{void}} T t; // expected-error {{incomplete}} } template void g(U x) { U u; } template void h(AA x) { AA aa; } template void i(BB x) { BB bb; } }; struct CU : BaseU { template void f(T x) { T t; } template void g(U x) { // expected-error {{void}} U u; // expected-error {{incomplete}} } template void h(AA x) { AA aa; } template 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 template void A::B::f(AA) { AA aa; } // error, 'BB' found in (2) template template void A::B::g(BB) { // expected-error {{does not match}} BB bb; // expected-error {{incomplete type}} } // error, 'AA' found in (4) template template void A::B::h(AA) { // expected-error {{does not match}} AA aa; // expected-error {{incomplete type}} } // error, 'BB' found in (2) template template void A::B::i(BB) { // expected-error {{does not match}} BB bb; // expected-error {{incomplete type}} } // OK, 'BB' found in (1) template template template void A::B::j(BB) { BB bb; } // error, 'BB' found in (2) template template template void A::B::k(V) { // expected-error {{does not match}} BB bb; // expected-error {{incomplete type}} } }