• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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