1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s 2 3 // Attempt to test each rule for forming associated namespaces 4 // and classes as described in [basic.lookup.argdep]p2. 5 6 // fundamental type: no associated namespace and no associated class 7 namespace adl_fundamental_type { g(char)8 constexpr int g(char) { return 1; } // #1 foo(T t)9 template <typename T> constexpr int foo(T t) { return g(t); } g(int)10 constexpr int g(int) { return 2; } // #2 not found test()11 void test() { 12 static_assert(foo(0) == 1); // ok, #1 13 } 14 } 15 16 // class type: 17 // associated classes: itself, the class of which it is a member (if any), 18 // direct and indirect base classes 19 // associated namespaces: innermost enclosing namespaces of associated classes 20 namespace adl_class_type { 21 // associated class: itself, simple case 22 namespace X1 { 23 namespace N { 24 struct S {}; 25 void f(S); // found 26 } 27 void g(N::S); // not found 28 }; test1()29 void test1() { 30 f(X1::N::S{}); // ok 31 g(X1::N::S{}); // expected-error {{use of undeclared identifier}} 32 } 33 34 // associated class: itself, local type 35 namespace X2 { foo()36 auto foo() { 37 struct S {} s; 38 return s; 39 } 40 using S = decltype(foo()); 41 void f(S); // #1 42 } test2()43 void test2() { 44 f(X2::S{}); // This is well-formed; X2 is the innermost enclosing namespace 45 // of the local struct S. Calls #1. 46 } 47 48 // associated class: the parent class 49 namespace X3 { 50 struct S { 51 struct T {}; 52 friend void f(T); 53 }; 54 } test3()55 void test3() { 56 f(X3::S::T{}); // ok 57 } 58 59 // associated class: direct and indirect base classes 60 namespace X4 { 61 namespace IndirectBaseNamespace { 62 struct IndirectBase {}; 63 void f(IndirectBase); // #1 64 } 65 namespace DirectBaseNamespace { 66 struct DirectBase : IndirectBaseNamespace::IndirectBase {}; 67 void g(DirectBase); // #2 68 } 69 struct S : DirectBaseNamespace::DirectBase {}; 70 } test4()71 void test4() { 72 f(X4::S{}); // ok, #1 73 g(X4::S{}); // ok, #2 74 } 75 76 // associated class: itself, lambda 77 namespace X5 { 78 namespace N { get_lambda()79 auto get_lambda() { return [](){}; } 80 void f(decltype(get_lambda())); 81 } 82 test5()83 void test5() { 84 auto lambda = N::get_lambda(); 85 f(lambda); // ok 86 } 87 } 88 89 // The parameter types and return type of a lambda's operator() do not 90 // contribute to the associated namespaces and classes of the lambda itself. 91 namespace X6 { 92 namespace N { 93 struct A {}; f(T)94 template<class T> constexpr int f(T) { return 1; } 95 } 96 f(N::A (*)())97 constexpr int f(N::A (*)()) { return 2; } f(void (*)(N::A))98 constexpr int f(void (*)(N::A)) { return 3; } 99 test()100 void test() { 101 constexpr auto lambda = []() -> N::A { return {}; }; 102 static_assert(f(lambda) == 2); 103 104 constexpr auto lambda2 = [](N::A) {}; 105 static_assert(f(lambda2) == 3); 106 } 107 } 108 } // namespace adl_class_type 109 110 // class template specialization: as for class type plus 111 // for non-type template arguments: 112 // - nothing 113 // for type template arguments: 114 // - associated namespaces and classes of the type template arguments 115 // for template template arguments: 116 // - namespaces of which template template arguments are member of 117 // - classes of which member template used as template template arguments 118 // are member of 119 namespace adl_class_template_specialization_type { 120 // non-type template argument 121 namespace X1 { 122 namespace BaseNamespace { struct Base {}; } 123 namespace N { struct S : BaseNamespace::Base {}; } 124 template <N::S *> struct C {}; 125 namespace N { 126 template <S *p> void X1_f(C<p>); // #1 127 } 128 namespace BaseNamespace { 129 template <N::S *p> void X1_g(C<p>); // #2 130 } 131 template <N::S *p> void X1_h(C<p>); // #3 132 } test1()133 void test1() { 134 constexpr X1::N::S *p = nullptr; 135 X1::C<p> c; 136 X1_f(c); // N is not added to the set of associated namespaces 137 // and #1 is not found... 138 // expected-error@-2 {{use of undeclared identifier}} 139 X1_g(c); // ... nor is #2 ... 140 // expected-error@-1 {{use of undeclared identifier}} 141 X1_h(c); // ... but the namespace X1 is added and #3 is found. 142 } 143 144 // type template argument 145 namespace X2 { 146 template <typename T> struct C {}; 147 namespace BaseNamespace { struct Base {}; } 148 namespace N { struct S : BaseNamespace::Base {}; } 149 namespace N { 150 template <typename T> void X2_f(C<T>); // #1 151 } 152 namespace BaseNamespace { 153 template <typename T> void X2_g(C<T>); // #2 154 } 155 template <typename T> void X2_h(C<T>); // #2 156 } test2()157 void test2() { 158 X2::C<X2::N::S> c; 159 X2_f(c); // N is added to the set of associated namespaces and #1 is found. 160 X2_g(c); // Similarly BaseNamespace is added and #2 is found. 161 X2_h(c); // As before, X2 is also added and #3 is found. 162 } 163 164 // template template argument 165 namespace X3 { 166 template <template <typename> class TT> struct C {}; 167 namespace N { 168 template <typename T> struct Z {}; 169 void X3_f(C<Z>); // #1 170 } 171 struct M { 172 template <typename T> struct Z {}; 173 friend void X3_g(C<Z>); // #2 174 }; 175 } test3()176 void test3() { 177 X3::C<X3::N::Z> c1; 178 X3::C<X3::M::Z> c2; 179 X3_f(c1); // ok, namespace N is added, #1 180 X3_g(c2); // ok, struct M is added, #2 181 } 182 } 183 184 // enumeration type: 185 // associated namespace: innermost enclosing namespace of its declaration. 186 // associated class: if the enumeration is a class member, the member's class. 187 namespace adl_enumeration_type { 188 namespace N { 189 enum E : int; 190 void f(E); 191 struct S { 192 enum F : int; 193 friend void g(F); 194 }; foo()195 auto foo() { 196 enum G {} g; 197 return g; 198 } 199 using G = decltype(foo()); 200 void h(G); 201 } 202 test()203 void test() { 204 N::E e; 205 f(e); // ok 206 N::S::F f; 207 g(f); // ok 208 N::G g; 209 h(g); // ok 210 211 } 212 } 213 214 // pointer and reference type: 215 // associated namespaces and classes of the pointee type 216 // array type: 217 // associated namespaces and classes of the base type 218 namespace adl_point_array_reference_type { 219 namespace N { 220 struct S {}; 221 void f(S *); 222 void f(S &); 223 } 224 test()225 void test() { 226 N::S *p; 227 f(p); // ok 228 extern N::S &r; 229 f(r); // ok 230 N::S a[2]; 231 f(a); // ok 232 } 233 } 234 235 // function type: 236 // associated namespaces and classes of the function parameter types 237 // and the return type. 238 namespace adl_function_type { 239 namespace M { struct T; } 240 namespace N { 241 struct S {}; 242 void f(S (*)(M::T)); 243 }; 244 namespace M { 245 struct T {}; 246 void g(N::S (*)(T)); 247 } 248 test()249 void test() { 250 extern N::S x(M::T); 251 f(x); // ok 252 g(x); // ok 253 } 254 } 255 256 // pointer to member function: 257 // associated namespaces and classes of the class, parameter types 258 // and return type. 259 namespace adl_pointer_to_member_function { 260 namespace M { struct C; } 261 namespace L { struct T; } 262 namespace N { 263 struct S {}; 264 void f(N::S (M::C::*)(L::T)); 265 } 266 namespace L { 267 struct T {}; 268 void g(N::S (M::C::*)(L::T)); 269 } 270 namespace M { 271 struct C {}; 272 void h(N::S (M::C::*)(L::T)); 273 } 274 test()275 void test() { 276 N::S (M::C::*p)(L::T); 277 f(p); // ok 278 g(p); // ok 279 h(p); // ok 280 } 281 } 282 283 // pointer to member: 284 // associated namespaces and classes of the class and of the member type. 285 namespace adl_pointer_to_member { 286 namespace M { struct C; } 287 namespace N { 288 struct S {}; 289 void f(N::S (M::C::*)); 290 } 291 namespace M { 292 struct C {}; 293 void g(N::S (M::C::*)); 294 } 295 test()296 void test() { 297 N::S (M::C::*p); 298 f(p); // ok 299 g(p); // ok 300 } 301 } 302 303 // [...] if the argument is the name or address of a set of overloaded 304 // functions and/or function templates, its associated classes and namespaces 305 // are the union of those associated with each of the members of the set, 306 // i.e., the classes and namespaces associated with its parameter types and 307 // return type. 308 // 309 // Additionally, if the aforementioned set of overloaded functions is named 310 // with a template-id, its associated classes and namespaces also include 311 // those of its type template-arguments and its template template-arguments. 312 // 313 // CWG 33 for the union rule. CWG 997 for the template-id rule. 314 namespace adl_overload_set { 315 namespace N { 316 struct S {}; f(int (* g)())317 constexpr int f(int (*g)()) { return g(); } 318 // expected-note@-1 2{{'N::f' declared here}} 319 template <typename T> struct Q; 320 } 321 g1()322 constexpr int g1() { return 1; } g1(N::S)323 constexpr int g1(N::S) { return 2; } 324 g2()325 template <typename T> constexpr int g2() { return 3; } 326 327 // Inspired from CWG 997. g3()328 constexpr int g3() { return 4; } g3(T,N::Q<T>)329 template <typename T> constexpr int g3(T, N::Q<T>) { return 5; } 330 test()331 void test() { 332 static_assert(f(g1) == 1, ""); // Well-formed from the union rule above 333 static_assert(f(g2<N::S>) == 3, ""); // FIXME: Well-formed from the template-id rule above. 334 // expected-error@-1 {{use of undeclared}} 335 336 // A objection was raised during review against implementing the 337 // template-id rule. Currently only GCC implements it. Implementing 338 // it would weaken the argument to remove it in the future since 339 // actual real code might start to depend on it. 340 341 static_assert(f(g3) == 4, ""); // FIXME: Also well-formed from the union rule. 342 // expected-error@-1 {{use of undeclared}} 343 } 344 } 345