[Arm] Fix generating code with UB in NeonEmitter (#121802)
[llvm-project.git] / clang / test / CXX / basic / basic.lookup / basic.lookup.argdep / p2-associated-namespaces-classes.cpp
blob7562e64b17a9b06a302141b0993102f5dfd75bea
1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
3 // Attempt to test each rule for forming associated namespaces
4 // and classes as described in [basic.lookup.argdep]p2.
6 // fundamental type: no associated namespace and no associated class
7 namespace adl_fundamental_type {
8 constexpr int g(char) { return 1; } // #1
9 template <typename T> constexpr int foo(T t) { return g(t); }
10 constexpr int g(int) { return 2; } // #2 not found
11 void test() {
12 static_assert(foo(0) == 1); // ok, #1
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
27 void g(N::S); // not found
29 void test1() {
30 f(X1::N::S{}); // ok
31 g(X1::N::S{}); // expected-error {{use of undeclared identifier}}
34 // associated class: itself, local type
35 namespace X2 {
36 auto foo() {
37 struct S {} s;
38 return s;
40 using S = decltype(foo());
41 void f(S); // #1
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.
48 // associated class: the parent class
49 namespace X3 {
50 struct S {
51 struct T {};
52 friend void f(T);
55 void test3() {
56 f(X3::S::T{}); // ok
59 // associated class: direct and indirect base classes
60 namespace X4 {
61 namespace IndirectBaseNamespace {
62 struct IndirectBase {};
63 void f(IndirectBase); // #1
65 namespace DirectBaseNamespace {
66 struct DirectBase : IndirectBaseNamespace::IndirectBase {};
67 void g(DirectBase); // #2
69 struct S : DirectBaseNamespace::DirectBase {};
71 void test4() {
72 f(X4::S{}); // ok, #1
73 g(X4::S{}); // ok, #2
76 // associated class: itself, lambda
77 namespace X5 {
78 namespace N {
79 auto get_lambda() { return [](){}; }
80 void f(decltype(get_lambda()));
83 void test5() {
84 auto lambda = N::get_lambda();
85 f(lambda); // ok
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 {};
94 template<class T> constexpr int f(T) { return 1; }
97 constexpr int f(N::A (*)()) { return 2; }
98 constexpr int f(void (*)(N::A)) { return 3; }
100 void test() {
101 constexpr auto lambda = []() -> N::A { return {}; };
102 static_assert(f(lambda) == 2);
104 constexpr auto lambda2 = [](N::A) {};
105 static_assert(f(lambda2) == 3);
108 } // namespace adl_class_type
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
128 namespace BaseNamespace {
129 template <N::S *p> void X1_g(C<p>); // #2
131 template <N::S *p> void X1_h(C<p>); // #3
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.
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
152 namespace BaseNamespace {
153 template <typename T> void X2_g(C<T>); // #2
155 template <typename T> void X2_h(C<T>); // #2
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.
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
171 struct M {
172 template <typename T> struct Z {};
173 friend void X3_g(C<Z>); // #2
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
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);
195 auto foo() {
196 enum G {} g;
197 return g;
199 using G = decltype(foo());
200 void h(G);
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
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 &);
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
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));
244 namespace M {
245 struct T {};
246 void g(N::S (*)(T));
249 void test() {
250 extern N::S x(M::T);
251 f(x); // ok
252 g(x); // ok
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));
266 namespace L {
267 struct T {};
268 void g(N::S (M::C::*)(L::T));
270 namespace M {
271 struct C {};
272 void h(N::S (M::C::*)(L::T));
275 void test() {
276 N::S (M::C::*p)(L::T);
277 f(p); // ok
278 g(p); // ok
279 h(p); // ok
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::*));
291 namespace M {
292 struct C {};
293 void g(N::S (M::C::*));
296 void test() {
297 N::S (M::C::*p);
298 f(p); // ok
299 g(p); // ok
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.
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.
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 {};
317 constexpr int f(int (*g)()) { return g(); }
318 // expected-note@-1 2{{'N::f' declared here}}
319 template <typename T> struct Q;
322 constexpr int g1() { return 1; }
323 constexpr int g1(N::S) { return 2; }
325 template <typename T> constexpr int g2() { return 3; }
327 // Inspired from CWG 997.
328 constexpr int g3() { return 4; }
329 template <typename T> constexpr int g3(T, N::Q<T>) { return 5; }
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}}
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.
341 static_assert(f(g3) == 4, ""); // FIXME: Also well-formed from the union rule.
342 // expected-error@-1 {{use of undeclared}}