1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 
3 // C++98 [class.friend]p7:
4 // C++11 [class.friend]p9:
5 //   A name nominated by a friend declaration shall be accessible in
6 //   the scope of the class containing the friend declaration.
7 
8 // PR12328
9 // Simple, non-templated case.
10 namespace test0 {
11   class X {
12     void f(); // expected-note {{implicitly declared private here}}
13   };
14 
15   class Y {
16     friend void X::f(); // expected-error {{friend function 'f' is a private member of 'test0::X'}}
17   };
18 }
19 
20 // Templated but non-dependent.
21 namespace test1 {
22   class X {
23     void f(); // expected-note {{implicitly declared private here}}
24   };
25 
26   template <class T> class Y {
27     friend void X::f(); // expected-error {{friend function 'f' is a private member of 'test1::X'}}
28   };
29 }
30 
31 // Dependent but instantiated at the right type.
32 namespace test2 {
33   template <class T> class Y;
34 
35   class X {
36     void f();
37     friend class Y<int>;
38   };
39 
40   template <class T> class Y {
41     friend void X::f();
42   };
43 
44   template class Y<int>;
45 }
46 
47 // Dependent and instantiated at the wrong type.
48 namespace test3 {
49   template <class T> class Y;
50 
51   class X {
52     void f(); // expected-note {{implicitly declared private here}}
53     friend class Y<int>;
54   };
55 
56   template <class T> class Y {
57     friend void X::f(); // expected-error {{friend function 'f' is a private member of 'test3::X'}}
58   };
59 
60   template class Y<float>; // expected-note {{in instantiation}}
61 }
62 
63 // Dependent because dependently-scoped.
64 namespace test4 {
65   template <class T> class X {
66     void f();
67   };
68 
69   template <class T> class Y {
70     friend void X<T>::f();
71   };
72 }
73 
74 // Dependently-scoped, no friends.
75 namespace test5 {
76   template <class T> class X {
77     void f(); // expected-note {{implicitly declared private here}}
78   };
79 
80   template <class T> class Y {
81     friend void X<T>::f(); // expected-error {{friend function 'f' is a private member of 'test5::X<int>'}}
82   };
83 
84   template class Y<int>; // expected-note {{in instantiation}}
85 }
86 
87 // Dependently-scoped, wrong friend.
88 namespace test6 {
89   template <class T> class Y;
90 
91   template <class T> class X {
92     void f(); // expected-note {{implicitly declared private here}}
93     friend class Y<float>;
94   };
95 
96   template <class T> class Y {
97     friend void X<T>::f(); // expected-error {{friend function 'f' is a private member of 'test6::X<int>'}}
98   };
99 
100   template class Y<int>; // expected-note {{in instantiation}}
101 }
102 
103 // Dependently-scoped, right friend.
104 namespace test7 {
105   template <class T> class Y;
106 
107   template <class T> class X {
108     void f();
109     friend class Y<int>;
110   };
111 
112   template <class T> class Y {
113     friend void X<T>::f();
114   };
115 
116   template class Y<int>;
117 }
118