annotate gcc/cp/friend.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Help friends in C++.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 1997-2020 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
kono
parents:
diff changeset
176 typedecl = TYPE_MAIN_DECL (type);
kono
parents:
diff changeset
177 list = DECL_FRIENDLIST (typedecl);
kono
parents:
diff changeset
178 name = DECL_NAME (decl);
kono
parents:
diff changeset
179 type = TREE_TYPE (typedecl);
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 while (list)
kono
parents:
diff changeset
182 {
kono
parents:
diff changeset
183 if (name == FRIEND_NAME (list))
kono
parents:
diff changeset
184 {
kono
parents:
diff changeset
185 tree friends = FRIEND_DECLS (list);
kono
parents:
diff changeset
186 for (; friends ; friends = TREE_CHAIN (friends))
kono
parents:
diff changeset
187 {
kono
parents:
diff changeset
188 if (decl == TREE_VALUE (friends))
kono
parents:
diff changeset
189 {
kono
parents:
diff changeset
190 if (complain)
kono
parents:
diff changeset
191 warning (OPT_Wredundant_decls,
kono
parents:
diff changeset
192 "%qD is already a friend of class %qT",
kono
parents:
diff changeset
193 decl, type);
kono
parents:
diff changeset
194 return;
kono
parents:
diff changeset
195 }
kono
parents:
diff changeset
196 }
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
kono
parents:
diff changeset
199 TREE_VALUE (list));
kono
parents:
diff changeset
200 break;
kono
parents:
diff changeset
201 }
kono
parents:
diff changeset
202 list = TREE_CHAIN (list);
kono
parents:
diff changeset
203 }
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 ctx = DECL_CONTEXT (decl);
kono
parents:
diff changeset
206 if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
kono
parents:
diff changeset
207 perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl,
kono
parents:
diff changeset
208 tf_warning_or_error);
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 if (!list)
kono
parents:
diff changeset
213 DECL_FRIENDLIST (typedecl)
kono
parents:
diff changeset
214 = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
kono
parents:
diff changeset
215 DECL_FRIENDLIST (typedecl));
kono
parents:
diff changeset
216 if (!uses_template_parms (type))
kono
parents:
diff changeset
217 DECL_BEFRIENDING_CLASSES (decl)
kono
parents:
diff changeset
218 = tree_cons (NULL_TREE, type,
kono
parents:
diff changeset
219 DECL_BEFRIENDING_CLASSES (decl));
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 /* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
kono
parents:
diff changeset
223 been defined, we make all of its member functions friends of
kono
parents:
diff changeset
224 TYPE. If not, we make it a pending friend, which can later be added
kono
parents:
diff changeset
225 when its definition is seen. If a type is defined, then its TYPE_DECL's
kono
parents:
diff changeset
226 DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
kono
parents:
diff changeset
227 classes that are not defined. If a type has not yet been defined,
kono
parents:
diff changeset
228 then the DECL_WAITING_FRIENDS contains a list of types
kono
parents:
diff changeset
229 waiting to make it their friend. Note that these two can both
kono
parents:
diff changeset
230 be in use at the same time!
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 If COMPLAIN is true, warning about duplicate friend is issued.
kono
parents:
diff changeset
233 We want to have this diagnostics during parsing but not
kono
parents:
diff changeset
234 when a template is being instantiated. */
kono
parents:
diff changeset
235
kono
parents:
diff changeset
236 void
kono
parents:
diff changeset
237 make_friend_class (tree type, tree friend_type, bool complain)
kono
parents:
diff changeset
238 {
kono
parents:
diff changeset
239 tree classes;
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
kono
parents:
diff changeset
242 the enclosing class. FRIEND_DEPTH counts the number of template
kono
parents:
diff changeset
243 headers used for this friend declaration. TEMPLATE_MEMBER_P,
kono
parents:
diff changeset
244 defined inside the `if' block for TYPENAME_TYPE case, is true if
kono
parents:
diff changeset
245 a template header in FRIEND_DEPTH is intended for DECLARATOR.
kono
parents:
diff changeset
246 For example, the code
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 template <class T> struct A {
kono
parents:
diff changeset
249 template <class U> struct B {
kono
parents:
diff changeset
250 template <class V> template <class W>
kono
parents:
diff changeset
251 friend class C<V>::D;
kono
parents:
diff changeset
252 };
kono
parents:
diff changeset
253 };
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 will eventually give the following results
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
kono
parents:
diff changeset
258 2. FRIEND_DEPTH equals 2 (for `V' and `W').
kono
parents:
diff changeset
259 3. TEMPLATE_MEMBER_P is true (for `W').
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 The friend is a template friend iff FRIEND_DEPTH is nonzero. */
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 int class_template_depth = template_class_depth (type);
kono
parents:
diff changeset
264 int friend_depth = processing_template_decl - class_template_depth;
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 if (! MAYBE_CLASS_TYPE_P (friend_type)
kono
parents:
diff changeset
267 && TREE_CODE (friend_type) != TEMPLATE_TEMPLATE_PARM)
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 /* N1791: If the type specifier in a friend declaration designates a
kono
parents:
diff changeset
270 (possibly cv-qualified) class type, that class is declared as a
kono
parents:
diff changeset
271 friend; otherwise, the friend declaration is ignored.
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 So don't complain in C++11 mode. */
kono
parents:
diff changeset
274 if (cxx_dialect < cxx11)
kono
parents:
diff changeset
275 pedwarn (input_location, complain ? 0 : OPT_Wpedantic,
kono
parents:
diff changeset
276 "invalid type %qT declared %<friend%>", friend_type);
kono
parents:
diff changeset
277 return;
kono
parents:
diff changeset
278 }
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 friend_type = cv_unqualified (friend_type);
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 if (check_for_bare_parameter_packs (friend_type))
kono
parents:
diff changeset
283 return;
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 if (friend_depth)
kono
parents:
diff changeset
286 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
287 /* [temp.friend] Friend declarations shall not declare partial
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
288 specializations. */
111
kono
parents:
diff changeset
289 if (CLASS_TYPE_P (friend_type)
kono
parents:
diff changeset
290 && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
kono
parents:
diff changeset
291 && uses_template_parms (friend_type))
kono
parents:
diff changeset
292 {
kono
parents:
diff changeset
293 error ("partial specialization %qT declared %<friend%>",
kono
parents:
diff changeset
294 friend_type);
kono
parents:
diff changeset
295 return;
kono
parents:
diff changeset
296 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
297
111
kono
parents:
diff changeset
298 if (TYPE_TEMPLATE_INFO (friend_type)
kono
parents:
diff changeset
299 && !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type)))
kono
parents:
diff changeset
300 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
301 auto_diagnostic_group d;
111
kono
parents:
diff changeset
302 error ("%qT is not a template", friend_type);
kono
parents:
diff changeset
303 inform (location_of (friend_type), "previous declaration here");
kono
parents:
diff changeset
304 if (TYPE_CLASS_SCOPE_P (friend_type)
kono
parents:
diff changeset
305 && CLASSTYPE_TEMPLATE_INFO (TYPE_CONTEXT (friend_type))
kono
parents:
diff changeset
306 && currently_open_class (TYPE_CONTEXT (friend_type)))
kono
parents:
diff changeset
307 inform (input_location, "perhaps you need explicit template "
kono
parents:
diff changeset
308 "arguments in your nested-name-specifier");
kono
parents:
diff changeset
309 return;
kono
parents:
diff changeset
310 }
kono
parents:
diff changeset
311 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
312
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
313 /* It makes sense for a template class to be friends with itself,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
314 that means the instantiations can be friendly. Other cases are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
315 not so meaningful. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
316 if (!friend_depth && same_type_p (type, friend_type))
111
kono
parents:
diff changeset
317 {
kono
parents:
diff changeset
318 if (complain)
kono
parents:
diff changeset
319 warning (0, "class %qT is implicitly friends with itself",
kono
parents:
diff changeset
320 type);
kono
parents:
diff changeset
321 return;
kono
parents:
diff changeset
322 }
kono
parents:
diff changeset
323
kono
parents:
diff changeset
324 /* [temp.friend]
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 A friend of a class or class template can be a function or
kono
parents:
diff changeset
327 class template, a specialization of a function template or
kono
parents:
diff changeset
328 class template, or an ordinary (nontemplate) function or
kono
parents:
diff changeset
329 class. */
kono
parents:
diff changeset
330 if (!friend_depth)
kono
parents:
diff changeset
331 ;/* ok */
kono
parents:
diff changeset
332 else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
kono
parents:
diff changeset
333 {
kono
parents:
diff changeset
334 if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
kono
parents:
diff changeset
335 == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 /* template <class U> friend class T::X<U>; */
kono
parents:
diff changeset
338 /* [temp.friend]
kono
parents:
diff changeset
339 Friend declarations shall not declare partial
kono
parents:
diff changeset
340 specializations. */
kono
parents:
diff changeset
341 error ("partial specialization %qT declared %<friend%>",
kono
parents:
diff changeset
342 friend_type);
kono
parents:
diff changeset
343 return;
kono
parents:
diff changeset
344 }
kono
parents:
diff changeset
345 else
kono
parents:
diff changeset
346 {
kono
parents:
diff changeset
347 /* We will figure this out later. */
kono
parents:
diff changeset
348 bool template_member_p = false;
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 tree ctype = TYPE_CONTEXT (friend_type);
kono
parents:
diff changeset
351 tree name = TYPE_IDENTIFIER (friend_type);
kono
parents:
diff changeset
352 tree decl;
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 if (!uses_template_parms_level (ctype, class_template_depth
kono
parents:
diff changeset
355 + friend_depth))
kono
parents:
diff changeset
356 template_member_p = true;
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 if (class_template_depth)
kono
parents:
diff changeset
359 {
kono
parents:
diff changeset
360 /* We rely on tsubst_friend_class to check the
kono
parents:
diff changeset
361 validity of the declaration later. */
kono
parents:
diff changeset
362 if (template_member_p)
kono
parents:
diff changeset
363 friend_type
kono
parents:
diff changeset
364 = make_unbound_class_template (ctype,
kono
parents:
diff changeset
365 name,
kono
parents:
diff changeset
366 current_template_parms,
kono
parents:
diff changeset
367 tf_error);
kono
parents:
diff changeset
368 else
kono
parents:
diff changeset
369 friend_type
kono
parents:
diff changeset
370 = make_typename_type (ctype, name, class_type, tf_error);
kono
parents:
diff changeset
371 }
kono
parents:
diff changeset
372 else
kono
parents:
diff changeset
373 {
kono
parents:
diff changeset
374 decl = lookup_member (ctype, name, 0, true, tf_warning_or_error);
kono
parents:
diff changeset
375 if (!decl)
kono
parents:
diff changeset
376 {
kono
parents:
diff changeset
377 error ("%qT is not a member of %qT", name, ctype);
kono
parents:
diff changeset
378 return;
kono
parents:
diff changeset
379 }
kono
parents:
diff changeset
380 if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
kono
parents:
diff changeset
381 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
382 auto_diagnostic_group d;
111
kono
parents:
diff changeset
383 error ("%qT is not a member class template of %qT",
kono
parents:
diff changeset
384 name, ctype);
kono
parents:
diff changeset
385 inform (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
386 "%qD declared here", decl);
kono
parents:
diff changeset
387 return;
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389 if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
kono
parents:
diff changeset
390 || !CLASS_TYPE_P (TREE_TYPE (decl))))
kono
parents:
diff changeset
391 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
392 auto_diagnostic_group d;
111
kono
parents:
diff changeset
393 error ("%qT is not a nested class of %qT",
kono
parents:
diff changeset
394 name, ctype);
kono
parents:
diff changeset
395 inform (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
396 "%qD declared here", decl);
kono
parents:
diff changeset
397 return;
kono
parents:
diff changeset
398 }
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
kono
parents:
diff changeset
401 }
kono
parents:
diff changeset
402 }
kono
parents:
diff changeset
403 }
kono
parents:
diff changeset
404 else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
kono
parents:
diff changeset
405 {
kono
parents:
diff changeset
406 /* template <class T> friend class T; */
kono
parents:
diff changeset
407 error ("template parameter type %qT declared %<friend%>", friend_type);
kono
parents:
diff changeset
408 return;
kono
parents:
diff changeset
409 }
kono
parents:
diff changeset
410 else if (TREE_CODE (friend_type) == TEMPLATE_TEMPLATE_PARM)
kono
parents:
diff changeset
411 friend_type = TYPE_NAME (friend_type);
kono
parents:
diff changeset
412 else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
kono
parents:
diff changeset
413 {
kono
parents:
diff changeset
414 /* template <class T> friend class A; where A is not a template */
kono
parents:
diff changeset
415 error ("%q#T is not a template", friend_type);
kono
parents:
diff changeset
416 return;
kono
parents:
diff changeset
417 }
kono
parents:
diff changeset
418 else
kono
parents:
diff changeset
419 /* template <class T> friend class A; where A is a template */
kono
parents:
diff changeset
420 friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
kono
parents:
diff changeset
421
kono
parents:
diff changeset
422 if (friend_type == error_mark_node)
kono
parents:
diff changeset
423 return;
kono
parents:
diff changeset
424
kono
parents:
diff changeset
425 /* See if it is already a friend. */
kono
parents:
diff changeset
426 for (classes = CLASSTYPE_FRIEND_CLASSES (type);
kono
parents:
diff changeset
427 classes;
kono
parents:
diff changeset
428 classes = TREE_CHAIN (classes))
kono
parents:
diff changeset
429 {
kono
parents:
diff changeset
430 tree probe = TREE_VALUE (classes);
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 if (TREE_CODE (friend_type) == TEMPLATE_DECL)
kono
parents:
diff changeset
433 {
kono
parents:
diff changeset
434 if (friend_type == probe)
kono
parents:
diff changeset
435 {
kono
parents:
diff changeset
436 if (complain)
kono
parents:
diff changeset
437 warning (OPT_Wredundant_decls,
kono
parents:
diff changeset
438 "%qD is already a friend of %qT", probe, type);
kono
parents:
diff changeset
439 break;
kono
parents:
diff changeset
440 }
kono
parents:
diff changeset
441 }
kono
parents:
diff changeset
442 else if (TREE_CODE (probe) != TEMPLATE_DECL)
kono
parents:
diff changeset
443 {
kono
parents:
diff changeset
444 if (same_type_p (probe, friend_type))
kono
parents:
diff changeset
445 {
kono
parents:
diff changeset
446 if (complain)
kono
parents:
diff changeset
447 warning (OPT_Wredundant_decls,
kono
parents:
diff changeset
448 "%qT is already a friend of %qT", probe, type);
kono
parents:
diff changeset
449 break;
kono
parents:
diff changeset
450 }
kono
parents:
diff changeset
451 }
kono
parents:
diff changeset
452 }
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 if (!classes)
kono
parents:
diff changeset
455 {
kono
parents:
diff changeset
456 maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 CLASSTYPE_FRIEND_CLASSES (type)
kono
parents:
diff changeset
459 = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
kono
parents:
diff changeset
460 if (TREE_CODE (friend_type) == TEMPLATE_DECL)
kono
parents:
diff changeset
461 friend_type = TREE_TYPE (friend_type);
kono
parents:
diff changeset
462 if (!uses_template_parms (type))
kono
parents:
diff changeset
463 CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
kono
parents:
diff changeset
464 = tree_cons (NULL_TREE, type,
kono
parents:
diff changeset
465 CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
kono
parents:
diff changeset
466 }
kono
parents:
diff changeset
467 }
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 /* Record DECL (a FUNCTION_DECL) as a friend of the
kono
parents:
diff changeset
470 CURRENT_CLASS_TYPE. If DECL is a member function, CTYPE is the
kono
parents:
diff changeset
471 class of which it is a member, as named in the friend declaration.
kono
parents:
diff changeset
472 DECLARATOR is the name of the friend. FUNCDEF_FLAG is true if the
kono
parents:
diff changeset
473 friend declaration is a definition of the function. FLAGS is as
kono
parents:
diff changeset
474 for grokclass fn. */
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 tree
kono
parents:
diff changeset
477 do_friend (tree ctype, tree declarator, tree decl,
kono
parents:
diff changeset
478 tree attrlist, enum overload_flags flags,
kono
parents:
diff changeset
479 bool funcdef_flag)
kono
parents:
diff changeset
480 {
kono
parents:
diff changeset
481 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
kono
parents:
diff changeset
482 gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 /* Every decl that gets here is a friend of something. */
kono
parents:
diff changeset
485 DECL_FRIEND_P (decl) = 1;
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl))
kono
parents:
diff changeset
488 error ("friend declaration %qD may not have virt-specifiers",
kono
parents:
diff changeset
489 decl);
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491 /* Unfortunately, we have to handle attributes here. Normally we would
kono
parents:
diff changeset
492 handle them in start_decl_1, but since this is a friend decl start_decl_1
kono
parents:
diff changeset
493 never gets to see it. */
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 /* Set attributes here so if duplicate decl, will have proper attributes. */
kono
parents:
diff changeset
496 cplus_decl_attributes (&decl, attrlist, 0);
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 declarator = TREE_OPERAND (declarator, 0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
501 if (!identifier_p (declarator))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
502 declarator = OVL_NAME (declarator);
111
kono
parents:
diff changeset
503 }
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 if (ctype)
kono
parents:
diff changeset
506 {
kono
parents:
diff changeset
507 /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
kono
parents:
diff changeset
508 the enclosing class. FRIEND_DEPTH counts the number of template
kono
parents:
diff changeset
509 headers used for this friend declaration. TEMPLATE_MEMBER_P is
kono
parents:
diff changeset
510 true if a template header in FRIEND_DEPTH is intended for
kono
parents:
diff changeset
511 DECLARATOR. For example, the code
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 template <class T> struct A {
kono
parents:
diff changeset
514 template <class U> struct B {
kono
parents:
diff changeset
515 template <class V> template <class W>
kono
parents:
diff changeset
516 friend void C<V>::f(W);
kono
parents:
diff changeset
517 };
kono
parents:
diff changeset
518 };
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 will eventually give the following results
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
kono
parents:
diff changeset
523 2. FRIEND_DEPTH equals 2 (for `V' and `W').
kono
parents:
diff changeset
524 3. TEMPLATE_MEMBER_P is true (for `W'). */
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 int class_template_depth = template_class_depth (current_class_type);
kono
parents:
diff changeset
527 int friend_depth = processing_template_decl - class_template_depth;
kono
parents:
diff changeset
528 /* We will figure this out later. */
kono
parents:
diff changeset
529 bool template_member_p = false;
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 tree cname = TYPE_NAME (ctype);
kono
parents:
diff changeset
532 if (TREE_CODE (cname) == TYPE_DECL)
kono
parents:
diff changeset
533 cname = DECL_NAME (cname);
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 /* A method friend. */
kono
parents:
diff changeset
536 if (flags == NO_SPECIAL && declarator == cname)
kono
parents:
diff changeset
537 DECL_CXX_CONSTRUCTOR_P (decl) = 1;
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 grokclassfn (ctype, decl, flags);
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 if (friend_depth)
kono
parents:
diff changeset
542 {
kono
parents:
diff changeset
543 if (!uses_template_parms_level (ctype, class_template_depth
kono
parents:
diff changeset
544 + friend_depth))
kono
parents:
diff changeset
545 template_member_p = true;
kono
parents:
diff changeset
546 }
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 /* A nested class may declare a member of an enclosing class
kono
parents:
diff changeset
549 to be a friend, so we do lookup here even if CTYPE is in
kono
parents:
diff changeset
550 the process of being defined. */
kono
parents:
diff changeset
551 if (class_template_depth
kono
parents:
diff changeset
552 || COMPLETE_OR_OPEN_TYPE_P (ctype))
kono
parents:
diff changeset
553 {
kono
parents:
diff changeset
554 if (DECL_TEMPLATE_INFO (decl))
kono
parents:
diff changeset
555 /* DECL is a template specialization. No need to
kono
parents:
diff changeset
556 build a new TEMPLATE_DECL. */
kono
parents:
diff changeset
557 ;
kono
parents:
diff changeset
558 else if (class_template_depth)
kono
parents:
diff changeset
559 /* We rely on tsubst_friend_function to check the
kono
parents:
diff changeset
560 validity of the declaration later. */
kono
parents:
diff changeset
561 decl = push_template_decl_real (decl, /*is_friend=*/true);
kono
parents:
diff changeset
562 else
kono
parents:
diff changeset
563 decl = check_classfn (ctype, decl,
kono
parents:
diff changeset
564 template_member_p
kono
parents:
diff changeset
565 ? current_template_parms
kono
parents:
diff changeset
566 : NULL_TREE);
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 if ((template_member_p
kono
parents:
diff changeset
569 /* Always pull out the TEMPLATE_DECL if we have a friend
kono
parents:
diff changeset
570 template in a class template so that it gets tsubsted
kono
parents:
diff changeset
571 properly later on (59956). tsubst_friend_function knows
kono
parents:
diff changeset
572 how to tell this apart from a member template. */
kono
parents:
diff changeset
573 || (class_template_depth && friend_depth))
kono
parents:
diff changeset
574 && decl && TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
575 decl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 if (decl)
kono
parents:
diff changeset
578 add_friend (current_class_type, decl, /*complain=*/true);
kono
parents:
diff changeset
579 }
kono
parents:
diff changeset
580 else
kono
parents:
diff changeset
581 error ("member %qD declared as friend before type %qT defined",
kono
parents:
diff changeset
582 decl, ctype);
kono
parents:
diff changeset
583 }
kono
parents:
diff changeset
584 /* A global friend.
kono
parents:
diff changeset
585 @@ or possibly a friend from a base class ?!? */
kono
parents:
diff changeset
586 else if (TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
587 {
kono
parents:
diff changeset
588 int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 /* Friends must all go through the overload machinery,
kono
parents:
diff changeset
591 even though they may not technically be overloaded.
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 Note that because classes all wind up being top-level
kono
parents:
diff changeset
594 in their scope, their friend wind up in top-level scope as well. */
kono
parents:
diff changeset
595 if (funcdef_flag)
kono
parents:
diff changeset
596 SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 if (! DECL_USE_TEMPLATE (decl))
kono
parents:
diff changeset
599 {
kono
parents:
diff changeset
600 /* We must check whether the decl refers to template
kono
parents:
diff changeset
601 arguments before push_template_decl_real adds a
kono
parents:
diff changeset
602 reference to the containing template class. */
kono
parents:
diff changeset
603 int warn = (warn_nontemplate_friend
kono
parents:
diff changeset
604 && ! funcdef_flag && ! is_friend_template
kono
parents:
diff changeset
605 && current_template_parms
kono
parents:
diff changeset
606 && uses_template_parms (decl));
kono
parents:
diff changeset
607
kono
parents:
diff changeset
608 if (is_friend_template
kono
parents:
diff changeset
609 || template_class_depth (current_class_type) != 0)
kono
parents:
diff changeset
610 /* We can't call pushdecl for a template class, since in
kono
parents:
diff changeset
611 general, such a declaration depends on template
kono
parents:
diff changeset
612 parameters. Instead, we call pushdecl when the class
kono
parents:
diff changeset
613 is instantiated. */
kono
parents:
diff changeset
614 decl = push_template_decl_real (decl, /*is_friend=*/true);
kono
parents:
diff changeset
615 else if (current_function_decl)
kono
parents:
diff changeset
616 /* pushdecl will check there's a local decl already. */
kono
parents:
diff changeset
617 decl = pushdecl (decl, /*is_friend=*/true);
kono
parents:
diff changeset
618 else
kono
parents:
diff changeset
619 {
kono
parents:
diff changeset
620 /* We can't use pushdecl, as we might be in a template
kono
parents:
diff changeset
621 class specialization, and pushdecl will insert an
kono
parents:
diff changeset
622 unqualified friend decl into the template parameter
kono
parents:
diff changeset
623 scope, rather than the namespace containing it. */
kono
parents:
diff changeset
624 tree ns = decl_namespace_context (decl);
kono
parents:
diff changeset
625
kono
parents:
diff changeset
626 push_nested_namespace (ns);
kono
parents:
diff changeset
627 decl = pushdecl_namespace_level (decl, /*is_friend=*/true);
kono
parents:
diff changeset
628 pop_nested_namespace (ns);
kono
parents:
diff changeset
629 }
kono
parents:
diff changeset
630
kono
parents:
diff changeset
631 if (warn)
kono
parents:
diff changeset
632 {
kono
parents:
diff changeset
633 static int explained;
kono
parents:
diff changeset
634 bool warned;
kono
parents:
diff changeset
635
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
636 auto_diagnostic_group d;
111
kono
parents:
diff changeset
637 warned = warning (OPT_Wnon_template_friend, "friend declaration "
kono
parents:
diff changeset
638 "%q#D declares a non-template function", decl);
kono
parents:
diff changeset
639 if (! explained && warned)
kono
parents:
diff changeset
640 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
641 inform (input_location, "(if this is not what you intended, "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
642 "make sure the function template has already been "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
643 "declared and add %<<>%> after the function name "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
644 "here)");
111
kono
parents:
diff changeset
645 explained = 1;
kono
parents:
diff changeset
646 }
kono
parents:
diff changeset
647 }
kono
parents:
diff changeset
648 }
kono
parents:
diff changeset
649
kono
parents:
diff changeset
650 if (decl == error_mark_node)
kono
parents:
diff changeset
651 return error_mark_node;
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 add_friend (current_class_type,
kono
parents:
diff changeset
654 is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
kono
parents:
diff changeset
655 /*complain=*/true);
kono
parents:
diff changeset
656 DECL_FRIEND_P (decl) = 1;
kono
parents:
diff changeset
657 }
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 return decl;
kono
parents:
diff changeset
660 }
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 #include "gt-cp-friend.h"