410 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s2// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s3// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s4// RUN: %clang_cc1 -fsyntax-only -verify %s5 6// C++'0x [class.friend] p1:7// A friend of a class is a function or class that is given permission to use8// the private and protected member names from the class. A class specifies9// its friends, if any, by way of friend declarations. Such declarations give10// special access rights to the friends, but they do not make the nominated11// friends members of the befriending class.12 13struct S { static void f(); }; // expected-note 2 {{'S' declared here}}14S* g() { return 0; } // expected-note 2 {{'g' declared here}}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'; did you mean simply 'g'?}}26 X::S x_s; // expected-error{{no type named 'S' in 'X'; did you mean simply 'S'?}}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, but32// 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(); }; // expected-note 2 {{'S2' declared here}}43 S2* g2() { return 0; } // expected-note 2 {{'g2' declared here}}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'; did you mean simply 'g'?}}50 X::S x_s; // expected-error{{no type named 'S' in 'N::X'; did you mean simply 'S'?}}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; did you mean simply 'g2'?}}57 ::S2 g_s2; // expected-error{{no type named 'S2' in the global namespace; did you mean simply 'S2'?}}58 X::g2(); // expected-error{{no member named 'g2' in 'N::X'; did you mean simply 'g2'?}}59 X::S2 x_s2; // expected-error{{no type named 'S2' in 'N::X'; did you mean simply 'S2'?}}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 public:71 void test();72 };73 74 void declared_test();75 76 class Class {77 static void member(); // expected-note 2 {{declared private here}}78 79 friend class ClassFriend;80 friend class UndeclaredClassFriend;81 82 friend void undeclared_test();83 friend void declared_test();84 friend void MemberFriend::test();85 };86 87 void declared_test() {88 Class::member();89 }90 91 void undeclared_test() {92 Class::member();93 }94 95 void unfriended_test() {96 Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}}97 }98 99 void ClassFriend::test() {100 Class::member();101 }102 103 void MemberFriend::test() {104 Class::member();105 }106 107 class UndeclaredClassFriend {108 void test() {109 Class::member();110 }111 };112 113 class ClassNonFriend {114 void test() {115 Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}}116 }117 };118}119 120// Make sure that friends have access to inherited protected members.121namespace test2 {122 struct X;123 124 class ilist_half_node {125 friend struct ilist_walker_bad;126 X *Prev;127 protected:128 X *getPrev() { return Prev; } // expected-note{{member is declared here}}129 };130 131 class ilist_node : private ilist_half_node { // expected-note {{constrained by private inheritance here}}132 friend struct ilist_walker;133 X *Next;134 X *getNext() { return Next; } // expected-note {{declared private here}}135 };136 137 struct X : ilist_node {};138 139 struct ilist_walker {140 static X *getPrev(X *N) { return N->getPrev(); }141 static X *getNext(X *N) { return N->getNext(); }142 }; 143 144 struct ilist_walker_bad {145 static X *getPrev(X *N) { return N->getPrev(); } // \146 // expected-error {{'getPrev' is a private member of '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// PR6174198namespace 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// PR6207216namespace test6 {217 struct A {};218 219 struct B {220 friend221#if __cplusplus >= 201103L222 constexpr223#endif224 A::A()225#if __cplusplus >= 201703L226 noexcept227#endif228 ;229 friend A::~A();230 friend231#if __cplusplus >= 201402L232 constexpr233#endif234 A &A::operator=(const A&)235#if __cplusplus >= 201703L236 noexcept237#endif238 ;239 };240}241 242namespace test7 {243 template <class T> struct X {244 X();245 ~X();246 void foo();247 void bar();248 };249 250 class A {251 friend void X<int>::foo();252 friend X<int>::X();253 friend254#if __cplusplus >= 201103L255 constexpr256#endif257 X<int>::X(const X&)258#if __cplusplus >= 201703L259 noexcept260#endif261 ;262 263 private:264 A(); // expected-note 2 {{declared private here}}265 };266 267 template<> void X<int>::foo() {268 A a;269 }270 271 template<> void X<int>::bar() {272 A a; // expected-error {{calling a private constructor}}273 }274 275 template<> X<int>::X() {276 A a;277 }278 279 template<> X<int>::~X() {280 A a; // expected-error {{calling a private constructor}}281 }282}283 284// Return types, parameters and default arguments to friend functions.285namespace test8 {286 class A {287 typedef int I; // expected-note 6 {{declared private here}}288 static const I x = 0; // expected-note {{implicitly declared private here}}289 friend I f(I i);290 template<typename T> friend I g(I i);291 };292 293 const A::I A::x;294 A::I f(A::I i = A::x) {}295 template<typename T> A::I g(A::I i) {296 T t;297 }298 template A::I g<A::I>(A::I i);299 300 A::I f2(A::I i = A::x) {} // expected-error 3 {{is a private member of}}301 template<typename T> A::I g2(A::I i) { // expected-error 2 {{is a private member of}}302 T t;303 }304 template <> A::I g2<char>(A::I i) { return 0; } // OK305 template A::I g2<A::I>(A::I i); // OK306 template <> A::I g2<char>(A::I i); // OK307 template <> A::I g2<A::I *>(A::I i); // OK308 template A::I g2<unsigned>(A::I i); // OK309 template int g2<A::I **>(int i); // OK310 template A::I g2<A::I ***>(A::I i); // OK311 312 template <typename T> A::I g3(A::I i) { return 0; } // expected-error 2 {{is a private member of}}313 template <> int g3<A::I>(int i); // OK314}315 316// PR6885317namespace test9 {318 class B {319 friend class test9;320 };321}322 323// PR7230324namespace test10 {325 extern "C" void test10_f(void);326 extern "C" void test10_g(void);327 328 namespace NS {329 class C {330 void foo(void); // expected-note {{declared private here}}331 friend void test10::test10_f(void);332 };333 static C* bar;334 }335 336 void test10_f(void) {337 NS::bar->foo();338 }339 340 void test10_g(void) {341 NS::bar->foo(); // expected-error {{private member}}342 }343}344 345// PR8705346namespace test11 {347 class A {348 public:349 void test0(int);350 void test1(int);351 void test2(int);352 void test3(int);353 };354 355 class B {356 typedef int private_type; // expected-note 2 {{implicitly declared private here}}357 friend void A::test0(int);358 friend void A::test1(int);359 };360 361 void A::test0(B::private_type x) {}362 void A::test1(int x = B::private_type()) {}363 void A::test2(B::private_type x) {} // expected-error {{'private_type' is a private member of 'test11::B'}}364 void A::test3(int x = B::private_type()) {} // expected-error {{'private_type' is a private member of 'test11::B'}}365}366 367 368// PR9221369namespace test12 {370 struct A {371 void foo();372 };373 class B : private A {374 friend void A::foo();375 void *mem;376 };377 void A::foo() {378 void *var = static_cast<B*>(this)->mem;379 }380}381 382namespace PR9103 {383 struct base {384 protected:385 static void foo(void) {}386 };387 388 struct cls: base {389 friend void bar(void) {390 base::foo();391 }392 };393}394 395// PR13642. When computing the effective context, we were walking up396// the DC chain for the canonical decl, which is unfortunate if that's397// (e.g.) a friend declaration.398namespace test14 {399 class A {400 class B { // expected-note {{implicitly declared private here}}401 static int i;402 friend void c();403 };404 };405 406 void c() {407 A::B::i = 5; // expected-error {{'B' is a private member of 'test14::A'}}408 }409}410