Index: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp =================================================================== --- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp +++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp @@ -0,0 +1,336 @@ +// 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); // expected-note {{'X2::f' declared here}} + } + void test2() { + f(X2::S{}); // FIXME: This is well-formed; X2 is the innermost enclosing namespace + // of the local struct S. + // expected-error@-2 {{use of undeclared identifier 'f'}} + } + + // 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); // FIXME: This is well-formed. expected-error {{use of undeclared}} + } + } + + // 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