| // RUN: %clang_cc1 -fsyntax-only -verify %s |
| |
| // C++98 [class.friend]p7: |
| // C++11 [class.friend]p9: |
| // A name nominated by a friend declaration shall be accessible in |
| // the scope of the class containing the friend declaration. |
| |
| // PR12328 |
| // Simple, non-templated case. |
| namespace test0 { |
| class X { |
| void f(); // expected-note {{implicitly declared private here}} |
| }; |
| |
| class Y { |
| friend void X::f(); // expected-error {{friend function 'f' is a private member of 'test0::X'}} |
| }; |
| } |
| |
| // Templated but non-dependent. |
| namespace test1 { |
| class X { |
| void f(); // expected-note {{implicitly declared private here}} |
| }; |
| |
| template <class T> class Y { |
| friend void X::f(); // expected-error {{friend function 'f' is a private member of 'test1::X'}} |
| }; |
| } |
| |
| // Dependent but instantiated at the right type. |
| namespace test2 { |
| template <class T> class Y; |
| |
| class X { |
| void f(); |
| friend class Y<int>; |
| }; |
| |
| template <class T> class Y { |
| friend void X::f(); |
| }; |
| |
| template class Y<int>; |
| } |
| |
| // Dependent and instantiated at the wrong type. |
| namespace test3 { |
| template <class T> class Y; |
| |
| class X { |
| void f(); // expected-note {{implicitly declared private here}} |
| friend class Y<int>; |
| }; |
| |
| template <class T> class Y { |
| friend void X::f(); // expected-error {{friend function 'f' is a private member of 'test3::X'}} |
| }; |
| |
| template class Y<float>; // expected-note {{in instantiation}} |
| } |
| |
| // Dependent because dependently-scoped. |
| namespace test4 { |
| template <class T> class X { |
| void f(); |
| }; |
| |
| template <class T> class Y { |
| friend void X<T>::f(); |
| }; |
| } |
| |
| // Dependently-scoped, no friends. |
| namespace test5 { |
| template <class T> class X { |
| void f(); // expected-note {{implicitly declared private here}} |
| }; |
| |
| template <class T> class Y { |
| friend void X<T>::f(); // expected-error {{friend function 'f' is a private member of 'test5::X<int>'}} |
| }; |
| |
| template class Y<int>; // expected-note {{in instantiation}} |
| } |
| |
| // Dependently-scoped, wrong friend. |
| namespace test6 { |
| template <class T> class Y; |
| |
| template <class T> class X { |
| void f(); // expected-note {{implicitly declared private here}} |
| friend class Y<float>; |
| }; |
| |
| template <class T> class Y { |
| friend void X<T>::f(); // expected-error {{friend function 'f' is a private member of 'test6::X<int>'}} |
| }; |
| |
| template class Y<int>; // expected-note {{in instantiation}} |
| } |
| |
| // Dependently-scoped, right friend. |
| namespace test7 { |
| template <class T> class Y; |
| |
| template <class T> class X { |
| void f(); |
| friend class Y<int>; |
| }; |
| |
| template <class T> class Y { |
| friend void X<T>::f(); |
| }; |
| |
| template class Y<int>; |
| } |