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 | |