// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s // Attempt to test each rule for forming associated namespaces // and classes as described in [basic.lookup.argdep]p2. // fundamental type: no associated namespace and no associated class namespace adl_fundamental_type { constexpr int g(char) { return 1; } // #1 template constexpr int foo(T t) { return g(t); } constexpr int g(int) { return 2; } // #2 not found void test() { static_assert(foo(0) == 1); // ok, #1 } } // class type: // associated classes: itself, the class of which it is a member (if any), // direct and indirect base classes // associated namespaces: innermost enclosing namespaces of associated classes namespace adl_class_type { // associated class: itself, simple case namespace X1 { namespace N { struct S {}; void f(S); // found } void g(N::S); // not found }; void test1() { f(X1::N::S{}); // ok g(X1::N::S{}); // expected-error {{use of undeclared identifier}} } // associated class: itself, local type namespace X2 { auto foo() { struct S {} s; return s; } using S = decltype(foo()); void f(S); // #1 } void test2() { f(X2::S{}); // This is well-formed; X2 is the innermost enclosing namespace // of the local struct S. Calls #1. } // associated class: the parent class namespace X3 { struct S { struct T {}; friend void f(T); }; } void test3() { f(X3::S::T{}); // ok } // associated class: direct and indirect base classes namespace X4 { namespace IndirectBaseNamespace { struct IndirectBase {}; void f(IndirectBase); // #1 } namespace DirectBaseNamespace { struct DirectBase : IndirectBaseNamespace::IndirectBase {}; void g(DirectBase); // #2 } struct S : DirectBaseNamespace::DirectBase {}; } void test4() { f(X4::S{}); // ok, #1 g(X4::S{}); // ok, #2 } // associated class: itself, lambda namespace X5 { namespace N { auto get_lambda() { return [](){}; } void f(decltype(get_lambda())); } void test5() { auto lambda = N::get_lambda(); f(lambda); // ok } } // The parameter types and return type of a lambda's operator() do not // contribute to the associated namespaces and classes of the lambda itself. namespace X6 { namespace N { struct A {}; template constexpr int f(T) { return 1; } } constexpr int f(N::A (*)()) { return 2; } constexpr int f(void (*)(N::A)) { return 3; } void test() { constexpr auto lambda = []() -> N::A { return {}; }; static_assert(f(lambda) == 2); constexpr auto lambda2 = [](N::A) {}; static_assert(f(lambda2) == 3); } } } // namespace adl_class_type // class template specialization: as for class type plus // for non-type template arguments: // - nothing // for type template arguments: // - associated namespaces and classes of the type template arguments // for template template arguments: // - namespaces of which template template arguments are member of // - classes of which member template used as template template arguments // are member of namespace adl_class_template_specialization_type { // non-type template argument namespace X1 { namespace BaseNamespace { struct Base {}; } namespace N { struct S : BaseNamespace::Base {}; } template struct C {}; namespace N { template void X1_f(C

); // #1 } namespace BaseNamespace { template void X1_g(C

); // #2 } template void X1_h(C

); // #3 } void test1() { constexpr X1::N::S *p = nullptr; X1::C

c; X1_f(c); // N is not added to the set of associated namespaces // and #1 is not found... // expected-error@-2 {{use of undeclared identifier}} X1_g(c); // ... nor is #2 ... // expected-error@-1 {{use of undeclared identifier}} X1_h(c); // ... but the namespace X1 is added and #3 is found. } // type template argument namespace X2 { template struct C {}; namespace BaseNamespace { struct Base {}; } namespace N { struct S : BaseNamespace::Base {}; } namespace N { template void X2_f(C); // #1 } namespace BaseNamespace { template void X2_g(C); // #2 } template void X2_h(C); // #2 } void test2() { X2::C c; X2_f(c); // N is added to the set of associated namespaces and #1 is found. X2_g(c); // Similarly BaseNamespace is added and #2 is found. X2_h(c); // As before, X2 is also added and #3 is found. } // template template argument namespace X3 { template