p1.cpp revision 3d04336baf091b16e9d8f85b48b82dafd2695874
1// RUN: %clang_cc1 -fsyntax-only -verify %s 2 3// C++'0x [class.friend] p1: 4// A friend of a class is a function or class that is given permission to use 5// the private and protected member names from the class. A class specifies 6// its friends, if any, by way of friend declarations. Such declarations give 7// special access rights to the friends, but they do not make the nominated 8// friends members of the befriending class. 9// 10// FIXME: Add tests for access control when implemented. Currently we only test 11// for parsing. 12 13struct S { static void f(); }; 14S* g() { return 0; } 15 16struct X { 17 friend struct S; 18 friend S* g(); 19}; 20 21void test1() { 22 S s; 23 g()->f(); 24 S::f(); 25 X::g(); // expected-error{{no member named 'g' in 'X'}} 26 X::S x_s; // expected-error{{no member named 'S' in 'X'}} 27 X x; 28 x.g(); // expected-error{{no member named 'g' in 'X'}} 29} 30 31// Test that we recurse through namespaces to find already declared names, but 32// new names are declared within the enclosing namespace. 33namespace N { 34 struct X { 35 friend struct S; 36 friend S* g(); 37 38 friend struct S2; 39 friend struct S2* g2(); 40 }; 41 42 struct S2 { static void f2(); }; 43 S2* g2() { return 0; } 44 45 void test() { 46 g()->f(); 47 S s; 48 S::f(); 49 X::g(); // expected-error{{no member named 'g' in 'N::X'}} 50 X::S x_s; // expected-error{{no member named 'S' in 'N::X'}} 51 X x; 52 x.g(); // expected-error{{no member named 'g' in 'N::X'}} 53 54 g2(); 55 S2 s2; 56 ::g2(); // expected-error{{no member named 'g2' in the global namespace}} 57 ::S2 g_s2; // expected-error{{no member named 'S2' in the global namespace}} 58 X::g2(); // expected-error{{no member named 'g2' in 'N::X'}} 59 X::S2 x_s2; // expected-error{{no member named 'S2' in 'N::X'}} 60 x.g2(); // expected-error{{no member named 'g2' in 'N::X'}} 61 } 62} 63 64namespace test0 { 65 class ClassFriend { 66 void test(); 67 }; 68 69 class MemberFriend { 70 void test(); 71 }; 72 73 void declared_test(); 74 75 class Class { 76 static void member(); // expected-note 2 {{declared private here}} 77 78 friend class ClassFriend; 79 friend class UndeclaredClassFriend; 80 81 friend void undeclared_test(); 82 friend void declared_test(); 83 friend void MemberFriend::test(); 84 }; 85 86 void declared_test() { 87 Class::member(); 88 } 89 90 void undeclared_test() { 91 Class::member(); 92 } 93 94 void unfriended_test() { 95 Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}} 96 } 97 98 void ClassFriend::test() { 99 Class::member(); 100 } 101 102 void MemberFriend::test() { 103 Class::member(); 104 } 105 106 class UndeclaredClassFriend { 107 void test() { 108 Class::member(); 109 } 110 }; 111 112 class ClassNonFriend { 113 void test() { 114 Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}} 115 } 116 }; 117} 118 119// Make sure that friends have access to inherited protected members. 120namespace test2 { 121 struct X; 122 123 class ilist_half_node { 124 friend struct ilist_walker_bad; 125 X *Prev; 126 protected: 127 X *getPrev() { return Prev; } 128 }; 129 130 class ilist_node : private ilist_half_node { // expected-note {{declared private here}} expected-note {{constrained by private inheritance here}} 131 friend struct ilist_walker; 132 X *Next; 133 X *getNext() { return Next; } // expected-note {{declared private here}} 134 }; 135 136 struct X : ilist_node {}; 137 138 struct ilist_walker { 139 static X *getPrev(X *N) { return N->getPrev(); } 140 static X *getNext(X *N) { return N->getNext(); } 141 }; 142 143 struct ilist_walker_bad { 144 static X *getPrev(X *N) { return N->getPrev(); } // \ 145 // expected-error {{'getPrev' is a private member of 'test2::ilist_half_node'}} \ 146 // expected-error {{cannot cast 'test2::X' to its private base class 'test2::ilist_half_node'}} 147 148 static X *getNext(X *N) { return N->getNext(); } // \ 149 // expected-error {{'getNext' is a private member of 'test2::ilist_node'}} 150 }; 151} 152 153namespace test3 { 154 class A { protected: int x; }; // expected-note {{declared protected here}} 155 156 class B : public A { 157 friend int foo(B*); 158 }; 159 160 int foo(B *p) { 161 return p->x; 162 } 163 164 int foo(const B *p) { 165 return p->x; // expected-error {{'x' is a protected member of 'test3::A'}} 166 } 167} 168 169namespace test3a { 170 class A { protected: int x; }; 171 172 class B : public A { 173 friend int foo(B*); 174 }; 175 176 int foo(B * const p) { 177 return p->x; 178 } 179} 180 181namespace test4 { 182 template <class T> class Holder { 183 T object; 184 friend bool operator==(Holder &a, Holder &b) { 185 return a.object == b.object; // expected-error {{invalid operands to binary expression}} 186 } 187 }; 188 189 struct Inequal {}; 190 bool test() { 191 Holder<Inequal> a, b; 192 return a == b; // expected-note {{requested here}} 193 } 194} 195 196 197// PR6174 198namespace test5 { 199 namespace ns { 200 class A; 201 } 202 203 class ns::A { 204 private: int x; 205 friend class B; 206 }; 207 208 namespace ns { 209 class B { 210 int test(A *p) { return p->x; } 211 }; 212 } 213} 214 215// PR6207 216namespace test6 { 217 struct A {}; 218 219 struct B { 220 friend A::A(); 221 friend A::~A(); 222 friend A &A::operator=(const A&); 223 }; 224} 225