1 | // RUN: %clang_cc1 -fsyntax-only %s -verify |
2 | |
3 | // C++'0x [namespace.memdef] p3: |
4 | // Every name first declared in a namespace is a member of that namespace. If |
5 | // a friend declaration in a non-local class first declares a class or |
6 | // function the friend class or function is a member of the innermost |
7 | // enclosing namespace. |
8 | |
9 | namespace N { |
10 | struct S0 { |
11 | friend struct F0; |
12 | friend void f0(int); |
13 | struct F0 member_func(); |
14 | }; |
15 | struct F0 { }; |
16 | F0 f0() { return S0().member_func(); } |
17 | } |
18 | N::F0 f0_var = N::f0(); |
19 | |
20 | // Ensure we can handle attaching friend declarations to an enclosing namespace |
21 | // with multiple contexts. |
22 | namespace N { struct S1 { struct IS1; }; } |
23 | namespace N { |
24 | struct S1::IS1 { |
25 | friend struct F1; |
26 | friend void f1(int); |
27 | struct F1 member_func(); |
28 | }; |
29 | struct F1 { }; |
30 | F1 f1() { return S1::IS1().member_func(); } |
31 | } |
32 | N::F1 f1_var = N::f1(); |
33 | |
34 | // The name of the friend is not found by unqualified lookup (3.4.1) or by |
35 | // qualified lookup (3.4.3) until a matching declaration is provided in that |
36 | // namespace scope (either before or after the class definition granting |
37 | // friendship). If a friend function is called, its name may be found by the |
38 | // name lookup that considers functions from namespaces and classes |
39 | // associated with the types of the function arguments (3.4.2). If the name |
40 | // in a friend declaration is neither qualified nor a template-id and the |
41 | // declaration is a function or an elaborated-type-specifier, the lookup to |
42 | // determine whether the entity has been previously declared shall not |
43 | // consider any scopes outside the innermost enclosing namespace. |
44 | |
45 | template<typename T> struct X0 { }; |
46 | struct X1 { }; |
47 | |
48 | struct Y { |
49 | template<typename T> union X0; |
50 | template<typename T> friend union X0; |
51 | |
52 | union X1; |
53 | friend union X1; |
54 | }; |
55 | |
56 | namespace N { |
57 | namespace M { |
58 | template<typename T> class X; |
59 | } |
60 | } |
61 | |
62 | namespace N3 { |
63 | class Y { |
64 | template<typename T> friend class N::M::X; |
65 | }; |
66 | } |
67 | |
68 | // FIXME: Woefully inadequate for testing |
69 | |
70 | // Friends declared as template-ids aren't subject to the restriction |
71 | // on innermost namespaces. |
72 | // rdar://problem/8552377 |
73 | namespace test5 { |
74 | template <class T> void f(T); |
75 | namespace ns { |
76 | class A { |
77 | friend void f<int>(int); |
78 | static void foo(); // expected-note 2 {{declared private here}} |
79 | }; |
80 | |
81 | // Note that this happens without instantiation. |
82 | template <class T> void f(T) { |
83 | A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} |
84 | } |
85 | } |
86 | |
87 | template <class T> void f(T) { |
88 | ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} |
89 | } |
90 | |
91 | template void f<int>(int); |
92 | template void f<long>(long); //expected-note {{instantiation}} |
93 | } |
94 | |
95 | // rdar://13393749 |
96 | namespace test6 { |
97 | class A; |
98 | namespace ns { |
99 | class B { |
100 | static void foo(); // expected-note {{implicitly declared private here}} |
101 | friend union A; |
102 | }; |
103 | |
104 | union A { |
105 | void test() { |
106 | B::foo(); |
107 | } |
108 | }; |
109 | } |
110 | |
111 | class A { |
112 | void test() { |
113 | ns::B::foo(); // expected-error {{'foo' is a private member of 'test6::ns::B'}} |
114 | } |
115 | }; |
116 | } |
117 | |
118 | // We seem to be following a correct interpretation with these, but |
119 | // the standard could probably be a bit clearer. |
120 | namespace test7a { |
121 | namespace ns { |
122 | class A; |
123 | } |
124 | |
125 | using namespace ns; |
126 | class B { |
127 | static void foo(); |
128 | friend class A; |
129 | }; |
130 | |
131 | class ns::A { |
132 | void test() { |
133 | B::foo(); |
134 | } |
135 | }; |
136 | } |
137 | namespace test7b { |
138 | namespace ns { |
139 | class A; |
140 | } |
141 | |
142 | using ns::A; |
143 | class B { |
144 | static void foo(); |
145 | friend class A; |
146 | }; |
147 | |
148 | class ns::A { |
149 | void test() { |
150 | B::foo(); |
151 | } |
152 | }; |
153 | } |
154 | namespace test7c { |
155 | namespace ns1 { |
156 | class A; |
157 | } |
158 | |
159 | namespace ns2 { |
160 | // ns1::A appears as if declared in test7c according to [namespace.udir]p2. |
161 | // I think that means we aren't supposed to find it. |
162 | using namespace ns1; |
163 | class B { |
164 | static void foo(); // expected-note {{implicitly declared private here}} |
165 | friend class A; |
166 | }; |
167 | } |
168 | |
169 | class ns1::A { |
170 | void test() { |
171 | ns2::B::foo(); // expected-error {{'foo' is a private member of 'test7c::ns2::B'}} |
172 | } |
173 | }; |
174 | } |
175 | namespace test7d { |
176 | namespace ns1 { |
177 | class A; |
178 | } |
179 | |
180 | namespace ns2 { |
181 | // Honor the lexical context of a using-declaration, though. |
182 | using ns1::A; |
183 | class B { |
184 | static void foo(); |
185 | friend class A; |
186 | }; |
187 | } |
188 | |
189 | class ns1::A { |
190 | void test() { |
191 | ns2::B::foo(); |
192 | } |
193 | }; |
194 | } |
195 | |