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