brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.1 KiB · 7562e64 Raw
345 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s2 3// Attempt to test each rule for forming associated namespaces4// and classes as described in [basic.lookup.argdep]p2.5 6// fundamental type: no associated namespace and no associated class7namespace adl_fundamental_type {8  constexpr int g(char) { return 1; } // #19  template <typename T> constexpr int foo(T t) { return g(t); }10  constexpr int g(int) { return 2; } // #2 not found11  void test() {12    static_assert(foo(0) == 1); // ok, #113  }14}15 16// class type:17//   associated classes: itself, the class of which it is a member (if any),18//                       direct and indirect base classes19//   associated namespaces: innermost enclosing namespaces of associated classes20namespace adl_class_type {21  // associated class: itself, simple case22  namespace X1 {23    namespace N {24      struct S {};25      void f(S); // found26    }27    void g(N::S); // not found28  };29  void test1() {30    f(X1::N::S{}); // ok31    g(X1::N::S{}); // expected-error {{use of undeclared identifier}}32  }33 34  // associated class: itself, local type35  namespace X2 {36    auto foo() {37      struct S {} s;38      return s;39    }40    using S = decltype(foo());41    void f(S); // #142  }43  void test2() {44    f(X2::S{}); // This is well-formed; X2 is the innermost enclosing namespace45                // of the local struct S. Calls #1.46  }47 48  // associated class: the parent class49  namespace X3 {50    struct S {51      struct T {};52      friend void f(T);53    };54  }55  void test3() {56    f(X3::S::T{}); // ok57  }58 59  // associated class: direct and indirect base classes60  namespace X4 {61    namespace IndirectBaseNamespace {62      struct IndirectBase {};63      void f(IndirectBase); // #164    }65    namespace DirectBaseNamespace {66      struct DirectBase : IndirectBaseNamespace::IndirectBase {};67      void g(DirectBase); // #268    }69    struct S : DirectBaseNamespace::DirectBase {};70  }71  void test4() {72    f(X4::S{}); // ok, #173    g(X4::S{}); // ok, #274  }75 76  // associated class: itself, lambda77  namespace X5 {78    namespace N {79      auto get_lambda() { return [](){}; }80      void f(decltype(get_lambda()));81    }82 83    void test5() {84      auto lambda = N::get_lambda();85      f(lambda); // ok86    }87  }88 89  // The parameter types and return type of a lambda's operator() do not90  // 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; }95    }96 97    constexpr int f(N::A (*)()) { return 2; }98    constexpr int f(void (*)(N::A)) { return 3; }99 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_type109 110// class template specialization: as for class type plus111//   for non-type template arguments:112//    - nothing113//   for type template arguments:114//    - associated namespaces and classes of the type template arguments115//   for template template arguments:116//    - namespaces of which template template arguments are member of117//    - classes of which member template used as template template arguments118//      are member of119namespace adl_class_template_specialization_type {120  // non-type template argument121  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>); // #1127    }128    namespace BaseNamespace {129      template <N::S *p> void X1_g(C<p>); // #2130    }131    template <N::S *p> void X1_h(C<p>); // #3132  }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 namespaces137             // 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 argument145  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>); // #1151    }152    namespace BaseNamespace {153      template <typename T> void X2_g(C<T>); // #2154    }155    template <typename T> void X2_h(C<T>); // #2156  }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 argument165  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>); // #1170    }171    struct M {172      template <typename T> struct Z {};173      friend void X3_g(C<Z>); // #2174    };175  }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, #1180    X3_g(c2); // ok, struct M is added, #2181  }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.187namespace 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    };195    auto foo() {196      enum G {} g;197      return g;198    }199    using G = decltype(foo());200    void h(G);201  }202 203  void test() {204    N::E e;205    f(e); // ok206    N::S::F f;207    g(f); // ok208    N::G g;209    h(g); // ok210 211  }212}213 214// pointer and reference type:215//  associated namespaces and classes of the pointee type216// array type:217//  associated namespaces and classes of the base type218namespace adl_point_array_reference_type {219  namespace N {220    struct S {};221    void f(S *);222    void f(S &);223  }224 225  void test() {226    N::S *p;227    f(p); // ok228    extern N::S &r;229    f(r); // ok230    N::S a[2];231    f(a); // ok232  }233}234 235// function type:236//  associated namespaces and classes of the function parameter types237//  and the return type.238namespace 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 249  void test() {250    extern N::S x(M::T);251    f(x); // ok252    g(x); // ok253  }254}255 256// pointer to member function:257//  associated namespaces and classes of the class, parameter types258//  and return type.259namespace 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 275  void test() {276    N::S (M::C::*p)(L::T);277    f(p); // ok278    g(p); // ok279    h(p); // ok280  }281}282 283// pointer to member:284//  associated namespaces and classes of the class and of the member type.285namespace 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 296  void test() {297    N::S (M::C::*p);298    f(p); // ok299    g(p); // ok300  }301}302 303// [...] if the argument is the name or address of a set of overloaded304// functions and/or function templates, its associated classes and namespaces305// 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 and307// return type.308//309// Additionally, if the aforementioned set of overloaded functions is named310// with a template-id, its associated classes and namespaces also include311// 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.314namespace 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;320  }321 322  constexpr int g1() { return 1; }323  constexpr int g1(N::S) { return 2; }324 325  template <typename T> constexpr int g2() { return 3; }326 327  // Inspired from CWG 997.328  constexpr int g3() { return 4; }329  template <typename T> constexpr int g3(T, N::Q<T>) { return 5; }330 331  void test() {332    static_assert(f(g1) == 1, "");        // Well-formed from the union rule above333    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 the337    // template-id rule. Currently only GCC implements it. Implementing338    // it would weaken the argument to remove it in the future since339    // 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