annotate gcc/cp/friend.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Help friends in C++.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 1997-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
7 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
8 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
9 any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
14 GNU General Public License for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #include "config.h"
kono
parents:
diff changeset
21 #include "system.h"
kono
parents:
diff changeset
22 #include "coretypes.h"
kono
parents:
diff changeset
23 #include "cp-tree.h"
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 /* Friend data structures are described in cp-tree.h. */
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 /* The GLOBAL_FRIEND scope (functions, classes, or templates) is
kono
parents:
diff changeset
29 regarded as a friend of every class. This is only used by libcc1,
kono
parents:
diff changeset
30 to enable GDB's code snippets to access private members without
kono
parents:
diff changeset
31 disabling access control in general, which could cause different
kono
parents:
diff changeset
32 template overload resolution results when accessibility matters
kono
parents:
diff changeset
33 (e.g. tests for an accessible member). */
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 static GTY(()) tree global_friend;
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 /* Set the GLOBAL_FRIEND for this compilation session. It might be
kono
parents:
diff changeset
38 set multiple times, but always to the same scope. */
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 void
kono
parents:
diff changeset
41 set_global_friend (tree scope)
kono
parents:
diff changeset
42 {
kono
parents:
diff changeset
43 gcc_checking_assert (scope != NULL_TREE);
kono
parents:
diff changeset
44 gcc_assert (!global_friend || global_friend == scope);
kono
parents:
diff changeset
45 global_friend = scope;
kono
parents:
diff changeset
46 }
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 /* Return TRUE if SCOPE is the global friend. */
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 bool
kono
parents:
diff changeset
51 is_global_friend (tree scope)
kono
parents:
diff changeset
52 {
kono
parents:
diff changeset
53 gcc_checking_assert (scope != NULL_TREE);
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 if (global_friend == scope)
kono
parents:
diff changeset
56 return true;
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 if (!global_friend)
kono
parents:
diff changeset
59 return false;
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 if (is_specialization_of_friend (global_friend, scope))
kono
parents:
diff changeset
62 return true;
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 return false;
kono
parents:
diff changeset
65 }
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 /* Returns nonzero if SUPPLICANT is a friend of TYPE. */
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 int
kono
parents:
diff changeset
70 is_friend (tree type, tree supplicant)
kono
parents:
diff changeset
71 {
kono
parents:
diff changeset
72 int declp;
kono
parents:
diff changeset
73 tree list;
kono
parents:
diff changeset
74 tree context;
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 if (supplicant == NULL_TREE || type == NULL_TREE)
kono
parents:
diff changeset
77 return 0;
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 if (is_global_friend (supplicant))
kono
parents:
diff changeset
80 return 1;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 declp = DECL_P (supplicant);
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 if (declp)
kono
parents:
diff changeset
85 /* It's a function decl. */
kono
parents:
diff changeset
86 {
kono
parents:
diff changeset
87 tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
kono
parents:
diff changeset
88 tree name = DECL_NAME (supplicant);
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 for (; list ; list = TREE_CHAIN (list))
kono
parents:
diff changeset
91 {
kono
parents:
diff changeset
92 if (name == FRIEND_NAME (list))
kono
parents:
diff changeset
93 {
kono
parents:
diff changeset
94 tree friends = FRIEND_DECLS (list);
kono
parents:
diff changeset
95 for (; friends ; friends = TREE_CHAIN (friends))
kono
parents:
diff changeset
96 {
kono
parents:
diff changeset
97 tree this_friend = TREE_VALUE (friends);
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 if (this_friend == NULL_TREE)
kono
parents:
diff changeset
100 continue;
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 if (supplicant == this_friend)
kono
parents:
diff changeset
103 return 1;
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 if (is_specialization_of_friend (supplicant, this_friend))
kono
parents:
diff changeset
106 return 1;
kono
parents:
diff changeset
107 }
kono
parents:
diff changeset
108 break;
kono
parents:
diff changeset
109 }
kono
parents:
diff changeset
110 }
kono
parents:
diff changeset
111 }
kono
parents:
diff changeset
112 else
kono
parents:
diff changeset
113 /* It's a type. */
kono
parents:
diff changeset
114 {
kono
parents:
diff changeset
115 if (same_type_p (supplicant, type))
kono
parents:
diff changeset
116 return 1;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
kono
parents:
diff changeset
119 for (; list ; list = TREE_CHAIN (list))
kono
parents:
diff changeset
120 {
kono
parents:
diff changeset
121 tree t = TREE_VALUE (list);
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 if (TREE_CODE (t) == TEMPLATE_DECL ?
kono
parents:
diff changeset
124 is_specialization_of_friend (TYPE_MAIN_DECL (supplicant), t) :
kono
parents:
diff changeset
125 same_type_p (supplicant, t))
kono
parents:
diff changeset
126 return 1;
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128 }
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 if (declp)
kono
parents:
diff changeset
131 {
kono
parents:
diff changeset
132 if (DECL_FUNCTION_MEMBER_P (supplicant))
kono
parents:
diff changeset
133 context = DECL_CONTEXT (supplicant);
kono
parents:
diff changeset
134 else
kono
parents:
diff changeset
135 context = NULL_TREE;
kono
parents:
diff changeset
136 }
kono
parents:
diff changeset
137 else
kono
parents:
diff changeset
138 {
kono
parents:
diff changeset
139 if (TYPE_CLASS_SCOPE_P (supplicant))
kono
parents:
diff changeset
140 /* Nested classes get the same access as their enclosing types, as
kono
parents:
diff changeset
141 per DR 45 (this is a change from the standard). */
kono
parents:
diff changeset
142 context = TYPE_CONTEXT (supplicant);
kono
parents:
diff changeset
143 else
kono
parents:
diff changeset
144 /* Local classes have the same access as the enclosing function. */
kono
parents:
diff changeset
145 context = decl_function_context (TYPE_MAIN_DECL (supplicant));
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 /* A namespace is not friend to anybody. */
kono
parents:
diff changeset
149 if (context && TREE_CODE (context) == NAMESPACE_DECL)
kono
parents:
diff changeset
150 context = NULL_TREE;
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 if (context)
kono
parents:
diff changeset
153 return is_friend (type, context);
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 return 0;
kono
parents:
diff changeset
156 }
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 /* Add a new friend to the friends of the aggregate type TYPE.
kono
parents:
diff changeset
159 DECL is the FUNCTION_DECL of the friend being added.
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 If COMPLAIN is true, warning about duplicate friend is issued.
kono
parents:
diff changeset
162 We want to have this diagnostics during parsing but not
kono
parents:
diff changeset
163 when a template is being instantiated. */
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 void
kono
parents:
diff changeset
166 add_friend (tree type, tree decl, bool complain)
kono
parents:
diff changeset
167 {
kono
parents:
diff changeset
168 tree typedecl;
kono
parents:
diff changeset
169 tree list;
kono
parents:
diff changeset
170 tree name;
kono
parents:
diff changeset
171 tree ctx;
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 if (decl == error_mark_node)
kono
parents:
diff changeset
174 return;
kono
parents:
diff changeset
175
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
176 if (TREE_CODE (decl) == FUNCTION_DECL
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
177 && DECL_TEMPLATE_INSTANTIATION (decl))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
178 /* We'll have parsed this as a declaration, and therefore not
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
179 marked the lookup set for keeping. Do that now. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
180 lookup_keep (DECL_TI_TEMPLATE (decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
181
111
kono
parents:
diff changeset
182 typedecl = TYPE_MAIN_DECL (type);
kono
parents:
diff changeset
183 list = DECL_FRIENDLIST (typedecl);
kono
parents:
diff changeset
184 name = DECL_NAME (decl);
kono
parents:
diff changeset
185 type = TREE_TYPE (typedecl);
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 while (list)
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 if (name == FRIEND_NAME (list))
kono
parents:
diff changeset
190 {
kono
parents:
diff changeset
191 tree friends = FRIEND_DECLS (list);
kono
parents:
diff changeset
192 for (; friends ; friends = TREE_CHAIN (friends))
kono
parents:
diff changeset
193 {
kono
parents:
diff changeset
194 if (decl == TREE_VALUE (friends))
kono
parents:
diff changeset
195 {
kono
parents:
diff changeset
196 if (complain)
kono
parents:
diff changeset
197 warning (OPT_Wredundant_decls,
kono
parents:
diff changeset
198 "%qD is already a friend of class %qT",
kono
parents:
diff changeset
199 decl, type);
kono
parents:
diff changeset
200 return;
kono
parents:
diff changeset
201 }
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
kono
parents:
diff changeset
205 TREE_VALUE (list));
kono
parents:
diff changeset
206 break;
kono
parents:
diff changeset
207 }
kono
parents:
diff changeset
208 list = TREE_CHAIN (list);
kono
parents:
diff changeset
209 }
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 ctx = DECL_CONTEXT (decl);
kono
parents:
diff changeset
212 if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
kono
parents:
diff changeset
213 perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl,
kono
parents:
diff changeset
214 tf_warning_or_error);
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 if (!list)
kono
parents:
diff changeset
219 DECL_FRIENDLIST (typedecl)
kono
parents:
diff changeset
220 = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
kono
parents:
diff changeset
221 DECL_FRIENDLIST (typedecl));
kono
parents:
diff changeset
222 if (!uses_template_parms (type))
kono
parents:
diff changeset
223 DECL_BEFRIENDING_CLASSES (decl)
kono
parents:
diff changeset
224 = tree_cons (NULL_TREE, type,
kono
parents:
diff changeset
225 DECL_BEFRIENDING_CLASSES (decl));
kono
parents:
diff changeset
226 }
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 /* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
kono
parents:
diff changeset
229 been defined, we make all of its member functions friends of
kono
parents:
diff changeset
230 TYPE. If not, we make it a pending friend, which can later be added
kono
parents:
diff changeset
231 when its definition is seen. If a type is defined, then its TYPE_DECL's
kono
parents:
diff changeset
232 DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
kono
parents:
diff changeset
233 classes that are not defined. If a type has not yet been defined,
kono
parents:
diff changeset
234 then the DECL_WAITING_FRIENDS contains a list of types
kono
parents:
diff changeset
235 waiting to make it their friend. Note that these two can both
kono
parents:
diff changeset
236 be in use at the same time!
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 If COMPLAIN is true, warning about duplicate friend is issued.
kono
parents:
diff changeset
239 We want to have this diagnostics during parsing but not
kono
parents:
diff changeset
240 when a template is being instantiated. */
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 void
kono
parents:
diff changeset
243 make_friend_class (tree type, tree friend_type, bool complain)
kono
parents:
diff changeset
244 {
kono
parents:
diff changeset
245 tree classes;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
kono
parents:
diff changeset
248 the enclosing class. FRIEND_DEPTH counts the number of template
kono
parents:
diff changeset
249 headers used for this friend declaration. TEMPLATE_MEMBER_P,
kono
parents:
diff changeset
250 defined inside the `if' block for TYPENAME_TYPE case, is true if
kono
parents:
diff changeset
251 a template header in FRIEND_DEPTH is intended for DECLARATOR.
kono
parents:
diff changeset
252 For example, the code
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 template <class T> struct A {
kono
parents:
diff changeset
255 template <class U> struct B {
kono
parents:
diff changeset
256 template <class V> template <class W>
kono
parents:
diff changeset
257 friend class C<V>::D;
kono
parents:
diff changeset
258 };
kono
parents:
diff changeset
259 };
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 will eventually give the following results
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
kono
parents:
diff changeset
264 2. FRIEND_DEPTH equals 2 (for `V' and `W').
kono
parents:
diff changeset
265 3. TEMPLATE_MEMBER_P is true (for `W').
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 The friend is a template friend iff FRIEND_DEPTH is nonzero. */
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 int class_template_depth = template_class_depth (type);
kono
parents:
diff changeset
270 int friend_depth = processing_template_decl - class_template_depth;
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 if (! MAYBE_CLASS_TYPE_P (friend_type)
kono
parents:
diff changeset
273 && TREE_CODE (friend_type) != TEMPLATE_TEMPLATE_PARM)
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 /* N1791: If the type specifier in a friend declaration designates a
kono
parents:
diff changeset
276 (possibly cv-qualified) class type, that class is declared as a
kono
parents:
diff changeset
277 friend; otherwise, the friend declaration is ignored.
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 So don't complain in C++11 mode. */
kono
parents:
diff changeset
280 if (cxx_dialect < cxx11)
kono
parents:
diff changeset
281 pedwarn (input_location, complain ? 0 : OPT_Wpedantic,
kono
parents:
diff changeset
282 "invalid type %qT declared %<friend%>", friend_type);
kono
parents:
diff changeset
283 return;
kono
parents:
diff changeset
284 }
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 friend_type = cv_unqualified (friend_type);
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 if (check_for_bare_parameter_packs (friend_type))
kono
parents:
diff changeset
289 return;
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 if (friend_depth)
kono
parents:
diff changeset
292 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
293 /* [temp.friend] Friend declarations shall not declare partial
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
294 specializations. */
111
kono
parents:
diff changeset
295 if (CLASS_TYPE_P (friend_type)
kono
parents:
diff changeset
296 && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
kono
parents:
diff changeset
297 && uses_template_parms (friend_type))
kono
parents:
diff changeset
298 {
kono
parents:
diff changeset
299 error ("partial specialization %qT declared %<friend%>",
kono
parents:
diff changeset
300 friend_type);
kono
parents:
diff changeset
301 return;
kono
parents:
diff changeset
302 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
303
111
kono
parents:
diff changeset
304 if (TYPE_TEMPLATE_INFO (friend_type)
kono
parents:
diff changeset
305 && !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type)))
kono
parents:
diff changeset
306 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
307 auto_diagnostic_group d;
111
kono
parents:
diff changeset
308 error ("%qT is not a template", friend_type);
kono
parents:
diff changeset
309 inform (location_of (friend_type), "previous declaration here");
kono
parents:
diff changeset
310 if (TYPE_CLASS_SCOPE_P (friend_type)
kono
parents:
diff changeset
311 && CLASSTYPE_TEMPLATE_INFO (TYPE_CONTEXT (friend_type))
kono
parents:
diff changeset
312 && currently_open_class (TYPE_CONTEXT (friend_type)))
kono
parents:
diff changeset
313 inform (input_location, "perhaps you need explicit template "
kono
parents:
diff changeset
314 "arguments in your nested-name-specifier");
kono
parents:
diff changeset
315 return;
kono
parents:
diff changeset
316 }
kono
parents:
diff changeset
317 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
318
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
319 /* It makes sense for a template class to be friends with itself,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
320 that means the instantiations can be friendly. Other cases are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
321 not so meaningful. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
322 if (!friend_depth && same_type_p (type, friend_type))
111
kono
parents:
diff changeset
323 {
kono
parents:
diff changeset
324 if (complain)
kono
parents:
diff changeset
325 warning (0, "class %qT is implicitly friends with itself",
kono
parents:
diff changeset
326 type);
kono
parents:
diff changeset
327 return;
kono
parents:
diff changeset
328 }
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 /* [temp.friend]
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 A friend of a class or class template can be a function or
kono
parents:
diff changeset
333 class template, a specialization of a function template or
kono
parents:
diff changeset
334 class template, or an ordinary (nontemplate) function or
kono
parents:
diff changeset
335 class. */
kono
parents:
diff changeset
336 if (!friend_depth)
kono
parents:
diff changeset
337 ;/* ok */
kono
parents:
diff changeset
338 else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
kono
parents:
diff changeset
339 {
kono
parents:
diff changeset
340 if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
kono
parents:
diff changeset
341 == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
342 {
kono
parents:
diff changeset
343 /* template <class U> friend class T::X<U>; */
kono
parents:
diff changeset
344 /* [temp.friend]
kono
parents:
diff changeset
345 Friend declarations shall not declare partial
kono
parents:
diff changeset
346 specializations. */
kono
parents:
diff changeset
347 error ("partial specialization %qT declared %<friend%>",
kono
parents:
diff changeset
348 friend_type);
kono
parents:
diff changeset
349 return;
kono
parents:
diff changeset
350 }
kono
parents:
diff changeset
351 else
kono
parents:
diff changeset
352 {
kono
parents:
diff changeset
353 /* We will figure this out later. */
kono
parents:
diff changeset
354 bool template_member_p = false;
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 tree ctype = TYPE_CONTEXT (friend_type);
kono
parents:
diff changeset
357 tree name = TYPE_IDENTIFIER (friend_type);
kono
parents:
diff changeset
358 tree decl;
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 if (!uses_template_parms_level (ctype, class_template_depth
kono
parents:
diff changeset
361 + friend_depth))
kono
parents:
diff changeset
362 template_member_p = true;
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 if (class_template_depth)
kono
parents:
diff changeset
365 {
kono
parents:
diff changeset
366 /* We rely on tsubst_friend_class to check the
kono
parents:
diff changeset
367 validity of the declaration later. */
kono
parents:
diff changeset
368 if (template_member_p)
kono
parents:
diff changeset
369 friend_type
kono
parents:
diff changeset
370 = make_unbound_class_template (ctype,
kono
parents:
diff changeset
371 name,
kono
parents:
diff changeset
372 current_template_parms,
kono
parents:
diff changeset
373 tf_error);
kono
parents:
diff changeset
374 else
kono
parents:
diff changeset
375 friend_type
kono
parents:
diff changeset
376 = make_typename_type (ctype, name, class_type, tf_error);
kono
parents:
diff changeset
377 }
kono
parents:
diff changeset
378 else
kono
parents:
diff changeset
379 {
kono
parents:
diff changeset
380 decl = lookup_member (ctype, name, 0, true, tf_warning_or_error);
kono
parents:
diff changeset
381 if (!decl)
kono
parents:
diff changeset
382 {
kono
parents:
diff changeset
383 error ("%qT is not a member of %qT", name, ctype);
kono
parents:
diff changeset
384 return;
kono
parents:
diff changeset
385 }
kono
parents:
diff changeset
386 if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
kono
parents:
diff changeset
387 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
388 auto_diagnostic_group d;
111
kono
parents:
diff changeset
389 error ("%qT is not a member class template of %qT",
kono
parents:
diff changeset
390 name, ctype);
kono
parents:
diff changeset
391 inform (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
392 "%qD declared here", decl);
kono
parents:
diff changeset
393 return;
kono
parents:
diff changeset
394 }
kono
parents:
diff changeset
395 if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
kono
parents:
diff changeset
396 || !CLASS_TYPE_P (TREE_TYPE (decl))))
kono
parents:
diff changeset
397 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
398 auto_diagnostic_group d;
111
kono
parents:
diff changeset
399 error ("%qT is not a nested class of %qT",
kono
parents:
diff changeset
400 name, ctype);
kono
parents:
diff changeset
401 inform (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
402 "%qD declared here", decl);
kono
parents:
diff changeset
403 return;
kono
parents:
diff changeset
404 }
kono
parents:
diff changeset
405
kono
parents:
diff changeset
406 friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
kono
parents:
diff changeset
407 }
kono
parents:
diff changeset
408 }
kono
parents:
diff changeset
409 }
kono
parents:
diff changeset
410 else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
kono
parents:
diff changeset
411 {
kono
parents:
diff changeset
412 /* template <class T> friend class T; */
kono
parents:
diff changeset
413 error ("template parameter type %qT declared %<friend%>", friend_type);
kono
parents:
diff changeset
414 return;
kono
parents:
diff changeset
415 }
kono
parents:
diff changeset
416 else if (TREE_CODE (friend_type) == TEMPLATE_TEMPLATE_PARM)
kono
parents:
diff changeset
417 friend_type = TYPE_NAME (friend_type);
kono
parents:
diff changeset
418 else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
kono
parents:
diff changeset
419 {
kono
parents:
diff changeset
420 /* template <class T> friend class A; where A is not a template */
kono
parents:
diff changeset
421 error ("%q#T is not a template", friend_type);
kono
parents:
diff changeset
422 return;
kono
parents:
diff changeset
423 }
kono
parents:
diff changeset
424 else
kono
parents:
diff changeset
425 /* template <class T> friend class A; where A is a template */
kono
parents:
diff changeset
426 friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 if (friend_type == error_mark_node)
kono
parents:
diff changeset
429 return;
kono
parents:
diff changeset
430
kono
parents:
diff changeset
431 /* See if it is already a friend. */
kono
parents:
diff changeset
432 for (classes = CLASSTYPE_FRIEND_CLASSES (type);
kono
parents:
diff changeset
433 classes;
kono
parents:
diff changeset
434 classes = TREE_CHAIN (classes))
kono
parents:
diff changeset
435 {
kono
parents:
diff changeset
436 tree probe = TREE_VALUE (classes);
kono
parents:
diff changeset
437
kono
parents:
diff changeset
438 if (TREE_CODE (friend_type) == TEMPLATE_DECL)
kono
parents:
diff changeset
439 {
kono
parents:
diff changeset
440 if (friend_type == probe)
kono
parents:
diff changeset
441 {
kono
parents:
diff changeset
442 if (complain)
kono
parents:
diff changeset
443 warning (OPT_Wredundant_decls,
kono
parents:
diff changeset
444 "%qD is already a friend of %qT", probe, type);
kono
parents:
diff changeset
445 break;
kono
parents:
diff changeset
446 }
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448 else if (TREE_CODE (probe) != TEMPLATE_DECL)
kono
parents:
diff changeset
449 {
kono
parents:
diff changeset
450 if (same_type_p (probe, friend_type))
kono
parents:
diff changeset
451 {
kono
parents:
diff changeset
452 if (complain)
kono
parents:
diff changeset
453 warning (OPT_Wredundant_decls,
kono
parents:
diff changeset
454 "%qT is already a friend of %qT", probe, type);
kono
parents:
diff changeset
455 break;
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457 }
kono
parents:
diff changeset
458 }
kono
parents:
diff changeset
459
kono
parents:
diff changeset
460 if (!classes)
kono
parents:
diff changeset
461 {
kono
parents:
diff changeset
462 maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 CLASSTYPE_FRIEND_CLASSES (type)
kono
parents:
diff changeset
465 = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
kono
parents:
diff changeset
466 if (TREE_CODE (friend_type) == TEMPLATE_DECL)
kono
parents:
diff changeset
467 friend_type = TREE_TYPE (friend_type);
kono
parents:
diff changeset
468 if (!uses_template_parms (type))
kono
parents:
diff changeset
469 CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
kono
parents:
diff changeset
470 = tree_cons (NULL_TREE, type,
kono
parents:
diff changeset
471 CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
kono
parents:
diff changeset
472 }
kono
parents:
diff changeset
473 }
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 /* Record DECL (a FUNCTION_DECL) as a friend of the
kono
parents:
diff changeset
476 CURRENT_CLASS_TYPE. If DECL is a member function, CTYPE is the
kono
parents:
diff changeset
477 class of which it is a member, as named in the friend declaration.
kono
parents:
diff changeset
478 DECLARATOR is the name of the friend. FUNCDEF_FLAG is true if the
kono
parents:
diff changeset
479 friend declaration is a definition of the function. FLAGS is as
kono
parents:
diff changeset
480 for grokclass fn. */
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 tree
kono
parents:
diff changeset
483 do_friend (tree ctype, tree declarator, tree decl,
kono
parents:
diff changeset
484 tree attrlist, enum overload_flags flags,
kono
parents:
diff changeset
485 bool funcdef_flag)
kono
parents:
diff changeset
486 {
kono
parents:
diff changeset
487 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
kono
parents:
diff changeset
488 gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 /* Every decl that gets here is a friend of something. */
kono
parents:
diff changeset
491 DECL_FRIEND_P (decl) = 1;
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl))
kono
parents:
diff changeset
494 error ("friend declaration %qD may not have virt-specifiers",
kono
parents:
diff changeset
495 decl);
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 /* Unfortunately, we have to handle attributes here. Normally we would
kono
parents:
diff changeset
498 handle them in start_decl_1, but since this is a friend decl start_decl_1
kono
parents:
diff changeset
499 never gets to see it. */
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 /* Set attributes here so if duplicate decl, will have proper attributes. */
kono
parents:
diff changeset
502 cplus_decl_attributes (&decl, attrlist, 0);
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
505 {
kono
parents:
diff changeset
506 declarator = TREE_OPERAND (declarator, 0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
507 if (!identifier_p (declarator))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
508 declarator = OVL_NAME (declarator);
111
kono
parents:
diff changeset
509 }
kono
parents:
diff changeset
510
kono
parents:
diff changeset
511 if (ctype)
kono
parents:
diff changeset
512 {
kono
parents:
diff changeset
513 /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
kono
parents:
diff changeset
514 the enclosing class. FRIEND_DEPTH counts the number of template
kono
parents:
diff changeset
515 headers used for this friend declaration. TEMPLATE_MEMBER_P is
kono
parents:
diff changeset
516 true if a template header in FRIEND_DEPTH is intended for
kono
parents:
diff changeset
517 DECLARATOR. For example, the code
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 template <class T> struct A {
kono
parents:
diff changeset
520 template <class U> struct B {
kono
parents:
diff changeset
521 template <class V> template <class W>
kono
parents:
diff changeset
522 friend void C<V>::f(W);
kono
parents:
diff changeset
523 };
kono
parents:
diff changeset
524 };
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 will eventually give the following results
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
kono
parents:
diff changeset
529 2. FRIEND_DEPTH equals 2 (for `V' and `W').
kono
parents:
diff changeset
530 3. TEMPLATE_MEMBER_P is true (for `W'). */
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 int class_template_depth = template_class_depth (current_class_type);
kono
parents:
diff changeset
533 int friend_depth = processing_template_decl - class_template_depth;
kono
parents:
diff changeset
534 /* We will figure this out later. */
kono
parents:
diff changeset
535 bool template_member_p = false;
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 tree cname = TYPE_NAME (ctype);
kono
parents:
diff changeset
538 if (TREE_CODE (cname) == TYPE_DECL)
kono
parents:
diff changeset
539 cname = DECL_NAME (cname);
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 /* A method friend. */
kono
parents:
diff changeset
542 if (flags == NO_SPECIAL && declarator == cname)
kono
parents:
diff changeset
543 DECL_CXX_CONSTRUCTOR_P (decl) = 1;
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 grokclassfn (ctype, decl, flags);
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 if (friend_depth)
kono
parents:
diff changeset
548 {
kono
parents:
diff changeset
549 if (!uses_template_parms_level (ctype, class_template_depth
kono
parents:
diff changeset
550 + friend_depth))
kono
parents:
diff changeset
551 template_member_p = true;
kono
parents:
diff changeset
552 }
kono
parents:
diff changeset
553
kono
parents:
diff changeset
554 /* A nested class may declare a member of an enclosing class
kono
parents:
diff changeset
555 to be a friend, so we do lookup here even if CTYPE is in
kono
parents:
diff changeset
556 the process of being defined. */
kono
parents:
diff changeset
557 if (class_template_depth
kono
parents:
diff changeset
558 || COMPLETE_OR_OPEN_TYPE_P (ctype))
kono
parents:
diff changeset
559 {
kono
parents:
diff changeset
560 if (DECL_TEMPLATE_INFO (decl))
kono
parents:
diff changeset
561 /* DECL is a template specialization. No need to
kono
parents:
diff changeset
562 build a new TEMPLATE_DECL. */
kono
parents:
diff changeset
563 ;
kono
parents:
diff changeset
564 else if (class_template_depth)
kono
parents:
diff changeset
565 /* We rely on tsubst_friend_function to check the
kono
parents:
diff changeset
566 validity of the declaration later. */
kono
parents:
diff changeset
567 decl = push_template_decl_real (decl, /*is_friend=*/true);
kono
parents:
diff changeset
568 else
kono
parents:
diff changeset
569 decl = check_classfn (ctype, decl,
kono
parents:
diff changeset
570 template_member_p
kono
parents:
diff changeset
571 ? current_template_parms
kono
parents:
diff changeset
572 : NULL_TREE);
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 if ((template_member_p
kono
parents:
diff changeset
575 /* Always pull out the TEMPLATE_DECL if we have a friend
kono
parents:
diff changeset
576 template in a class template so that it gets tsubsted
kono
parents:
diff changeset
577 properly later on (59956). tsubst_friend_function knows
kono
parents:
diff changeset
578 how to tell this apart from a member template. */
kono
parents:
diff changeset
579 || (class_template_depth && friend_depth))
kono
parents:
diff changeset
580 && decl && TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
581 decl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 if (decl)
kono
parents:
diff changeset
584 add_friend (current_class_type, decl, /*complain=*/true);
kono
parents:
diff changeset
585 }
kono
parents:
diff changeset
586 else
kono
parents:
diff changeset
587 error ("member %qD declared as friend before type %qT defined",
kono
parents:
diff changeset
588 decl, ctype);
kono
parents:
diff changeset
589 }
kono
parents:
diff changeset
590 /* A global friend.
kono
parents:
diff changeset
591 @@ or possibly a friend from a base class ?!? */
kono
parents:
diff changeset
592 else if (TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
593 {
kono
parents:
diff changeset
594 int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 /* Friends must all go through the overload machinery,
kono
parents:
diff changeset
597 even though they may not technically be overloaded.
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 Note that because classes all wind up being top-level
kono
parents:
diff changeset
600 in their scope, their friend wind up in top-level scope as well. */
kono
parents:
diff changeset
601 if (funcdef_flag)
kono
parents:
diff changeset
602 SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 if (! DECL_USE_TEMPLATE (decl))
kono
parents:
diff changeset
605 {
kono
parents:
diff changeset
606 /* We must check whether the decl refers to template
kono
parents:
diff changeset
607 arguments before push_template_decl_real adds a
kono
parents:
diff changeset
608 reference to the containing template class. */
kono
parents:
diff changeset
609 int warn = (warn_nontemplate_friend
kono
parents:
diff changeset
610 && ! funcdef_flag && ! is_friend_template
kono
parents:
diff changeset
611 && current_template_parms
kono
parents:
diff changeset
612 && uses_template_parms (decl));
kono
parents:
diff changeset
613
kono
parents:
diff changeset
614 if (is_friend_template
kono
parents:
diff changeset
615 || template_class_depth (current_class_type) != 0)
kono
parents:
diff changeset
616 /* We can't call pushdecl for a template class, since in
kono
parents:
diff changeset
617 general, such a declaration depends on template
kono
parents:
diff changeset
618 parameters. Instead, we call pushdecl when the class
kono
parents:
diff changeset
619 is instantiated. */
kono
parents:
diff changeset
620 decl = push_template_decl_real (decl, /*is_friend=*/true);
kono
parents:
diff changeset
621 else if (current_function_decl)
kono
parents:
diff changeset
622 /* pushdecl will check there's a local decl already. */
kono
parents:
diff changeset
623 decl = pushdecl (decl, /*is_friend=*/true);
kono
parents:
diff changeset
624 else
kono
parents:
diff changeset
625 {
kono
parents:
diff changeset
626 /* We can't use pushdecl, as we might be in a template
kono
parents:
diff changeset
627 class specialization, and pushdecl will insert an
kono
parents:
diff changeset
628 unqualified friend decl into the template parameter
kono
parents:
diff changeset
629 scope, rather than the namespace containing it. */
kono
parents:
diff changeset
630 tree ns = decl_namespace_context (decl);
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 push_nested_namespace (ns);
kono
parents:
diff changeset
633 decl = pushdecl_namespace_level (decl, /*is_friend=*/true);
kono
parents:
diff changeset
634 pop_nested_namespace (ns);
kono
parents:
diff changeset
635 }
kono
parents:
diff changeset
636
kono
parents:
diff changeset
637 if (warn)
kono
parents:
diff changeset
638 {
kono
parents:
diff changeset
639 static int explained;
kono
parents:
diff changeset
640 bool warned;
kono
parents:
diff changeset
641
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
642 auto_diagnostic_group d;
111
kono
parents:
diff changeset
643 warned = warning (OPT_Wnon_template_friend, "friend declaration "
kono
parents:
diff changeset
644 "%q#D declares a non-template function", decl);
kono
parents:
diff changeset
645 if (! explained && warned)
kono
parents:
diff changeset
646 {
kono
parents:
diff changeset
647 inform (input_location, "(if this is not what you intended, make sure "
kono
parents:
diff changeset
648 "the function template has already been declared "
kono
parents:
diff changeset
649 "and add <> after the function name here) ");
kono
parents:
diff changeset
650 explained = 1;
kono
parents:
diff changeset
651 }
kono
parents:
diff changeset
652 }
kono
parents:
diff changeset
653 }
kono
parents:
diff changeset
654
kono
parents:
diff changeset
655 if (decl == error_mark_node)
kono
parents:
diff changeset
656 return error_mark_node;
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 add_friend (current_class_type,
kono
parents:
diff changeset
659 is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
kono
parents:
diff changeset
660 /*complain=*/true);
kono
parents:
diff changeset
661 DECL_FRIEND_P (decl) = 1;
kono
parents:
diff changeset
662 }
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 return decl;
kono
parents:
diff changeset
665 }
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 #include "gt-cp-friend.h"