brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 7ed9a58 Raw
193 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only %s -verify2 3// C++'0x [namespace.memdef] p3:4//   Every name first declared in a namespace is a member of that namespace. If5//   a friend declaration in a non-local class first declares a class or6//   function the friend class or function is a member of the innermost7//   enclosing namespace.8 9namespace N {10  struct S0 {11    friend struct F0;12    friend void f0(int);13    struct F0 member_func();14  };15  struct F0 { };16  F0 f0() { return S0().member_func(); }17}18N::F0 f0_var = N::f0();19 20// Ensure we can handle attaching friend declarations to an enclosing namespace21// with multiple contexts.22namespace N { struct S1 { struct IS1; }; }23namespace N {24  struct S1::IS1 {25    friend struct F1;26    friend void f1(int);27    struct F1 member_func();28  };29  struct F1 { };30  F1 f1() { return S1::IS1().member_func(); }31}32N::F1 f1_var = N::f1();33 34//   The name of the friend is not found by unqualified lookup (3.4.1) or by35//   qualified lookup (3.4.3) until a matching declaration is provided in that36//   namespace scope (either before or after the class definition granting37//   friendship). If a friend function is called, its name may be found by the38//   name lookup that considers functions from namespaces and classes39//   associated with the types of the function arguments (3.4.2). If the name40//   in a friend declaration is neither qualified nor a template-id and the41//   declaration is a function or an elaborated-type-specifier, the lookup to42//   determine whether the entity has been previously declared shall not43//   consider any scopes outside the innermost enclosing namespace.44 45template<typename T> struct X0 { };46struct X1 { };47 48struct Y {49  template<typename T> union X0;50  template<typename T> friend union X0;51  52  union X1;53  friend union X1;54};55 56namespace N {57  namespace M {58    template<typename T> class X;59  }60}61 62namespace N3 {63  class Y {64    template<typename T> friend class N::M::X;65  };66}67 68// FIXME: Woefully inadequate for testing69 70// Friends declared as template-ids aren't subject to the restriction71// on innermost namespaces.72namespace test5 {73  template <class T> void f(T);  74  namespace ns {75    class A {76      friend void f<int>(int);77      static void foo(); // expected-note 2 {{declared private here}}78    };79 80    // Note that this happens without instantiation.81    template <class T> void f(T) {82      A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}}83    }84  }85 86  template <class T> void f(T) {87    ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}}88  }89 90  template void f<int>(int);91  template void f<long>(long); //expected-note {{instantiation}}92}93 94namespace test6 {95  class A;96  namespace ns {97    class B {98      static void foo(); // expected-note {{implicitly declared private here}}99      friend union A;100    };101 102    union A {103      void test() {104        B::foo();105      }106    };107  }108 109  class A {110    void test() {111      ns::B::foo(); // expected-error {{'foo' is a private member of 'test6::ns::B'}}112    }113  };114}115 116// We seem to be following a correct interpretation with these, but117// the standard could probably be a bit clearer.118namespace test7a {119  namespace ns {120    class A;121  }122 123  using namespace ns;124  class B {125    static void foo();126    friend class A;127  };128 129  class ns::A {130    void test() {131      B::foo();132    }133  };134}135namespace test7b {136  namespace ns {137    class A;138  }139 140  using ns::A;141  class B {142    static void foo();143    friend class A;144  };145 146  class ns::A {147    void test() {148      B::foo();149    }150  };151}152namespace test7c {153  namespace ns1 {154    class A;155  }156 157  namespace ns2 {158    // ns1::A appears as if declared in test7c according to [namespace.udir]p2.159    // I think that means we aren't supposed to find it.160    using namespace ns1;161    class B {162      static void foo(); // expected-note {{implicitly declared private here}}163      friend class A;164    };165  }166 167  class ns1::A {168    void test() {169      ns2::B::foo(); // expected-error {{'foo' is a private member of 'test7c::ns2::B'}}170    }171  };172}173namespace test7d {174  namespace ns1 {175    class A;176  }177 178  namespace ns2 {179    // Honor the lexical context of a using-declaration, though.180    using ns1::A;181    class B {182      static void foo();183      friend class A;184    };185  }186 187  class ns1::A {188    void test() {189      ns2::B::foo();190    }191  };192}193