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