1 | /* Handle the hair of processing (but not expanding) inline functions. |
2 | Also manage function and variable name overloading. |
3 | Copyright (C) 1987-2024 Free Software Foundation, Inc. |
4 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
5 | |
6 | This file is part of GCC. |
7 | |
8 | GCC is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 3, or (at your option) |
11 | any later version. |
12 | |
13 | GCC is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ |
21 | |
22 | |
23 | /* Handle method declarations. */ |
24 | #include "config.h" |
25 | #include "system.h" |
26 | #include "coretypes.h" |
27 | #include "target.h" |
28 | #include "cp-tree.h" |
29 | #include "stringpool.h" |
30 | #include "cgraph.h" |
31 | #include "varasm.h" |
32 | #include "toplev.h" |
33 | #include "intl.h" |
34 | #include "common/common-target.h" |
35 | |
36 | static void do_build_copy_assign (tree); |
37 | static void do_build_copy_constructor (tree); |
38 | static tree make_alias_for_thunk (tree); |
39 | |
40 | /* Called once to initialize method.cc. */ |
41 | |
42 | void |
43 | init_method (void) |
44 | { |
45 | init_mangle (); |
46 | } |
47 | |
48 | /* Return a this or result adjusting thunk to FUNCTION. THIS_ADJUSTING |
49 | indicates whether it is a this or result adjusting thunk. |
50 | FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment |
51 | (see thunk_adjust). VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET |
52 | never is. VIRTUAL_OFFSET is the /index/ into the vtable for this |
53 | adjusting thunks, we scale it to a byte offset. For covariant |
54 | thunks VIRTUAL_OFFSET is the virtual binfo. You must post process |
55 | the returned thunk with finish_thunk. */ |
56 | |
57 | tree |
58 | make_thunk (tree function, bool this_adjusting, |
59 | tree fixed_offset, tree virtual_offset) |
60 | { |
61 | HOST_WIDE_INT d; |
62 | tree thunk; |
63 | |
64 | gcc_assert (TREE_CODE (function) == FUNCTION_DECL); |
65 | /* We can have this thunks to covariant thunks, but not vice versa. */ |
66 | gcc_assert (!DECL_THIS_THUNK_P (function)); |
67 | gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting); |
68 | |
69 | /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */ |
70 | if (this_adjusting && virtual_offset) |
71 | virtual_offset |
72 | = size_binop (MULT_EXPR, |
73 | virtual_offset, |
74 | convert (ssizetype, |
75 | TYPE_SIZE_UNIT (vtable_entry_type))); |
76 | |
77 | d = tree_to_shwi (fixed_offset); |
78 | |
79 | /* See if we already have the thunk in question. For this_adjusting |
80 | thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it |
81 | will be a BINFO. */ |
82 | for (thunk = DECL_THUNKS (function); thunk; thunk = DECL_CHAIN (thunk)) |
83 | if (DECL_THIS_THUNK_P (thunk) == this_adjusting |
84 | && THUNK_FIXED_OFFSET (thunk) == d |
85 | && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk) |
86 | && (!virtual_offset |
87 | || (this_adjusting |
88 | ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk), |
89 | virtual_offset) |
90 | : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset))) |
91 | return thunk; |
92 | |
93 | /* All thunks must be created before FUNCTION is actually emitted; |
94 | the ABI requires that all thunks be emitted together with the |
95 | function to which they transfer control. */ |
96 | gcc_assert (!TREE_ASM_WRITTEN (function)); |
97 | /* Likewise, we can only be adding thunks to a function declared in |
98 | the class currently being laid out. */ |
99 | gcc_assert (TYPE_SIZE (DECL_CONTEXT (function)) |
100 | && TYPE_BEING_DEFINED (DECL_CONTEXT (function))); |
101 | |
102 | thunk = build_decl (DECL_SOURCE_LOCATION (function), |
103 | FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); |
104 | DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); |
105 | cxx_dup_lang_specific_decl (thunk); |
106 | DECL_VIRTUAL_P (thunk) = true; |
107 | SET_DECL_THUNKS (thunk, NULL_TREE); |
108 | |
109 | DECL_CONTEXT (thunk) = DECL_CONTEXT (function); |
110 | TREE_READONLY (thunk) = TREE_READONLY (function); |
111 | TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function); |
112 | TREE_PUBLIC (thunk) = TREE_PUBLIC (function); |
113 | SET_DECL_THUNK_P (thunk, this_adjusting); |
114 | THUNK_TARGET (thunk) = function; |
115 | THUNK_FIXED_OFFSET (thunk) = d; |
116 | THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset; |
117 | THUNK_ALIAS (thunk) = NULL_TREE; |
118 | |
119 | DECL_INTERFACE_KNOWN (thunk) = 1; |
120 | DECL_NOT_REALLY_EXTERN (thunk) = 1; |
121 | DECL_COMDAT (thunk) = DECL_COMDAT (function); |
122 | DECL_SAVED_AUTO_RETURN_TYPE (thunk) = NULL; |
123 | /* The thunk itself is not a constructor or destructor, even if |
124 | the thing it is thunking to is. */ |
125 | DECL_CXX_DESTRUCTOR_P (thunk) = 0; |
126 | DECL_CXX_CONSTRUCTOR_P (thunk) = 0; |
127 | DECL_EXTERNAL (thunk) = 1; |
128 | DECL_ARTIFICIAL (thunk) = 1; |
129 | /* The THUNK is not a pending inline, even if the FUNCTION is. */ |
130 | DECL_PENDING_INLINE_P (thunk) = 0; |
131 | DECL_DECLARED_INLINE_P (thunk) = 0; |
132 | /* Nor is it a template instantiation. */ |
133 | DECL_USE_TEMPLATE (thunk) = 0; |
134 | DECL_TEMPLATE_INFO (thunk) = NULL; |
135 | |
136 | /* Add it to the list of thunks associated with FUNCTION. */ |
137 | DECL_CHAIN (thunk) = DECL_THUNKS (function); |
138 | SET_DECL_THUNKS (function, thunk); |
139 | |
140 | return thunk; |
141 | } |
142 | |
143 | /* Finish THUNK, a thunk decl. */ |
144 | |
145 | void |
146 | finish_thunk (tree thunk) |
147 | { |
148 | tree function, name; |
149 | tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk)); |
150 | tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk); |
151 | |
152 | gcc_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk)); |
153 | if (virtual_offset && DECL_RESULT_THUNK_P (thunk)) |
154 | virtual_offset = BINFO_VPTR_FIELD (virtual_offset); |
155 | function = THUNK_TARGET (thunk); |
156 | name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk), |
157 | fixed_offset, virtual_offset, thunk); |
158 | |
159 | /* We can end up with declarations of (logically) different |
160 | covariant thunks, that do identical adjustments. The two thunks |
161 | will be adjusting between within different hierarchies, which |
162 | happen to have the same layout. We must nullify one of them to |
163 | refer to the other. */ |
164 | if (DECL_RESULT_THUNK_P (thunk)) |
165 | { |
166 | tree cov_probe; |
167 | |
168 | for (cov_probe = DECL_THUNKS (function); |
169 | cov_probe; cov_probe = DECL_CHAIN (cov_probe)) |
170 | if (DECL_NAME (cov_probe) == name) |
171 | { |
172 | gcc_assert (!DECL_THUNKS (thunk)); |
173 | THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe) |
174 | ? THUNK_ALIAS (cov_probe) : cov_probe); |
175 | break; |
176 | } |
177 | } |
178 | |
179 | DECL_NAME (thunk) = name; |
180 | SET_DECL_ASSEMBLER_NAME (thunk, name); |
181 | } |
182 | |
183 | static GTY (()) int thunk_labelno; |
184 | |
185 | /* Create a static alias to target. */ |
186 | |
187 | tree |
188 | make_alias_for (tree target, tree newid) |
189 | { |
190 | tree alias = build_decl (DECL_SOURCE_LOCATION (target), |
191 | TREE_CODE (target), newid, TREE_TYPE (target)); |
192 | DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (target); |
193 | cxx_dup_lang_specific_decl (alias); |
194 | DECL_CONTEXT (alias) = DECL_CONTEXT (target); |
195 | TREE_READONLY (alias) = TREE_READONLY (target); |
196 | TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (target); |
197 | TREE_PUBLIC (alias) = 0; |
198 | DECL_INTERFACE_KNOWN (alias) = 1; |
199 | if (DECL_LANG_SPECIFIC (alias)) |
200 | { |
201 | DECL_NOT_REALLY_EXTERN (alias) = 1; |
202 | DECL_USE_TEMPLATE (alias) = 0; |
203 | DECL_TEMPLATE_INFO (alias) = NULL; |
204 | } |
205 | DECL_EXTERNAL (alias) = 0; |
206 | DECL_ARTIFICIAL (alias) = 1; |
207 | DECL_TEMPLATE_INSTANTIATED (alias) = 0; |
208 | if (TREE_CODE (alias) == FUNCTION_DECL) |
209 | { |
210 | DECL_SAVED_AUTO_RETURN_TYPE (alias) = NULL; |
211 | DECL_CXX_DESTRUCTOR_P (alias) = 0; |
212 | DECL_CXX_CONSTRUCTOR_P (alias) = 0; |
213 | DECL_PENDING_INLINE_P (alias) = 0; |
214 | DECL_DECLARED_INLINE_P (alias) = 0; |
215 | DECL_INITIAL (alias) = error_mark_node; |
216 | DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (target)); |
217 | } |
218 | else |
219 | TREE_STATIC (alias) = 1; |
220 | TREE_ADDRESSABLE (alias) = 1; |
221 | TREE_USED (alias) = 1; |
222 | SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); |
223 | return alias; |
224 | } |
225 | |
226 | static tree |
227 | make_alias_for_thunk (tree function) |
228 | { |
229 | tree alias; |
230 | char buf[256]; |
231 | |
232 | targetm.asm_out.generate_internal_label (buf, "LTHUNK" , thunk_labelno); |
233 | thunk_labelno++; |
234 | |
235 | alias = make_alias_for (target: function, get_identifier (buf)); |
236 | |
237 | if (!flag_syntax_only) |
238 | { |
239 | struct cgraph_node *funcn, *aliasn; |
240 | funcn = cgraph_node::get (decl: function); |
241 | gcc_checking_assert (funcn); |
242 | aliasn = cgraph_node::create_same_body_alias (alias, decl: function); |
243 | DECL_ASSEMBLER_NAME (function); |
244 | gcc_assert (aliasn != NULL); |
245 | } |
246 | |
247 | return alias; |
248 | } |
249 | |
250 | /* Emit the definition of a C++ multiple inheritance or covariant |
251 | return vtable thunk. If EMIT_P is nonzero, the thunk is emitted |
252 | immediately. */ |
253 | |
254 | void |
255 | use_thunk (tree thunk_fndecl, bool emit_p) |
256 | { |
257 | tree a, t, function, alias; |
258 | tree virtual_offset; |
259 | HOST_WIDE_INT fixed_offset, virtual_value; |
260 | bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); |
261 | struct cgraph_node *funcn, *thunk_node; |
262 | |
263 | /* We should have called finish_thunk to give it a name. */ |
264 | gcc_assert (DECL_NAME (thunk_fndecl)); |
265 | |
266 | /* We should never be using an alias, always refer to the |
267 | aliased thunk. */ |
268 | gcc_assert (!THUNK_ALIAS (thunk_fndecl)); |
269 | |
270 | if (TREE_ASM_WRITTEN (thunk_fndecl)) |
271 | return; |
272 | |
273 | function = THUNK_TARGET (thunk_fndecl); |
274 | if (DECL_RESULT (thunk_fndecl)) |
275 | /* We already turned this thunk into an ordinary function. |
276 | There's no need to process this thunk again. */ |
277 | return; |
278 | |
279 | if (DECL_THUNK_P (function)) |
280 | /* The target is itself a thunk, process it now. */ |
281 | use_thunk (thunk_fndecl: function, emit_p); |
282 | |
283 | /* Thunks are always addressable; they only appear in vtables. */ |
284 | TREE_ADDRESSABLE (thunk_fndecl) = 1; |
285 | |
286 | /* Figure out what function is being thunked to. It's referenced in |
287 | this translation unit. */ |
288 | TREE_ADDRESSABLE (function) = 1; |
289 | mark_used (function); |
290 | if (!emit_p) |
291 | return; |
292 | |
293 | if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)) |
294 | alias = make_alias_for_thunk (function); |
295 | else |
296 | alias = function; |
297 | |
298 | fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); |
299 | virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); |
300 | |
301 | if (virtual_offset) |
302 | { |
303 | if (!this_adjusting) |
304 | virtual_offset = BINFO_VPTR_FIELD (virtual_offset); |
305 | virtual_value = tree_to_shwi (virtual_offset); |
306 | gcc_assert (virtual_value); |
307 | } |
308 | else |
309 | virtual_value = 0; |
310 | |
311 | /* And, if we need to emit the thunk, it's used. */ |
312 | mark_used (thunk_fndecl); |
313 | /* This thunk is actually defined. */ |
314 | DECL_EXTERNAL (thunk_fndecl) = 0; |
315 | /* The linkage of the function may have changed. FIXME in linkage |
316 | rewrite. */ |
317 | gcc_assert (DECL_INTERFACE_KNOWN (function)); |
318 | TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); |
319 | DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); |
320 | DECL_VISIBILITY_SPECIFIED (thunk_fndecl) |
321 | = DECL_VISIBILITY_SPECIFIED (function); |
322 | DECL_COMDAT (thunk_fndecl) = DECL_COMDAT (function); |
323 | DECL_WEAK (thunk_fndecl) = DECL_WEAK (function); |
324 | |
325 | if (flag_syntax_only) |
326 | { |
327 | TREE_ASM_WRITTEN (thunk_fndecl) = 1; |
328 | return; |
329 | } |
330 | |
331 | push_to_top_level (); |
332 | |
333 | if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) |
334 | && targetm_common.have_named_sections) |
335 | { |
336 | tree fn = function; |
337 | struct symtab_node *symbol; |
338 | |
339 | if ((symbol = symtab_node::get (decl: function)) |
340 | && symbol->alias) |
341 | { |
342 | if (symbol->analyzed) |
343 | fn = symtab_node::get (decl: function)->ultimate_alias_target ()->decl; |
344 | else |
345 | fn = symtab_node::get (decl: function)->alias_target; |
346 | } |
347 | resolve_unique_section (fn, 0, flag_function_sections); |
348 | |
349 | if (DECL_SECTION_NAME (fn) != NULL && DECL_ONE_ONLY (fn)) |
350 | { |
351 | resolve_unique_section (thunk_fndecl, 0, flag_function_sections); |
352 | |
353 | /* Output the thunk into the same section as function. */ |
354 | set_decl_section_name (thunk_fndecl, fn); |
355 | symtab_node::get (decl: thunk_fndecl)->implicit_section |
356 | = symtab_node::get (decl: fn)->implicit_section; |
357 | } |
358 | } |
359 | |
360 | /* Set up cloned argument trees for the thunk. */ |
361 | t = NULL_TREE; |
362 | for (a = DECL_ARGUMENTS (function); a; a = DECL_CHAIN (a)) |
363 | { |
364 | tree x = copy_node (a); |
365 | DECL_CHAIN (x) = t; |
366 | DECL_CONTEXT (x) = thunk_fndecl; |
367 | SET_DECL_RTL (x, NULL); |
368 | DECL_HAS_VALUE_EXPR_P (x) = 0; |
369 | TREE_ADDRESSABLE (x) = 0; |
370 | t = x; |
371 | } |
372 | a = nreverse (t); |
373 | DECL_ARGUMENTS (thunk_fndecl) = a; |
374 | TREE_ASM_WRITTEN (thunk_fndecl) = 1; |
375 | funcn = cgraph_node::get (decl: function); |
376 | gcc_checking_assert (funcn); |
377 | thunk_node = funcn->create_thunk (alias: thunk_fndecl, function, |
378 | this_adjusting, fixed_offset, virtual_value, |
379 | indirect_offset: 0, virtual_offset, real_alias: alias); |
380 | if (DECL_ONE_ONLY (function)) |
381 | thunk_node->add_to_same_comdat_group (old_node: funcn); |
382 | |
383 | pop_from_top_level (); |
384 | } |
385 | |
386 | /* Code for synthesizing methods which have default semantics defined. */ |
387 | |
388 | /* True iff CTYPE has a trivial SFK. */ |
389 | |
390 | static bool |
391 | type_has_trivial_fn (tree ctype, special_function_kind sfk) |
392 | { |
393 | switch (sfk) |
394 | { |
395 | case sfk_constructor: |
396 | return !TYPE_HAS_COMPLEX_DFLT (ctype); |
397 | case sfk_copy_constructor: |
398 | return !TYPE_HAS_COMPLEX_COPY_CTOR (ctype); |
399 | case sfk_move_constructor: |
400 | return !TYPE_HAS_COMPLEX_MOVE_CTOR (ctype); |
401 | case sfk_copy_assignment: |
402 | return !TYPE_HAS_COMPLEX_COPY_ASSIGN (ctype); |
403 | case sfk_move_assignment: |
404 | return !TYPE_HAS_COMPLEX_MOVE_ASSIGN (ctype); |
405 | case sfk_destructor: |
406 | case sfk_virtual_destructor: |
407 | return !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype); |
408 | case sfk_inheriting_constructor: |
409 | case sfk_comparison: |
410 | return false; |
411 | default: |
412 | gcc_unreachable (); |
413 | } |
414 | } |
415 | |
416 | /* Note that CTYPE has a non-trivial SFK even though we previously thought |
417 | it was trivial. */ |
418 | |
419 | static void |
420 | type_set_nontrivial_flag (tree ctype, special_function_kind sfk) |
421 | { |
422 | switch (sfk) |
423 | { |
424 | case sfk_constructor: |
425 | TYPE_HAS_COMPLEX_DFLT (ctype) = true; |
426 | return; |
427 | case sfk_copy_constructor: |
428 | TYPE_HAS_COMPLEX_COPY_CTOR (ctype) = true; |
429 | return; |
430 | case sfk_move_constructor: |
431 | TYPE_HAS_COMPLEX_MOVE_CTOR (ctype) = true; |
432 | return; |
433 | case sfk_copy_assignment: |
434 | TYPE_HAS_COMPLEX_COPY_ASSIGN (ctype) = true; |
435 | return; |
436 | case sfk_move_assignment: |
437 | TYPE_HAS_COMPLEX_MOVE_ASSIGN (ctype) = true; |
438 | return; |
439 | case sfk_destructor: |
440 | TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true; |
441 | return; |
442 | case sfk_inheriting_constructor: |
443 | default: |
444 | gcc_unreachable (); |
445 | } |
446 | } |
447 | |
448 | /* True iff FN is a trivial defaulted member function ([cd]tor, op=). */ |
449 | |
450 | bool |
451 | trivial_fn_p (tree fn) |
452 | { |
453 | if (TREE_CODE (fn) == TEMPLATE_DECL) |
454 | return false; |
455 | if (!DECL_DEFAULTED_FN (fn)) |
456 | return false; |
457 | |
458 | /* If fn is a clone, get the primary variant. */ |
459 | if (tree prim = DECL_CLONED_FUNCTION (fn)) |
460 | fn = prim; |
461 | return type_has_trivial_fn (DECL_CONTEXT (fn), sfk: special_function_p (fn)); |
462 | } |
463 | |
464 | /* PARM is a PARM_DECL for a function which we want to forward to another |
465 | function without changing its value category, a la std::forward. */ |
466 | |
467 | tree |
468 | forward_parm (tree parm) |
469 | { |
470 | tree exp = convert_from_reference (parm); |
471 | tree type = TREE_TYPE (parm); |
472 | if (DECL_PACK_P (parm)) |
473 | type = PACK_EXPANSION_PATTERN (type); |
474 | if (!TYPE_REF_P (type)) |
475 | type = cp_build_reference_type (type, /*rval=*/true); |
476 | warning_sentinel w (warn_useless_cast); |
477 | exp = build_static_cast (input_location, type, exp, |
478 | tf_warning_or_error); |
479 | if (DECL_PACK_P (parm)) |
480 | exp = make_pack_expansion (exp); |
481 | return exp; |
482 | } |
483 | |
484 | /* Strip all inheriting constructors, if any, to return the original |
485 | constructor from a (possibly indirect) base class. */ |
486 | |
487 | tree |
488 | strip_inheriting_ctors (tree dfn) |
489 | { |
490 | if (!flag_new_inheriting_ctors) |
491 | return dfn; |
492 | tree fn = dfn; |
493 | while (tree inh = DECL_INHERITED_CTOR (fn)) |
494 | fn = OVL_FIRST (inh); |
495 | |
496 | if (TREE_CODE (fn) == TEMPLATE_DECL |
497 | && TREE_CODE (dfn) == FUNCTION_DECL) |
498 | fn = DECL_TEMPLATE_RESULT (fn); |
499 | return fn; |
500 | } |
501 | |
502 | /* Find the binfo for the base subobject of BINFO being initialized by |
503 | inherited constructor FNDECL (a member of a direct base of BINFO). */ |
504 | |
505 | static tree inherited_ctor_binfo (tree, tree); |
506 | static tree |
507 | inherited_ctor_binfo_1 (tree binfo, tree fndecl) |
508 | { |
509 | tree base = DECL_CONTEXT (fndecl); |
510 | tree base_binfo; |
511 | for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) |
512 | if (BINFO_TYPE (base_binfo) == base) |
513 | return inherited_ctor_binfo (base_binfo, fndecl); |
514 | |
515 | gcc_unreachable(); |
516 | } |
517 | |
518 | /* Find the binfo for the base subobject of BINFO being initialized by |
519 | inheriting constructor FNDECL (a member of BINFO), or BINFO if FNDECL is not |
520 | an inheriting constructor. */ |
521 | |
522 | static tree |
523 | inherited_ctor_binfo (tree binfo, tree fndecl) |
524 | { |
525 | tree inh = DECL_INHERITED_CTOR (fndecl); |
526 | if (!inh) |
527 | return binfo; |
528 | |
529 | tree results = NULL_TREE; |
530 | for (ovl_iterator iter (inh); iter; ++iter) |
531 | { |
532 | tree one = inherited_ctor_binfo_1 (binfo, fndecl: *iter); |
533 | if (!results) |
534 | results = one; |
535 | else if (one != results) |
536 | results = tree_cons (NULL_TREE, one, results); |
537 | } |
538 | return results; |
539 | } |
540 | |
541 | /* Find the binfo for the base subobject being initialized by inheriting |
542 | constructor FNDECL, or NULL_TREE if FNDECL is not an inheriting |
543 | constructor. */ |
544 | |
545 | tree |
546 | inherited_ctor_binfo (tree fndecl) |
547 | { |
548 | if (!DECL_INHERITED_CTOR (fndecl)) |
549 | return NULL_TREE; |
550 | tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl)); |
551 | return inherited_ctor_binfo (binfo, fndecl); |
552 | } |
553 | |
554 | |
555 | /* True if we should omit all user-declared parameters from a base |
556 | construtor built from complete constructor FN. |
557 | That's when the ctor is inherited from a virtual base. */ |
558 | |
559 | bool |
560 | base_ctor_omit_inherited_parms (tree comp_ctor) |
561 | { |
562 | gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (comp_ctor)); |
563 | |
564 | if (!flag_new_inheriting_ctors) |
565 | /* We only optimize away the parameters in the new model. */ |
566 | return false; |
567 | |
568 | if (!CLASSTYPE_VBASECLASSES (DECL_CONTEXT (comp_ctor))) |
569 | return false; |
570 | |
571 | if (FUNCTION_FIRST_USER_PARMTYPE (comp_ctor) == void_list_node) |
572 | /* No user-declared parameters to omit. */ |
573 | return false; |
574 | |
575 | for (tree binfo = inherited_ctor_binfo (fndecl: comp_ctor); |
576 | binfo; |
577 | binfo = BINFO_INHERITANCE_CHAIN (binfo)) |
578 | if (BINFO_VIRTUAL_P (binfo)) |
579 | return true; |
580 | |
581 | return false; |
582 | } |
583 | |
584 | |
585 | /* True if we should omit all user-declared parameters from constructor FN, |
586 | because it is a base clone of a ctor inherited from a virtual base. */ |
587 | |
588 | bool |
589 | ctor_omit_inherited_parms (tree fn) |
590 | { |
591 | gcc_checking_assert (TREE_CODE (fn) == FUNCTION_DECL); |
592 | |
593 | if (!DECL_BASE_CONSTRUCTOR_P (fn)) |
594 | return false; |
595 | |
596 | return base_ctor_omit_inherited_parms (DECL_CLONED_FUNCTION (fn)); |
597 | } |
598 | |
599 | /* True iff constructor(s) INH inherited into BINFO initializes INIT_BINFO. |
600 | This can be true for multiple virtual bases as well as one direct |
601 | non-virtual base. */ |
602 | |
603 | static bool |
604 | binfo_inherited_from (tree binfo, tree init_binfo, tree inh) |
605 | { |
606 | /* inh is an OVERLOAD if we inherited the same constructor along |
607 | multiple paths, check all of them. */ |
608 | for (ovl_iterator iter (inh); iter; ++iter) |
609 | { |
610 | tree fn = *iter; |
611 | tree base = DECL_CONTEXT (fn); |
612 | tree base_binfo = NULL_TREE; |
613 | for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) |
614 | if (BINFO_TYPE (base_binfo) == base) |
615 | break; |
616 | if (base_binfo == init_binfo |
617 | || (flag_new_inheriting_ctors |
618 | && binfo_inherited_from (binfo: base_binfo, init_binfo, |
619 | DECL_INHERITED_CTOR (fn)))) |
620 | return true; |
621 | } |
622 | return false; |
623 | } |
624 | |
625 | /* Subroutine of do_build_copy_constructor: Add a mem-initializer for BINFO |
626 | given the parameter or parameters PARM, possibly inherited constructor |
627 | base INH, or move flag MOVE_P. */ |
628 | |
629 | static tree |
630 | add_one_base_init (tree binfo, tree parm, bool move_p, tree inh, |
631 | tree member_init_list) |
632 | { |
633 | tree init; |
634 | if (inh) |
635 | { |
636 | /* An inheriting constructor only has a mem-initializer for |
637 | the base it inherits from. */ |
638 | if (!binfo_inherited_from (TYPE_BINFO (current_class_type), init_binfo: binfo, inh)) |
639 | return member_init_list; |
640 | |
641 | tree *p = &init; |
642 | init = NULL_TREE; |
643 | for (; parm; parm = DECL_CHAIN (parm)) |
644 | { |
645 | tree exp = forward_parm (parm); |
646 | *p = build_tree_list (NULL_TREE, exp); |
647 | p = &TREE_CHAIN (*p); |
648 | } |
649 | } |
650 | else |
651 | { |
652 | init = build_base_path (PLUS_EXPR, parm, binfo, 1, |
653 | tf_warning_or_error); |
654 | if (move_p) |
655 | init = move (init); |
656 | init = build_tree_list (NULL_TREE, init); |
657 | } |
658 | return tree_cons (binfo, init, member_init_list); |
659 | } |
660 | |
661 | /* Generate code for default X(X&) or X(X&&) constructor or an inheriting |
662 | constructor. */ |
663 | |
664 | static void |
665 | do_build_copy_constructor (tree fndecl) |
666 | { |
667 | tree parm = FUNCTION_FIRST_USER_PARM (fndecl); |
668 | bool move_p = DECL_MOVE_CONSTRUCTOR_P (fndecl); |
669 | bool trivial = trivial_fn_p (fn: fndecl); |
670 | tree inh = DECL_INHERITED_CTOR (fndecl); |
671 | |
672 | if (!inh) |
673 | parm = convert_from_reference (parm); |
674 | |
675 | if (trivial) |
676 | { |
677 | if (is_empty_class (current_class_type)) |
678 | /* Don't copy the padding byte; it might not have been allocated |
679 | if *this is a base subobject. */; |
680 | else if (tree_int_cst_equal (TYPE_SIZE (current_class_type), |
681 | CLASSTYPE_SIZE (current_class_type))) |
682 | { |
683 | tree t = cp_build_init_expr (current_class_ref, i: parm); |
684 | finish_expr_stmt (t); |
685 | } |
686 | else |
687 | { |
688 | /* We must only copy the non-tail padding parts. */ |
689 | tree base_size = CLASSTYPE_SIZE_UNIT (current_class_type); |
690 | base_size = size_binop (MINUS_EXPR, base_size, size_int (1)); |
691 | tree array_type = build_array_type (unsigned_char_type_node, |
692 | build_index_type (base_size)); |
693 | tree alias_set = build_int_cst (TREE_TYPE (current_class_ptr), 0); |
694 | tree lhs = build2 (MEM_REF, array_type, |
695 | current_class_ptr, alias_set); |
696 | tree rhs = build2 (MEM_REF, array_type, |
697 | TREE_OPERAND (parm, 0), alias_set); |
698 | tree t = cp_build_init_expr (t: lhs, i: rhs); |
699 | finish_expr_stmt (t); |
700 | } |
701 | } |
702 | else |
703 | { |
704 | tree member_init_list = NULL_TREE; |
705 | int i; |
706 | tree binfo, base_binfo; |
707 | vec<tree, va_gc> *vbases; |
708 | |
709 | /* Initialize all the base-classes with the parameter converted |
710 | to their type so that we get their copy constructor and not |
711 | another constructor that takes current_class_type. We must |
712 | deal with the binfo's directly as a direct base might be |
713 | inaccessible due to ambiguity. */ |
714 | for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; |
715 | vec_safe_iterate (v: vbases, ix: i, ptr: &binfo); i++) |
716 | { |
717 | member_init_list = add_one_base_init (binfo, parm, move_p, inh, |
718 | member_init_list); |
719 | } |
720 | |
721 | for (binfo = TYPE_BINFO (current_class_type), i = 0; |
722 | BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) |
723 | { |
724 | if (BINFO_VIRTUAL_P (base_binfo)) |
725 | continue; |
726 | member_init_list = add_one_base_init (binfo: base_binfo, parm, move_p, |
727 | inh, member_init_list); |
728 | } |
729 | |
730 | if (!inh) |
731 | { |
732 | int cvquals = cp_type_quals (TREE_TYPE (parm)); |
733 | |
734 | for (tree fields = TYPE_FIELDS (current_class_type); |
735 | fields; fields = DECL_CHAIN (fields)) |
736 | { |
737 | tree field = fields; |
738 | tree expr_type; |
739 | |
740 | if (TREE_CODE (field) != FIELD_DECL) |
741 | continue; |
742 | |
743 | expr_type = TREE_TYPE (field); |
744 | if (DECL_NAME (field)) |
745 | { |
746 | if (VFIELD_NAME_P (DECL_NAME (field))) |
747 | continue; |
748 | } |
749 | else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type)) |
750 | /* Just use the field; anonymous types can't have |
751 | nontrivial copy ctors or assignment ops or this |
752 | function would be deleted. */; |
753 | else |
754 | continue; |
755 | |
756 | /* Compute the type of "init->field". If the copy-constructor |
757 | parameter is, for example, "const S&", and the type of |
758 | the field is "T", then the type will usually be "const |
759 | T". (There are no cv-qualified variants of reference |
760 | types.) */ |
761 | if (!TYPE_REF_P (expr_type)) |
762 | { |
763 | int quals = cvquals; |
764 | |
765 | if (DECL_MUTABLE_P (field)) |
766 | quals &= ~TYPE_QUAL_CONST; |
767 | quals |= cp_type_quals (expr_type); |
768 | expr_type = cp_build_qualified_type (expr_type, quals); |
769 | } |
770 | |
771 | tree init = build3 (COMPONENT_REF, expr_type, parm, field, NULL_TREE); |
772 | if (move_p && !TYPE_REF_P (expr_type) |
773 | /* 'move' breaks bit-fields, and has no effect for scalars. */ |
774 | && !scalarish_type_p (expr_type)) |
775 | init = move (init); |
776 | init = build_tree_list (NULL_TREE, init); |
777 | |
778 | member_init_list = tree_cons (field, init, member_init_list); |
779 | } |
780 | } |
781 | |
782 | finish_mem_initializers (member_init_list); |
783 | } |
784 | } |
785 | |
786 | static void |
787 | do_build_copy_assign (tree fndecl) |
788 | { |
789 | tree parm = DECL_CHAIN (DECL_ARGUMENTS (fndecl)); |
790 | tree compound_stmt; |
791 | bool move_p = move_fn_p (fndecl); |
792 | bool trivial = trivial_fn_p (fn: fndecl); |
793 | int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED; |
794 | |
795 | compound_stmt = begin_compound_stmt (0); |
796 | parm = convert_from_reference (parm); |
797 | |
798 | /* If we are building a defaulted xobj copy/move assignment operator then |
799 | current_class_ref will not have been set up. |
800 | Kind of an icky hack, but what can ya do? */ |
801 | tree const class_ref = DECL_XOBJ_MEMBER_FUNCTION_P (fndecl) |
802 | ? cp_build_fold_indirect_ref (DECL_ARGUMENTS (fndecl)) : current_class_ref; |
803 | |
804 | if (trivial |
805 | && is_empty_class (current_class_type)) |
806 | /* Don't copy the padding byte; it might not have been allocated |
807 | if *this is a base subobject. */; |
808 | else if (trivial) |
809 | { |
810 | tree t = build2 (MODIFY_EXPR, void_type_node, class_ref, parm); |
811 | finish_expr_stmt (t); |
812 | } |
813 | else |
814 | { |
815 | tree fields; |
816 | int cvquals = cp_type_quals (TREE_TYPE (parm)); |
817 | int i; |
818 | tree binfo, base_binfo; |
819 | |
820 | /* Assign to each of the direct base classes. */ |
821 | for (binfo = TYPE_BINFO (current_class_type), i = 0; |
822 | BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) |
823 | { |
824 | tree converted_parm; |
825 | |
826 | /* We must convert PARM directly to the base class |
827 | explicitly since the base class may be ambiguous. */ |
828 | converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1, |
829 | tf_warning_or_error); |
830 | if (move_p) |
831 | converted_parm = move (converted_parm); |
832 | /* Call the base class assignment operator. */ |
833 | releasing_vec parmvec (make_tree_vector_single (converted_parm)); |
834 | finish_expr_stmt |
835 | (build_special_member_call (class_ref, |
836 | assign_op_identifier, |
837 | &parmvec, |
838 | base_binfo, |
839 | flags, |
840 | tf_warning_or_error)); |
841 | } |
842 | |
843 | /* Assign to each of the non-static data members. */ |
844 | for (fields = TYPE_FIELDS (current_class_type); |
845 | fields; |
846 | fields = DECL_CHAIN (fields)) |
847 | { |
848 | tree comp = class_ref; |
849 | tree init = parm; |
850 | tree field = fields; |
851 | tree expr_type; |
852 | int quals; |
853 | |
854 | if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) |
855 | continue; |
856 | |
857 | expr_type = TREE_TYPE (field); |
858 | |
859 | if (CP_TYPE_CONST_P (expr_type)) |
860 | { |
861 | error ("non-static const member %q#D, cannot use default " |
862 | "assignment operator" , field); |
863 | continue; |
864 | } |
865 | else if (TYPE_REF_P (expr_type)) |
866 | { |
867 | error ("non-static reference member %q#D, cannot use " |
868 | "default assignment operator" , field); |
869 | continue; |
870 | } |
871 | |
872 | if (DECL_NAME (field)) |
873 | { |
874 | if (VFIELD_NAME_P (DECL_NAME (field))) |
875 | continue; |
876 | } |
877 | else if (ANON_AGGR_TYPE_P (expr_type) |
878 | && TYPE_FIELDS (expr_type) != NULL_TREE) |
879 | /* Just use the field; anonymous types can't have |
880 | nontrivial copy ctors or assignment ops or this |
881 | function would be deleted. */; |
882 | else |
883 | continue; |
884 | |
885 | comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE); |
886 | |
887 | /* Compute the type of init->field */ |
888 | quals = cvquals; |
889 | if (DECL_MUTABLE_P (field)) |
890 | quals &= ~TYPE_QUAL_CONST; |
891 | expr_type = cp_build_qualified_type (expr_type, quals); |
892 | |
893 | init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); |
894 | if (move_p && !TYPE_REF_P (expr_type) |
895 | /* 'move' breaks bit-fields, and has no effect for scalars. */ |
896 | && !scalarish_type_p (expr_type)) |
897 | init = move (init); |
898 | |
899 | if (DECL_NAME (field)) |
900 | init = cp_build_modify_expr (input_location, comp, NOP_EXPR, init, |
901 | tf_warning_or_error); |
902 | else |
903 | init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); |
904 | finish_expr_stmt (init); |
905 | } |
906 | } |
907 | finish_return_stmt (class_ref); |
908 | finish_compound_stmt (compound_stmt); |
909 | } |
910 | |
911 | /* C++20 <compare> comparison category types. */ |
912 | |
913 | enum comp_cat_tag |
914 | { |
915 | cc_partial_ordering, |
916 | cc_weak_ordering, |
917 | cc_strong_ordering, |
918 | cc_last |
919 | }; |
920 | |
921 | /* Names of the comparison categories and their value members, to be indexed by |
922 | comp_cat_tag enumerators. genericize_spaceship below relies on the ordering |
923 | of the members. */ |
924 | |
925 | struct comp_cat_info_t |
926 | { |
927 | const char *name; |
928 | const char *members[4]; |
929 | }; |
930 | static const comp_cat_info_t comp_cat_info[cc_last] |
931 | = { |
932 | { .name: "partial_ordering" , .members: { "equivalent" , "greater" , "less" , "unordered" } }, |
933 | { .name: "weak_ordering" , .members: { "equivalent" , "greater" , "less" } }, |
934 | { .name: "strong_ordering" , .members: { "equal" , "greater" , "less" } } |
935 | }; |
936 | |
937 | /* A cache of the category types to speed repeated lookups. */ |
938 | |
939 | static GTY((deletable)) tree comp_cat_cache[cc_last]; |
940 | |
941 | /* Look up one of the result variables in the comparison category type. */ |
942 | |
943 | static tree |
944 | lookup_comparison_result (tree type, const char *name_str, |
945 | tsubst_flags_t complain = tf_warning_or_error) |
946 | { |
947 | tree name = get_identifier (name_str); |
948 | tree decl = lookup_qualified_name (scope: type, name); |
949 | if (TREE_CODE (decl) != VAR_DECL) |
950 | { |
951 | if (complain & tf_error) |
952 | { |
953 | auto_diagnostic_group d; |
954 | if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST) |
955 | qualified_name_lookup_error (type, name, decl, input_location); |
956 | else |
957 | error ("%qD is not a static data member" , decl); |
958 | inform (input_location, "determining value of %qs" , "operator<=>" ); |
959 | } |
960 | return error_mark_node; |
961 | } |
962 | return decl; |
963 | } |
964 | |
965 | /* Look up a <compare> comparison category type in std. */ |
966 | |
967 | static tree |
968 | lookup_comparison_category (comp_cat_tag tag, |
969 | tsubst_flags_t complain = tf_warning_or_error) |
970 | { |
971 | if (tree cached = comp_cat_cache[tag]) |
972 | return cached; |
973 | |
974 | tree name = get_identifier (comp_cat_info[tag].name); |
975 | tree decl = lookup_qualified_name (std_node, name); |
976 | if (TREE_CODE (decl) != TYPE_DECL) |
977 | { |
978 | if (complain & tf_error) |
979 | { |
980 | auto_diagnostic_group d; |
981 | if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST) |
982 | qualified_name_lookup_error (std_node, name, decl, input_location); |
983 | else |
984 | error ("%qD is not a type" , decl); |
985 | inform (input_location, "forming type of %qs" , "operator<=>" ); |
986 | } |
987 | return error_mark_node; |
988 | } |
989 | /* Also make sure we can look up the value members now, since we won't |
990 | really use them until genericize time. */ |
991 | tree type = TREE_TYPE (decl); |
992 | for (int i = 0; i < 4; ++i) |
993 | { |
994 | const char *p = comp_cat_info[tag].members[i]; |
995 | if (!p) break; |
996 | if (lookup_comparison_result (type, name_str: p, complain) |
997 | == error_mark_node) |
998 | return error_mark_node; |
999 | } |
1000 | return comp_cat_cache[tag] = type; |
1001 | } |
1002 | |
1003 | /* Wrapper that takes the tag rather than the type. */ |
1004 | |
1005 | static tree |
1006 | lookup_comparison_result (comp_cat_tag tag, const char *name_str, |
1007 | tsubst_flags_t complain = tf_warning_or_error) |
1008 | { |
1009 | tree type = lookup_comparison_category (tag, complain); |
1010 | return lookup_comparison_result (type, name_str, complain); |
1011 | } |
1012 | |
1013 | /* Wrapper that takes the index into the members array instead of the name. */ |
1014 | |
1015 | static tree |
1016 | lookup_comparison_result (comp_cat_tag tag, tree type, int idx) |
1017 | { |
1018 | const char *name_str = comp_cat_info[tag].members[idx]; |
1019 | if (!name_str) |
1020 | return NULL_TREE; |
1021 | return lookup_comparison_result (type, name_str); |
1022 | } |
1023 | |
1024 | /* Does TYPE correspond to TAG? */ |
1025 | |
1026 | static bool |
1027 | is_cat (tree type, comp_cat_tag tag) |
1028 | { |
1029 | tree name = TYPE_LINKAGE_IDENTIFIER (type); |
1030 | return id_equal (id: name, str: comp_cat_info[tag].name); |
1031 | } |
1032 | |
1033 | /* Return the comp_cat_tag for TYPE. */ |
1034 | |
1035 | static comp_cat_tag |
1036 | cat_tag_for (tree type) |
1037 | { |
1038 | if (!CLASS_TYPE_P (type) || !decl_in_std_namespace_p (TYPE_MAIN_DECL (type))) |
1039 | return cc_last; |
1040 | for (int i = 0; i < cc_last; ++i) |
1041 | { |
1042 | comp_cat_tag tag = (comp_cat_tag)i; |
1043 | if (is_cat (type, tag)) |
1044 | return tag; |
1045 | } |
1046 | return cc_last; |
1047 | } |
1048 | |
1049 | /* Return the comparison category tag of a <=> expression with non-class type |
1050 | OPTYPE. */ |
1051 | |
1052 | static comp_cat_tag |
1053 | spaceship_comp_cat (tree optype) |
1054 | { |
1055 | if (INTEGRAL_OR_ENUMERATION_TYPE_P (optype) || TYPE_PTROBV_P (optype)) |
1056 | return cc_strong_ordering; |
1057 | else if (SCALAR_FLOAT_TYPE_P (optype)) |
1058 | return cc_partial_ordering; |
1059 | |
1060 | /* ??? should vector <=> produce a vector of one of the above? */ |
1061 | gcc_unreachable (); |
1062 | } |
1063 | |
1064 | /* Return the comparison category type of a <=> expression with non-class type |
1065 | OPTYPE. */ |
1066 | |
1067 | tree |
1068 | spaceship_type (tree optype, tsubst_flags_t complain) |
1069 | { |
1070 | comp_cat_tag tag = spaceship_comp_cat (optype); |
1071 | return lookup_comparison_category (tag, complain); |
1072 | } |
1073 | |
1074 | /* Turn <=> with type TYPE and operands OP0 and OP1 into GENERIC. |
1075 | This is also used by build_comparison_op for fallback to op< and op== |
1076 | in a defaulted op<=>. */ |
1077 | |
1078 | tree |
1079 | genericize_spaceship (location_t loc, tree type, tree op0, tree op1) |
1080 | { |
1081 | /* ??? maybe optimize based on knowledge of representation? */ |
1082 | comp_cat_tag tag = cat_tag_for (type); |
1083 | |
1084 | if (tag == cc_last && is_auto (type)) |
1085 | { |
1086 | /* build_comparison_op is checking to see if we want to suggest changing |
1087 | the op<=> return type from auto to a specific comparison category; any |
1088 | category will do for now. */ |
1089 | tag = cc_strong_ordering; |
1090 | type = lookup_comparison_category (tag, complain: tf_none); |
1091 | if (type == error_mark_node) |
1092 | return error_mark_node; |
1093 | } |
1094 | |
1095 | gcc_checking_assert (tag < cc_last); |
1096 | |
1097 | tree r; |
1098 | bool scalar = SCALAR_TYPE_P (TREE_TYPE (op0)); |
1099 | if (scalar) |
1100 | { |
1101 | op0 = save_expr (op0); |
1102 | op1 = save_expr (op1); |
1103 | } |
1104 | |
1105 | tree gt = lookup_comparison_result (tag, type, idx: 1); |
1106 | |
1107 | int flags = LOOKUP_NORMAL; |
1108 | tsubst_flags_t complain = tf_none; |
1109 | tree comp; |
1110 | |
1111 | if (tag == cc_partial_ordering) |
1112 | { |
1113 | /* op0 == op1 ? equivalent : op0 < op1 ? less : |
1114 | op1 < op0 ? greater : unordered */ |
1115 | tree uo = lookup_comparison_result (tag, type, idx: 3); |
1116 | if (scalar) |
1117 | { |
1118 | /* For scalars use the low level operations; using build_new_op causes |
1119 | trouble with constexpr eval in the middle of genericize (100367). */ |
1120 | comp = fold_build2 (LT_EXPR, boolean_type_node, op1, op0); |
1121 | r = fold_build3 (COND_EXPR, type, comp, gt, uo); |
1122 | } |
1123 | else |
1124 | { |
1125 | comp = build_new_op (loc, code: LT_EXPR, flags, arg1: op1, arg2: op0, complain); |
1126 | r = build_conditional_expr (loc, comp, gt, uo, complain); |
1127 | } |
1128 | } |
1129 | else |
1130 | /* op0 == op1 ? equal : op0 < op1 ? less : greater */ |
1131 | r = gt; |
1132 | |
1133 | tree lt = lookup_comparison_result (tag, type, idx: 2); |
1134 | if (scalar) |
1135 | { |
1136 | comp = fold_build2 (LT_EXPR, boolean_type_node, op0, op1); |
1137 | r = fold_build3 (COND_EXPR, type, comp, lt, r); |
1138 | } |
1139 | else |
1140 | { |
1141 | comp = build_new_op (loc, code: LT_EXPR, flags, arg1: op0, arg2: op1, complain); |
1142 | r = build_conditional_expr (loc, comp, lt, r, complain); |
1143 | } |
1144 | |
1145 | tree eq = lookup_comparison_result (tag, type, idx: 0); |
1146 | if (scalar) |
1147 | { |
1148 | comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1); |
1149 | r = fold_build3 (COND_EXPR, type, comp, eq, r); |
1150 | } |
1151 | else |
1152 | { |
1153 | comp = build_new_op (loc, code: EQ_EXPR, flags, arg1: op0, arg2: op1, complain); |
1154 | r = build_conditional_expr (loc, comp, eq, r, complain); |
1155 | } |
1156 | |
1157 | return r; |
1158 | } |
1159 | |
1160 | /* Check that the signature of a defaulted comparison operator is |
1161 | well-formed. */ |
1162 | |
1163 | static bool |
1164 | early_check_defaulted_comparison (tree fn) |
1165 | { |
1166 | location_t loc = DECL_SOURCE_LOCATION (fn); |
1167 | tree ctx; |
1168 | if (DECL_CLASS_SCOPE_P (fn)) |
1169 | ctx = DECL_CONTEXT (fn); |
1170 | else |
1171 | ctx = DECL_FRIEND_CONTEXT (fn); |
1172 | bool ok = true; |
1173 | |
1174 | if (cxx_dialect < cxx20) |
1175 | { |
1176 | error_at (loc, "defaulted %qD only available with %<-std=c++20%> or " |
1177 | "%<-std=gnu++20%>" , fn); |
1178 | return false; |
1179 | } |
1180 | |
1181 | if (!DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR) |
1182 | && !same_type_p (TREE_TYPE (TREE_TYPE (fn)), boolean_type_node)) |
1183 | { |
1184 | diagnostic_t kind = DK_UNSPECIFIED; |
1185 | int opt = 0; |
1186 | if (is_auto (TREE_TYPE (fn))) |
1187 | kind = DK_PEDWARN; |
1188 | else |
1189 | kind = DK_ERROR; |
1190 | emit_diagnostic (kind, loc, opt, |
1191 | "defaulted %qD must return %<bool%>" , fn); |
1192 | if (kind == DK_ERROR) |
1193 | ok = false; |
1194 | } |
1195 | |
1196 | bool mem = DECL_IOBJ_MEMBER_FUNCTION_P (fn); |
1197 | if (mem && type_memfn_quals (TREE_TYPE (fn)) != TYPE_QUAL_CONST) |
1198 | { |
1199 | error_at (loc, "defaulted %qD must be %<const%>" , fn); |
1200 | ok = false; |
1201 | } |
1202 | if (mem && type_memfn_rqual (TREE_TYPE (fn)) == REF_QUAL_RVALUE) |
1203 | { |
1204 | error_at (loc, "defaulted %qD must not have %<&&%> ref-qualifier" , fn); |
1205 | ok = false; |
1206 | } |
1207 | tree parmnode = FUNCTION_FIRST_USER_PARMTYPE (fn); |
1208 | bool saw_byval = false; |
1209 | bool saw_byref = mem; |
1210 | bool saw_bad = false; |
1211 | for (; parmnode != void_list_node; parmnode = TREE_CHAIN (parmnode)) |
1212 | { |
1213 | tree parmtype = TREE_VALUE (parmnode); |
1214 | if (CLASS_TYPE_P (parmtype)) |
1215 | saw_byval = true; |
1216 | else if (TREE_CODE (parmtype) == REFERENCE_TYPE |
1217 | && !TYPE_REF_IS_RVALUE (parmtype) |
1218 | && TYPE_QUALS (TREE_TYPE (parmtype)) == TYPE_QUAL_CONST) |
1219 | { |
1220 | saw_byref = true; |
1221 | parmtype = TREE_TYPE (parmtype); |
1222 | } |
1223 | else |
1224 | saw_bad = true; |
1225 | |
1226 | if (!saw_bad && !ctx) |
1227 | { |
1228 | /* Defaulted outside the class body. */ |
1229 | ctx = TYPE_MAIN_VARIANT (parmtype); |
1230 | if (!is_friend (ctx, fn)) |
1231 | { |
1232 | auto_diagnostic_group d; |
1233 | error_at (loc, "defaulted %qD is not a friend of %qT" , fn, ctx); |
1234 | inform (location_of (ctx), "declared here" ); |
1235 | ok = false; |
1236 | } |
1237 | } |
1238 | else if (!same_type_ignoring_top_level_qualifiers_p (parmtype, ctx)) |
1239 | saw_bad = true; |
1240 | } |
1241 | |
1242 | if (saw_bad || (saw_byval && saw_byref)) |
1243 | { |
1244 | if (DECL_IOBJ_MEMBER_FUNCTION_P (fn)) |
1245 | error_at (loc, "defaulted member %qD must have parameter type " |
1246 | "%<const %T&%>" , fn, ctx); |
1247 | else if (saw_bad) |
1248 | error_at (loc, "defaulted %qD must have parameters of either type " |
1249 | "%<const %T&%> or %qT" , fn, ctx, ctx); |
1250 | else |
1251 | error_at (loc, "defaulted %qD must have parameters of either type " |
1252 | "%<const %T&%> or %qT, not both" , fn, ctx, ctx); |
1253 | ok = false; |
1254 | } |
1255 | |
1256 | /* We still need to deduce deleted/constexpr/noexcept and maybe return. */ |
1257 | DECL_MAYBE_DELETED (fn) = ok; |
1258 | |
1259 | return ok; |
1260 | } |
1261 | |
1262 | /* Subroutine of build_comparison_op. Given the vec of memberwise |
1263 | comparisons COMPS, calculate the overall comparison category for |
1264 | operator<=>. */ |
1265 | |
1266 | static tree |
1267 | common_comparison_type (vec<tree> &comps) |
1268 | { |
1269 | tree seen[cc_last] = {}; |
1270 | |
1271 | for (unsigned i = 0; i < comps.length(); ++i) |
1272 | { |
1273 | tree comp = comps[i]; |
1274 | if (TREE_CODE (comp) == TREE_LIST) |
1275 | comp = TREE_VALUE (comp); |
1276 | tree ctype = TREE_TYPE (comp); |
1277 | comp_cat_tag tag = cat_tag_for (type: ctype); |
1278 | /* build_comparison_op already checked this. */ |
1279 | gcc_checking_assert (tag < cc_last); |
1280 | seen[tag] = ctype; |
1281 | } |
1282 | |
1283 | /* Otherwise, if at least one T i is std::partial_ordering, U is |
1284 | std::partial_ordering. */ |
1285 | if (tree t = seen[cc_partial_ordering]) return t; |
1286 | |
1287 | /* Otherwise, if at least one T i is std::weak_ordering, U is |
1288 | std::weak_ordering. */ |
1289 | if (tree t = seen[cc_weak_ordering]) return t; |
1290 | |
1291 | /* Otherwise, U is std::strong_ordering. */ |
1292 | if (tree t = seen[cc_strong_ordering]) return t; |
1293 | return lookup_comparison_category (tag: cc_strong_ordering); |
1294 | } |
1295 | |
1296 | /* Data structure for build_comparison_op. */ |
1297 | |
1298 | struct comp_info |
1299 | { |
1300 | tree fndecl; |
1301 | location_t loc; |
1302 | tsubst_flags_t complain; |
1303 | tree_code code; |
1304 | comp_cat_tag retcat; |
1305 | bool first_time; |
1306 | bool constexp; |
1307 | bool was_constexp; |
1308 | bool noex; |
1309 | |
1310 | comp_info (tree fndecl, tsubst_flags_t complain) |
1311 | : fndecl (fndecl), complain (complain) |
1312 | { |
1313 | loc = DECL_SOURCE_LOCATION (fndecl); |
1314 | |
1315 | first_time = DECL_MAYBE_DELETED (fndecl); |
1316 | DECL_MAYBE_DELETED (fndecl) = false; |
1317 | |
1318 | /* Do we want to try to set constexpr? */ |
1319 | was_constexp = DECL_DECLARED_CONSTEXPR_P (fndecl); |
1320 | constexp = first_time; |
1321 | if (constexp) |
1322 | /* Set this for var_in_constexpr_fn. */ |
1323 | DECL_DECLARED_CONSTEXPR_P (fndecl) = true; |
1324 | |
1325 | /* Do we want to try to set noexcept? */ |
1326 | noex = first_time; |
1327 | if (noex) |
1328 | { |
1329 | tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fndecl)); |
1330 | if (raises && !UNEVALUATED_NOEXCEPT_SPEC_P (raises)) |
1331 | /* There was an explicit exception-specification. */ |
1332 | noex = false; |
1333 | } |
1334 | } |
1335 | |
1336 | /* EXPR is an expression built as part of the function body. |
1337 | Adjust the properties appropriately. */ |
1338 | void check (tree expr) |
1339 | { |
1340 | if (expr == error_mark_node) |
1341 | DECL_DELETED_FN (fndecl) = true; |
1342 | if ((constexp || was_constexp) |
1343 | && !potential_rvalue_constant_expression (expr)) |
1344 | { |
1345 | if (was_constexp) |
1346 | require_potential_rvalue_constant_expression_fncheck (expr); |
1347 | else |
1348 | constexp = false; |
1349 | } |
1350 | if (noex && !expr_noexcept_p (expr, tf_none)) |
1351 | noex = false; |
1352 | } |
1353 | |
1354 | ~comp_info () |
1355 | { |
1356 | if (first_time) |
1357 | { |
1358 | DECL_DECLARED_CONSTEXPR_P (fndecl) = constexp || was_constexp; |
1359 | tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fndecl)); |
1360 | if (!raises || UNEVALUATED_NOEXCEPT_SPEC_P (raises)) |
1361 | { |
1362 | raises = noex ? noexcept_true_spec : noexcept_false_spec; |
1363 | TREE_TYPE (fndecl) = build_exception_variant (TREE_TYPE (fndecl), |
1364 | raises); |
1365 | } |
1366 | } |
1367 | } |
1368 | }; |
1369 | |
1370 | /* Subroutine of build_comparison_op, to compare a single subobject. */ |
1371 | |
1372 | static tree |
1373 | do_one_comp (location_t loc, const comp_info &info, tree sub, tree lhs, tree rhs) |
1374 | { |
1375 | const tree_code code = info.code; |
1376 | const tree fndecl = info.fndecl; |
1377 | const comp_cat_tag retcat = info.retcat; |
1378 | const tsubst_flags_t complain = info.complain; |
1379 | |
1380 | tree overload = NULL_TREE; |
1381 | int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED; |
1382 | /* If we have an explicit comparison category return type we can fall back |
1383 | to </=, so don't give an error yet if <=> lookup fails. */ |
1384 | bool tentative = retcat != cc_last; |
1385 | tree comp = build_new_op (loc, code, flags, lhs, rhs, |
1386 | NULL_TREE, NULL_TREE, &overload, |
1387 | tentative ? tf_none : complain); |
1388 | |
1389 | if (code != SPACESHIP_EXPR) |
1390 | return comp; |
1391 | |
1392 | tree rettype = TREE_TYPE (TREE_TYPE (fndecl)); |
1393 | |
1394 | if (comp == error_mark_node) |
1395 | { |
1396 | if (overload == NULL_TREE && (tentative || complain)) |
1397 | { |
1398 | /* No viable <=>, try using op< and op==. */ |
1399 | tree lteq = genericize_spaceship (loc, type: rettype, op0: lhs, op1: rhs); |
1400 | if (lteq != error_mark_node) |
1401 | { |
1402 | /* We found usable < and ==. */ |
1403 | if (retcat != cc_last) |
1404 | /* Return type is a comparison category, use them. */ |
1405 | comp = lteq; |
1406 | else if (complain & tf_error) |
1407 | /* Return type is auto, suggest changing it. */ |
1408 | inform (info.loc, "changing the return type from %qs " |
1409 | "to a comparison category type will allow the " |
1410 | "comparison to use %qs and %qs" , "auto" , |
1411 | "operator<" , "operator==" ); |
1412 | } |
1413 | else if (tentative && complain) |
1414 | /* No usable < and ==, give an error for op<=>. */ |
1415 | build_new_op (loc, code, flags, arg1: lhs, arg2: rhs, complain); |
1416 | } |
1417 | if (comp == error_mark_node) |
1418 | return error_mark_node; |
1419 | } |
1420 | |
1421 | if (FNDECL_USED_AUTO (fndecl) |
1422 | && cat_tag_for (TREE_TYPE (comp)) == cc_last) |
1423 | { |
1424 | /* The operator function is defined as deleted if ... Ri is not a |
1425 | comparison category type. */ |
1426 | if (complain & tf_error) |
1427 | inform (loc, |
1428 | "three-way comparison of %qD has type %qT, not a " |
1429 | "comparison category type" , sub, TREE_TYPE (comp)); |
1430 | return error_mark_node; |
1431 | } |
1432 | else if (!FNDECL_USED_AUTO (fndecl) |
1433 | && !can_convert (rettype, TREE_TYPE (comp), complain)) |
1434 | { |
1435 | if (complain & tf_error) |
1436 | error_at (loc, |
1437 | "three-way comparison of %qD has type %qT, which " |
1438 | "does not convert to %qT" , |
1439 | sub, TREE_TYPE (comp), rettype); |
1440 | return error_mark_node; |
1441 | } |
1442 | |
1443 | return comp; |
1444 | } |
1445 | |
1446 | /* Build up the definition of a defaulted comparison operator. Unlike other |
1447 | defaulted functions that use synthesized_method_walk to determine whether |
1448 | the function is e.g. deleted, for comparisons we use the same code. We try |
1449 | to use synthesize_method at the earliest opportunity and bail out if the |
1450 | function ends up being deleted. */ |
1451 | |
1452 | void |
1453 | build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain) |
1454 | { |
1455 | comp_info info (fndecl, complain); |
1456 | |
1457 | if (!defining && !(complain & tf_error) && !DECL_MAYBE_DELETED (fndecl)) |
1458 | return; |
1459 | |
1460 | int flags = LOOKUP_NORMAL; |
1461 | const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (DECL_NAME (fndecl)); |
1462 | tree_code code = info.code = op->tree_code; |
1463 | |
1464 | tree lhs = DECL_ARGUMENTS (fndecl); |
1465 | tree rhs = DECL_CHAIN (lhs); |
1466 | if (is_this_parameter (lhs)) |
1467 | lhs = cp_build_fold_indirect_ref (lhs); |
1468 | else |
1469 | lhs = convert_from_reference (lhs); |
1470 | rhs = convert_from_reference (rhs); |
1471 | tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (lhs)); |
1472 | gcc_assert (!defining || COMPLETE_TYPE_P (ctype)); |
1473 | |
1474 | iloc_sentinel ils (info.loc); |
1475 | |
1476 | /* A defaulted comparison operator function for class C is defined as |
1477 | deleted if ... C has variant members. */ |
1478 | if (TREE_CODE (ctype) == UNION_TYPE |
1479 | && next_aggregate_field (TYPE_FIELDS (ctype))) |
1480 | { |
1481 | if (complain & tf_error) |
1482 | inform (info.loc, "cannot default compare union %qT" , ctype); |
1483 | DECL_DELETED_FN (fndecl) = true; |
1484 | return; |
1485 | } |
1486 | |
1487 | tree compound_stmt = NULL_TREE; |
1488 | if (defining) |
1489 | compound_stmt = begin_compound_stmt (0); |
1490 | else |
1491 | ++cp_unevaluated_operand; |
1492 | |
1493 | tree rettype = TREE_TYPE (TREE_TYPE (fndecl)); |
1494 | if (code != SPACESHIP_EXPR && is_auto (rettype)) |
1495 | { |
1496 | rettype = boolean_type_node; |
1497 | apply_deduced_return_type (fndecl, rettype); |
1498 | } |
1499 | |
1500 | if (code == EQ_EXPR || code == SPACESHIP_EXPR) |
1501 | { |
1502 | comp_cat_tag &retcat = (info.retcat = cc_last); |
1503 | if (code == SPACESHIP_EXPR && !FNDECL_USED_AUTO (fndecl)) |
1504 | retcat = cat_tag_for (type: rettype); |
1505 | |
1506 | bool bad = false; |
1507 | auto_vec<tree> comps; |
1508 | |
1509 | /* Compare the base subobjects. We handle them this way, rather than in |
1510 | the field loop below, because maybe_instantiate_noexcept might bring |
1511 | us here before we've built the base fields. */ |
1512 | for (tree base_binfo : BINFO_BASE_BINFOS (TYPE_BINFO (ctype))) |
1513 | { |
1514 | tree lhs_base |
1515 | = build_base_path (PLUS_EXPR, lhs, base_binfo, 0, complain); |
1516 | tree rhs_base |
1517 | = build_base_path (PLUS_EXPR, rhs, base_binfo, 0, complain); |
1518 | |
1519 | location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (ctype)); |
1520 | tree comp = do_one_comp (loc, info, BINFO_TYPE (base_binfo), |
1521 | lhs: lhs_base, rhs: rhs_base); |
1522 | if (comp == error_mark_node) |
1523 | { |
1524 | bad = true; |
1525 | continue; |
1526 | } |
1527 | |
1528 | comps.safe_push (obj: comp); |
1529 | } |
1530 | |
1531 | /* Now compare the field subobjects. */ |
1532 | for (tree field = next_aggregate_field (TYPE_FIELDS (ctype)); |
1533 | field; |
1534 | field = next_aggregate_field (DECL_CHAIN (field))) |
1535 | { |
1536 | if (DECL_VIRTUAL_P (field) || DECL_FIELD_IS_BASE (field)) |
1537 | /* We ignore the vptr, and we already handled bases. */ |
1538 | continue; |
1539 | |
1540 | tree expr_type = TREE_TYPE (field); |
1541 | |
1542 | location_t field_loc = DECL_SOURCE_LOCATION (field); |
1543 | |
1544 | /* A defaulted comparison operator function for class C is defined as |
1545 | deleted if any non-static data member of C is of reference type or |
1546 | C has variant members. */ |
1547 | if (TREE_CODE (expr_type) == REFERENCE_TYPE) |
1548 | { |
1549 | if (complain & tf_error) |
1550 | inform (field_loc, "cannot default compare " |
1551 | "reference member %qD" , field); |
1552 | bad = true; |
1553 | continue; |
1554 | } |
1555 | else if (ANON_UNION_TYPE_P (expr_type) |
1556 | && next_aggregate_field (TYPE_FIELDS (expr_type))) |
1557 | { |
1558 | if (complain & tf_error) |
1559 | inform (field_loc, "cannot default compare " |
1560 | "anonymous union member" ); |
1561 | bad = true; |
1562 | continue; |
1563 | } |
1564 | |
1565 | tree lhs_mem = build3_loc (loc: field_loc, code: COMPONENT_REF, type: expr_type, arg0: lhs, |
1566 | arg1: field, NULL_TREE); |
1567 | tree rhs_mem = build3_loc (loc: field_loc, code: COMPONENT_REF, type: expr_type, arg0: rhs, |
1568 | arg1: field, NULL_TREE); |
1569 | tree loop_indexes = NULL_TREE; |
1570 | while (TREE_CODE (expr_type) == ARRAY_TYPE) |
1571 | { |
1572 | /* Flexible array member. */ |
1573 | if (TYPE_DOMAIN (expr_type) == NULL_TREE |
1574 | || TYPE_MAX_VALUE (TYPE_DOMAIN (expr_type)) == NULL_TREE) |
1575 | { |
1576 | if (complain & tf_error) |
1577 | inform (field_loc, "cannot default compare " |
1578 | "flexible array member" ); |
1579 | bad = true; |
1580 | break; |
1581 | } |
1582 | tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (expr_type)); |
1583 | /* [0] array. No subobjects to compare, just skip it. */ |
1584 | if (integer_all_onesp (maxval)) |
1585 | break; |
1586 | tree idx; |
1587 | /* [1] array, no loop needed, just add [0] ARRAY_REF. |
1588 | Similarly if !defining. */ |
1589 | if (integer_zerop (maxval) || !defining) |
1590 | idx = size_zero_node; |
1591 | /* Some other array, will need runtime loop. */ |
1592 | else |
1593 | { |
1594 | idx = force_target_expr (sizetype, maxval, complain); |
1595 | loop_indexes = tree_cons (idx, NULL_TREE, loop_indexes); |
1596 | } |
1597 | expr_type = TREE_TYPE (expr_type); |
1598 | lhs_mem = build4_loc (loc: field_loc, code: ARRAY_REF, type: expr_type, arg0: lhs_mem, |
1599 | arg1: idx, NULL_TREE, NULL_TREE); |
1600 | rhs_mem = build4_loc (loc: field_loc, code: ARRAY_REF, type: expr_type, arg0: rhs_mem, |
1601 | arg1: idx, NULL_TREE, NULL_TREE); |
1602 | } |
1603 | if (TREE_CODE (expr_type) == ARRAY_TYPE) |
1604 | continue; |
1605 | |
1606 | tree comp = do_one_comp (loc: field_loc, info, sub: field, lhs: lhs_mem, rhs: rhs_mem); |
1607 | if (comp == error_mark_node) |
1608 | { |
1609 | bad = true; |
1610 | continue; |
1611 | } |
1612 | |
1613 | /* Most of the time, comp is the expression that should be evaluated |
1614 | to compare the two members. If the expression needs to be |
1615 | evaluated more than once in a loop, it will be a TREE_LIST |
1616 | instead, whose TREE_VALUE is the expression for one array element, |
1617 | TREE_PURPOSE is innermost iterator temporary and if the array |
1618 | is multidimensional, TREE_CHAIN will contain another TREE_LIST |
1619 | with second innermost iterator in its TREE_PURPOSE and so on. */ |
1620 | if (loop_indexes) |
1621 | { |
1622 | TREE_VALUE (loop_indexes) = comp; |
1623 | comp = loop_indexes; |
1624 | } |
1625 | comps.safe_push (obj: comp); |
1626 | } |
1627 | if (code == SPACESHIP_EXPR && is_auto (rettype)) |
1628 | { |
1629 | rettype = common_comparison_type (comps); |
1630 | apply_deduced_return_type (fndecl, rettype); |
1631 | } |
1632 | if (bad) |
1633 | { |
1634 | DECL_DELETED_FN (fndecl) = true; |
1635 | goto out; |
1636 | } |
1637 | for (unsigned i = 0; i < comps.length(); ++i) |
1638 | { |
1639 | tree comp = comps[i]; |
1640 | tree eq, retval = NULL_TREE, if_ = NULL_TREE; |
1641 | tree loop_indexes = NULL_TREE; |
1642 | if (defining) |
1643 | { |
1644 | if (TREE_CODE (comp) == TREE_LIST) |
1645 | { |
1646 | loop_indexes = comp; |
1647 | comp = TREE_VALUE (comp); |
1648 | loop_indexes = nreverse (loop_indexes); |
1649 | for (tree loop_index = loop_indexes; loop_index; |
1650 | loop_index = TREE_CHAIN (loop_index)) |
1651 | { |
1652 | tree for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE); |
1653 | tree idx = TREE_PURPOSE (loop_index); |
1654 | tree maxval = TARGET_EXPR_INITIAL (idx); |
1655 | TARGET_EXPR_INITIAL (idx) = size_zero_node; |
1656 | add_stmt (idx); |
1657 | finish_init_stmt (for_stmt); |
1658 | finish_for_cond (build2 (LE_EXPR, boolean_type_node, idx, |
1659 | maxval), for_stmt, false, 0, |
1660 | false); |
1661 | finish_for_expr (cp_build_unary_op (PREINCREMENT_EXPR, |
1662 | TARGET_EXPR_SLOT (idx), |
1663 | false, complain), |
1664 | for_stmt); |
1665 | /* Store in TREE_VALUE the for_stmt tree, so that we can |
1666 | later on call finish_for_stmt on it (in the reverse |
1667 | order). */ |
1668 | TREE_VALUE (loop_index) = for_stmt; |
1669 | } |
1670 | loop_indexes = nreverse (loop_indexes); |
1671 | } |
1672 | if_ = begin_if_stmt (); |
1673 | } |
1674 | /* Spaceship is specified to use !=, but for the comparison category |
1675 | types, != is equivalent to !(==), so let's use == directly. */ |
1676 | if (code == EQ_EXPR) |
1677 | { |
1678 | /* if (x==y); else return false; */ |
1679 | eq = comp; |
1680 | retval = boolean_false_node; |
1681 | } |
1682 | else |
1683 | { |
1684 | /* if (auto v = x<=>y, v == 0); else return v; */ |
1685 | if (TREE_CODE (comp) == SPACESHIP_EXPR) |
1686 | TREE_TYPE (comp) = rettype; |
1687 | else |
1688 | comp = build_static_cast (input_location, rettype, comp, |
1689 | complain); |
1690 | info.check (expr: comp); |
1691 | if (defining) |
1692 | { |
1693 | tree var = create_temporary_var (rettype); |
1694 | DECL_NAME (var) = get_identifier ("retval" ); |
1695 | pushdecl (var); |
1696 | cp_finish_decl (var, comp, false, NULL_TREE, flags); |
1697 | comp = retval = var; |
1698 | } |
1699 | eq = build_new_op (info.loc, EQ_EXPR, flags, comp, |
1700 | integer_zero_node, NULL_TREE, NULL_TREE, |
1701 | NULL, complain); |
1702 | } |
1703 | tree ceq = contextual_conv_bool (eq, complain); |
1704 | info.check (expr: ceq); |
1705 | if (defining) |
1706 | { |
1707 | finish_if_stmt_cond (ceq, if_); |
1708 | finish_then_clause (if_); |
1709 | begin_else_clause (if_); |
1710 | finish_return_stmt (retval); |
1711 | finish_else_clause (if_); |
1712 | finish_if_stmt (if_); |
1713 | for (tree loop_index = loop_indexes; loop_index; |
1714 | loop_index = TREE_CHAIN (loop_index)) |
1715 | finish_for_stmt (TREE_VALUE (loop_index)); |
1716 | } |
1717 | } |
1718 | if (defining) |
1719 | { |
1720 | tree val; |
1721 | if (code == EQ_EXPR) |
1722 | val = boolean_true_node; |
1723 | else |
1724 | { |
1725 | tree seql = lookup_comparison_result (tag: cc_strong_ordering, |
1726 | name_str: "equal" , complain); |
1727 | val = build_static_cast (input_location, rettype, seql, |
1728 | complain); |
1729 | } |
1730 | finish_return_stmt (val); |
1731 | } |
1732 | } |
1733 | else if (code == NE_EXPR) |
1734 | { |
1735 | tree comp = build_new_op (info.loc, EQ_EXPR, flags, lhs, rhs, |
1736 | NULL_TREE, NULL_TREE, NULL, complain); |
1737 | comp = contextual_conv_bool (comp, complain); |
1738 | info.check (expr: comp); |
1739 | if (defining) |
1740 | { |
1741 | tree neg = build1 (TRUTH_NOT_EXPR, boolean_type_node, comp); |
1742 | finish_return_stmt (neg); |
1743 | } |
1744 | } |
1745 | else |
1746 | { |
1747 | tree comp = build_new_op (info.loc, SPACESHIP_EXPR, flags, lhs, rhs, |
1748 | NULL_TREE, NULL_TREE, NULL, complain); |
1749 | tree comp2 = build_new_op (info.loc, code, flags, comp, integer_zero_node, |
1750 | NULL_TREE, NULL_TREE, NULL, complain); |
1751 | info.check (expr: comp2); |
1752 | if (defining) |
1753 | finish_return_stmt (comp2); |
1754 | } |
1755 | |
1756 | out: |
1757 | if (defining) |
1758 | finish_compound_stmt (compound_stmt); |
1759 | else |
1760 | --cp_unevaluated_operand; |
1761 | } |
1762 | |
1763 | /* True iff DECL is an implicitly-declared special member function with no real |
1764 | source location, so we can use its DECL_SOURCE_LOCATION to remember where we |
1765 | triggered its synthesis. */ |
1766 | |
1767 | bool |
1768 | decl_remember_implicit_trigger_p (tree decl) |
1769 | { |
1770 | if (!DECL_ARTIFICIAL (decl)) |
1771 | return false; |
1772 | special_function_kind sfk = special_function_p (decl); |
1773 | /* Inherited constructors have the location of their using-declaration, and |
1774 | operator== has the location of the corresponding operator<=>. */ |
1775 | return (sfk != sfk_inheriting_constructor |
1776 | && sfk != sfk_comparison); |
1777 | } |
1778 | |
1779 | /* Synthesize FNDECL, a non-static member function. */ |
1780 | |
1781 | void |
1782 | synthesize_method (tree fndecl) |
1783 | { |
1784 | bool need_body = true; |
1785 | tree stmt; |
1786 | location_t save_input_location = input_location; |
1787 | int error_count = errorcount; |
1788 | int warning_count = warningcount + werrorcount; |
1789 | special_function_kind sfk = special_function_p (fndecl); |
1790 | |
1791 | /* Reset the source location, we might have been previously |
1792 | deferred, and thus have saved where we were first needed. */ |
1793 | if (decl_remember_implicit_trigger_p (decl: fndecl)) |
1794 | DECL_SOURCE_LOCATION (fndecl) |
1795 | = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl))); |
1796 | |
1797 | /* If we've been asked to synthesize a clone, just synthesize the |
1798 | cloned function instead. Doing so will automatically fill in the |
1799 | body for the clone. */ |
1800 | if (DECL_CLONED_FUNCTION_P (fndecl)) |
1801 | fndecl = DECL_CLONED_FUNCTION (fndecl); |
1802 | |
1803 | /* We may be in the middle of deferred access check. Disable |
1804 | it now. */ |
1805 | push_deferring_access_checks (dk_no_deferred); |
1806 | |
1807 | bool push_to_top = maybe_push_to_top_level (fndecl); |
1808 | |
1809 | input_location = DECL_SOURCE_LOCATION (fndecl); |
1810 | |
1811 | start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); |
1812 | stmt = begin_function_body (); |
1813 | |
1814 | if (DECL_ASSIGNMENT_OPERATOR_P (fndecl) |
1815 | && DECL_OVERLOADED_OPERATOR_IS (fndecl, NOP_EXPR)) |
1816 | { |
1817 | do_build_copy_assign (fndecl); |
1818 | need_body = false; |
1819 | } |
1820 | else if (DECL_CONSTRUCTOR_P (fndecl)) |
1821 | { |
1822 | tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl); |
1823 | if (arg_chain != void_list_node) |
1824 | do_build_copy_constructor (fndecl); |
1825 | else |
1826 | finish_mem_initializers (NULL_TREE); |
1827 | } |
1828 | else if (sfk == sfk_comparison) |
1829 | { |
1830 | /* Pass tf_none so the function is just deleted if there's a problem. */ |
1831 | build_comparison_op (fndecl, defining: true, complain: tf_none); |
1832 | need_body = false; |
1833 | } |
1834 | |
1835 | /* If we haven't yet generated the body of the function, just |
1836 | generate an empty compound statement. */ |
1837 | if (need_body) |
1838 | { |
1839 | tree compound_stmt; |
1840 | compound_stmt = begin_compound_stmt (BCS_FN_BODY); |
1841 | finish_compound_stmt (compound_stmt); |
1842 | } |
1843 | |
1844 | finish_function_body (stmt); |
1845 | finish_function (/*inline_p=*/false); |
1846 | |
1847 | if (!DECL_DELETED_FN (fndecl)) |
1848 | expand_or_defer_fn (fndecl); |
1849 | |
1850 | input_location = save_input_location; |
1851 | |
1852 | maybe_pop_from_top_level (push_to_top); |
1853 | |
1854 | pop_deferring_access_checks (); |
1855 | |
1856 | if (error_count != errorcount || warning_count != warningcount + werrorcount) |
1857 | if (DECL_ARTIFICIAL (fndecl)) |
1858 | inform (input_location, "synthesized method %qD first required here" , |
1859 | fndecl); |
1860 | } |
1861 | |
1862 | /* Like synthesize_method, but don't actually synthesize defaulted comparison |
1863 | methods if their class is still incomplete. Just deduce the return |
1864 | type in that case. */ |
1865 | |
1866 | void |
1867 | maybe_synthesize_method (tree fndecl) |
1868 | { |
1869 | if (special_function_p (fndecl) == sfk_comparison) |
1870 | { |
1871 | tree lhs = DECL_ARGUMENTS (fndecl); |
1872 | if (is_this_parameter (lhs)) |
1873 | lhs = cp_build_fold_indirect_ref (lhs); |
1874 | else |
1875 | lhs = convert_from_reference (lhs); |
1876 | tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (lhs)); |
1877 | if (!COMPLETE_TYPE_P (ctype)) |
1878 | { |
1879 | push_deferring_access_checks (dk_no_deferred); |
1880 | build_comparison_op (fndecl, defining: false, complain: tf_none); |
1881 | pop_deferring_access_checks (); |
1882 | return; |
1883 | } |
1884 | } |
1885 | return synthesize_method (fndecl); |
1886 | } |
1887 | |
1888 | /* Build a reference to type TYPE with cv-quals QUALS, which is an |
1889 | rvalue if RVALUE is true. */ |
1890 | |
1891 | static tree |
1892 | build_stub_type (tree type, int quals, bool rvalue) |
1893 | { |
1894 | tree argtype = cp_build_qualified_type (type, quals); |
1895 | return cp_build_reference_type (argtype, rvalue); |
1896 | } |
1897 | |
1898 | /* Build a dummy glvalue from dereferencing a dummy reference of type |
1899 | REFTYPE. */ |
1900 | |
1901 | tree |
1902 | build_stub_object (tree reftype) |
1903 | { |
1904 | if (!TYPE_REF_P (reftype)) |
1905 | reftype = cp_build_reference_type (reftype, /*rval*/true); |
1906 | tree stub = build1 (CONVERT_EXPR, reftype, integer_one_node); |
1907 | return convert_from_reference (stub); |
1908 | } |
1909 | |
1910 | /* Build a std::declval<TYPE>() expression and return it. */ |
1911 | |
1912 | tree |
1913 | build_trait_object (tree type) |
1914 | { |
1915 | /* TYPE can't be a function with cv-/ref-qualifiers: std::declval is |
1916 | defined as |
1917 | |
1918 | template<class T> |
1919 | typename std::add_rvalue_reference<T>::type declval() noexcept; |
1920 | |
1921 | and std::add_rvalue_reference yields T when T is a function with |
1922 | cv- or ref-qualifiers, making the definition ill-formed. */ |
1923 | if (FUNC_OR_METHOD_TYPE_P (type) |
1924 | && (type_memfn_quals (type) != TYPE_UNQUALIFIED |
1925 | || type_memfn_rqual (type) != REF_QUAL_NONE)) |
1926 | return error_mark_node; |
1927 | |
1928 | return build_stub_object (reftype: type); |
1929 | } |
1930 | |
1931 | /* Determine which function will be called when looking up NAME in TYPE, |
1932 | called with a single ARGTYPE argument, or no argument if ARGTYPE is |
1933 | null. FLAGS and COMPLAIN are as for build_new_method_call. |
1934 | |
1935 | Returns a FUNCTION_DECL if all is well. |
1936 | Returns NULL_TREE if overload resolution failed. |
1937 | Returns error_mark_node if the chosen function cannot be called. */ |
1938 | |
1939 | static tree |
1940 | locate_fn_flags (tree type, tree name, tree argtype, int flags, |
1941 | tsubst_flags_t complain) |
1942 | { |
1943 | tree ob, fn, fns, binfo, rval; |
1944 | |
1945 | if (TYPE_P (type)) |
1946 | binfo = TYPE_BINFO (type); |
1947 | else |
1948 | { |
1949 | binfo = type; |
1950 | type = BINFO_TYPE (binfo); |
1951 | } |
1952 | |
1953 | ob = build_stub_object (reftype: cp_build_reference_type (type, false)); |
1954 | releasing_vec args; |
1955 | if (argtype) |
1956 | { |
1957 | if (TREE_CODE (argtype) == TREE_LIST) |
1958 | { |
1959 | for (tree elt = argtype; elt && elt != void_list_node; |
1960 | elt = TREE_CHAIN (elt)) |
1961 | { |
1962 | tree type = TREE_VALUE (elt); |
1963 | tree arg = build_stub_object (reftype: type); |
1964 | vec_safe_push (r&: args, t: arg); |
1965 | } |
1966 | } |
1967 | else |
1968 | { |
1969 | tree arg = build_stub_object (reftype: argtype); |
1970 | args->quick_push (obj: arg); |
1971 | } |
1972 | } |
1973 | |
1974 | fns = lookup_fnfields (binfo, name, 0, complain); |
1975 | rval = build_new_method_call (ob, fns, &args, binfo, flags, &fn, complain); |
1976 | |
1977 | if (fn && rval == error_mark_node) |
1978 | return rval; |
1979 | else |
1980 | return fn; |
1981 | } |
1982 | |
1983 | /* Locate the dtor of TYPE. */ |
1984 | |
1985 | tree |
1986 | get_dtor (tree type, tsubst_flags_t complain) |
1987 | { |
1988 | tree fn = locate_fn_flags (type, complete_dtor_identifier, NULL_TREE, |
1989 | LOOKUP_NORMAL, complain); |
1990 | if (fn == error_mark_node) |
1991 | return NULL_TREE; |
1992 | return fn; |
1993 | } |
1994 | |
1995 | /* Locate the default ctor of TYPE. */ |
1996 | |
1997 | tree |
1998 | locate_ctor (tree type) |
1999 | { |
2000 | tree fn; |
2001 | |
2002 | push_deferring_access_checks (dk_no_check); |
2003 | fn = locate_fn_flags (type, complete_ctor_identifier, NULL_TREE, |
2004 | LOOKUP_SPECULATIVE, complain: tf_none); |
2005 | pop_deferring_access_checks (); |
2006 | if (fn == error_mark_node) |
2007 | return NULL_TREE; |
2008 | return fn; |
2009 | } |
2010 | |
2011 | /* Likewise, but give any appropriate errors. */ |
2012 | |
2013 | tree |
2014 | get_default_ctor (tree type) |
2015 | { |
2016 | tree fn = locate_fn_flags (type, complete_ctor_identifier, NULL_TREE, |
2017 | LOOKUP_NORMAL, complain: tf_warning_or_error); |
2018 | if (fn == error_mark_node) |
2019 | return NULL_TREE; |
2020 | return fn; |
2021 | } |
2022 | |
2023 | /* Locate the copy ctor of TYPE. */ |
2024 | |
2025 | tree |
2026 | get_copy_ctor (tree type, tsubst_flags_t complain) |
2027 | { |
2028 | int quals = (TYPE_HAS_CONST_COPY_CTOR (type) |
2029 | ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED); |
2030 | tree argtype = build_stub_type (type, quals, rvalue: false); |
2031 | tree fn = locate_fn_flags (type, complete_ctor_identifier, argtype, |
2032 | LOOKUP_NORMAL, complain); |
2033 | if (fn == error_mark_node) |
2034 | return NULL_TREE; |
2035 | return fn; |
2036 | } |
2037 | |
2038 | /* Locate the copy assignment operator of TYPE. */ |
2039 | |
2040 | tree |
2041 | get_copy_assign (tree type) |
2042 | { |
2043 | int quals = (TYPE_HAS_CONST_COPY_ASSIGN (type) |
2044 | ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED); |
2045 | tree argtype = build_stub_type (type, quals, rvalue: false); |
2046 | tree fn = locate_fn_flags (type, assign_op_identifier, argtype, |
2047 | LOOKUP_NORMAL, complain: tf_warning_or_error); |
2048 | if (fn == error_mark_node) |
2049 | return NULL_TREE; |
2050 | return fn; |
2051 | } |
2052 | |
2053 | /* walk_tree helper function for is_trivially_xible. If *TP is a call, |
2054 | return it if it calls something other than a trivial special member |
2055 | function. */ |
2056 | |
2057 | static tree |
2058 | check_nontriv (tree *tp, int *, void *) |
2059 | { |
2060 | tree fn = cp_get_callee (*tp); |
2061 | if (fn == NULL_TREE) |
2062 | return NULL_TREE; |
2063 | |
2064 | if (TREE_CODE (fn) == ADDR_EXPR) |
2065 | fn = TREE_OPERAND (fn, 0); |
2066 | |
2067 | if (TREE_CODE (fn) != FUNCTION_DECL |
2068 | || !trivial_fn_p (fn)) |
2069 | return fn; |
2070 | return NULL_TREE; |
2071 | } |
2072 | |
2073 | /* Return declval<T>() = declval<U>() treated as an unevaluated operand. */ |
2074 | |
2075 | static tree |
2076 | assignable_expr (tree to, tree from) |
2077 | { |
2078 | cp_unevaluated cp_uneval_guard; |
2079 | to = build_trait_object (type: to); |
2080 | from = build_trait_object (type: from); |
2081 | tree r = cp_build_modify_expr (input_location, to, NOP_EXPR, from, tf_none); |
2082 | return r; |
2083 | } |
2084 | |
2085 | /* The predicate condition for a template specialization |
2086 | is_constructible<T, Args...> shall be satisfied if and only if the |
2087 | following variable definition would be well-formed for some invented |
2088 | variable t: T t(create<Args>()...); |
2089 | |
2090 | Return something equivalent in well-formedness and triviality. */ |
2091 | |
2092 | static tree |
2093 | constructible_expr (tree to, tree from) |
2094 | { |
2095 | tree expr; |
2096 | cp_unevaluated cp_uneval_guard; |
2097 | const int len = TREE_VEC_LENGTH (from); |
2098 | if (CLASS_TYPE_P (to)) |
2099 | { |
2100 | tree ctype = to; |
2101 | vec<tree, va_gc> *args = NULL; |
2102 | if (!TYPE_REF_P (to)) |
2103 | to = cp_build_reference_type (to, /*rval*/false); |
2104 | tree ob = build_stub_object (reftype: to); |
2105 | if (len == 0) |
2106 | expr = build_value_init (ctype, tf_none); |
2107 | else |
2108 | { |
2109 | vec_alloc (v&: args, nelems: len); |
2110 | for (tree arg : tree_vec_range (from)) |
2111 | args->quick_push (obj: build_stub_object (reftype: arg)); |
2112 | expr = build_special_member_call (ob, complete_ctor_identifier, &args, |
2113 | ctype, LOOKUP_NORMAL, tf_none); |
2114 | } |
2115 | if (expr == error_mark_node) |
2116 | return error_mark_node; |
2117 | /* The current state of the standard vis-a-vis LWG 2116 is that |
2118 | is_*constructible involves destruction as well. */ |
2119 | if (type_build_dtor_call (ctype)) |
2120 | { |
2121 | tree dtor = build_special_member_call (ob, complete_dtor_identifier, |
2122 | NULL, ctype, LOOKUP_NORMAL, |
2123 | tf_none); |
2124 | if (dtor == error_mark_node) |
2125 | return error_mark_node; |
2126 | if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (ctype)) |
2127 | expr = build2 (COMPOUND_EXPR, void_type_node, expr, dtor); |
2128 | } |
2129 | } |
2130 | else |
2131 | { |
2132 | if (len == 0) |
2133 | return build_value_init (strip_array_types (type: to), tf_none); |
2134 | if (len > 1) |
2135 | { |
2136 | if (cxx_dialect < cxx20) |
2137 | /* Too many initializers. */ |
2138 | return error_mark_node; |
2139 | |
2140 | /* In C++20 this is well-formed: |
2141 | using T = int[2]; |
2142 | T t(1, 2); |
2143 | which means that std::is_constructible_v<int[2], int, int> |
2144 | should be true. */ |
2145 | vec<constructor_elt, va_gc> *v; |
2146 | vec_alloc (v, nelems: len); |
2147 | for (tree arg : tree_vec_range (from)) |
2148 | { |
2149 | tree stub = build_stub_object (reftype: arg); |
2150 | constructor_elt elt = { NULL_TREE, .value: stub }; |
2151 | v->quick_push (obj: elt); |
2152 | } |
2153 | from = build_constructor (init_list_type_node, v); |
2154 | CONSTRUCTOR_IS_DIRECT_INIT (from) = true; |
2155 | CONSTRUCTOR_IS_PAREN_INIT (from) = true; |
2156 | } |
2157 | else |
2158 | from = build_stub_object (TREE_VEC_ELT (from, 0)); |
2159 | expr = perform_direct_initialization_if_possible (to, from, |
2160 | /*cast*/false, |
2161 | tf_none); |
2162 | /* If t(e) didn't work, maybe t{e} will. */ |
2163 | if (expr == NULL_TREE |
2164 | && len == 1 |
2165 | && cxx_dialect >= cxx20) |
2166 | { |
2167 | from = build_constructor_single (init_list_type_node, NULL_TREE, |
2168 | from); |
2169 | CONSTRUCTOR_IS_DIRECT_INIT (from) = true; |
2170 | CONSTRUCTOR_IS_PAREN_INIT (from) = true; |
2171 | expr = perform_direct_initialization_if_possible (to, from, |
2172 | /*cast*/false, |
2173 | tf_none); |
2174 | } |
2175 | } |
2176 | return expr; |
2177 | } |
2178 | |
2179 | /* Returns a tree iff TO is assignable (if CODE is MODIFY_EXPR) or |
2180 | constructible (otherwise) from FROM, which is a single type for |
2181 | assignment or a list of types for construction. */ |
2182 | |
2183 | static tree |
2184 | is_xible_helper (enum tree_code code, tree to, tree from, bool trivial) |
2185 | { |
2186 | to = complete_type (to); |
2187 | deferring_access_check_sentinel acs (dk_no_deferred); |
2188 | if (VOID_TYPE_P (to) || ABSTRACT_CLASS_TYPE_P (to) |
2189 | || (from && FUNC_OR_METHOD_TYPE_P (from) |
2190 | && (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from)))) |
2191 | return error_mark_node; |
2192 | tree expr; |
2193 | if (code == MODIFY_EXPR) |
2194 | expr = assignable_expr (to, from); |
2195 | else if (trivial && TREE_VEC_LENGTH (from) > 1 |
2196 | && cxx_dialect < cxx20) |
2197 | return error_mark_node; // only 0- and 1-argument ctors can be trivial |
2198 | // before C++20 aggregate paren init |
2199 | else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to)) |
2200 | return error_mark_node; // can't construct an array of unknown bound |
2201 | else |
2202 | expr = constructible_expr (to, from); |
2203 | return expr; |
2204 | } |
2205 | |
2206 | /* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or |
2207 | constructible (otherwise) from FROM, which is a single type for |
2208 | assignment or a list of types for construction. */ |
2209 | |
2210 | bool |
2211 | is_trivially_xible (enum tree_code code, tree to, tree from) |
2212 | { |
2213 | tree expr = is_xible_helper (code, to, from, /*trivial*/true); |
2214 | if (expr == NULL_TREE || expr == error_mark_node) |
2215 | return false; |
2216 | tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL); |
2217 | return !nt; |
2218 | } |
2219 | |
2220 | /* Returns true iff TO is nothrow assignable (if CODE is MODIFY_EXPR) or |
2221 | constructible (otherwise) from FROM, which is a single type for |
2222 | assignment or a list of types for construction. */ |
2223 | |
2224 | bool |
2225 | is_nothrow_xible (enum tree_code code, tree to, tree from) |
2226 | { |
2227 | ++cp_noexcept_operand; |
2228 | tree expr = is_xible_helper (code, to, from, /*trivial*/false); |
2229 | --cp_noexcept_operand; |
2230 | if (expr == NULL_TREE || expr == error_mark_node) |
2231 | return false; |
2232 | return expr_noexcept_p (expr, tf_none); |
2233 | } |
2234 | |
2235 | /* Returns true iff TO is assignable (if CODE is MODIFY_EXPR) or |
2236 | constructible (otherwise) from FROM, which is a single type for |
2237 | assignment or a list of types for construction. */ |
2238 | |
2239 | bool |
2240 | is_xible (enum tree_code code, tree to, tree from) |
2241 | { |
2242 | tree expr = is_xible_helper (code, to, from, /*trivial*/false); |
2243 | if (expr == error_mark_node) |
2244 | return false; |
2245 | return !!expr; |
2246 | } |
2247 | |
2248 | /* Return true iff conjunction_v<is_reference<T>, is_constructible<T, U>> is |
2249 | true, and the initialization |
2250 | T t(VAL<U>); // DIRECT_INIT_P |
2251 | or |
2252 | T t = VAL<U>; // !DIRECT_INIT_P |
2253 | binds t to a temporary object whose lifetime is extended. |
2254 | VAL<T> is defined in [meta.unary.prop]: |
2255 | -- If T is a reference or function type, VAL<T> is an expression with the |
2256 | same type and value category as declval<T>(). |
2257 | -- Otherwise, VAL<T> is a prvalue that initially has type T. */ |
2258 | |
2259 | bool |
2260 | ref_xes_from_temporary (tree to, tree from, bool direct_init_p) |
2261 | { |
2262 | /* Check is_reference<T>. */ |
2263 | if (!TYPE_REF_P (to)) |
2264 | return false; |
2265 | /* We don't check is_constructible<T, U>: if T isn't constructible |
2266 | from U, we won't be able to create a conversion. */ |
2267 | tree val = build_trait_object (type: from); |
2268 | if (val == error_mark_node) |
2269 | return false; |
2270 | if (!TYPE_REF_P (from) && TREE_CODE (from) != FUNCTION_TYPE) |
2271 | val = CLASS_TYPE_P (from) ? force_rvalue (val, tf_none) : rvalue (val); |
2272 | return ref_conv_binds_to_temporary (to, val, direct_init_p).is_true (); |
2273 | } |
2274 | |
2275 | /* Worker for is_{,nothrow_}convertible. Attempt to perform an implicit |
2276 | conversion from FROM to TO and return the result. */ |
2277 | |
2278 | static tree |
2279 | is_convertible_helper (tree from, tree to) |
2280 | { |
2281 | if (VOID_TYPE_P (from) && VOID_TYPE_P (to)) |
2282 | return integer_one_node; |
2283 | cp_unevaluated u; |
2284 | tree expr = build_trait_object (type: from); |
2285 | /* std::is_{,nothrow_}convertible test whether the imaginary function |
2286 | definition |
2287 | |
2288 | To test() { return std::declval<From>(); } |
2289 | |
2290 | is well-formed. A function can't return a function. */ |
2291 | if (FUNC_OR_METHOD_TYPE_P (to) || expr == error_mark_node) |
2292 | return error_mark_node; |
2293 | deferring_access_check_sentinel acs (dk_no_deferred); |
2294 | return perform_implicit_conversion (to, expr, tf_none); |
2295 | } |
2296 | |
2297 | /* Return true if FROM can be converted to TO using implicit conversions, |
2298 | or both FROM and TO are possibly cv-qualified void. NB: This doesn't |
2299 | implement the "Access checks are performed as if from a context unrelated |
2300 | to either type" restriction. */ |
2301 | |
2302 | bool |
2303 | is_convertible (tree from, tree to) |
2304 | { |
2305 | tree expr = is_convertible_helper (from, to); |
2306 | if (expr == error_mark_node) |
2307 | return false; |
2308 | return !!expr; |
2309 | } |
2310 | |
2311 | /* Like is_convertible, but the conversion is also noexcept. */ |
2312 | |
2313 | bool |
2314 | is_nothrow_convertible (tree from, tree to) |
2315 | { |
2316 | tree expr = is_convertible_helper (from, to); |
2317 | if (expr == NULL_TREE || expr == error_mark_node) |
2318 | return false; |
2319 | return expr_noexcept_p (expr, tf_none); |
2320 | } |
2321 | |
2322 | /* Categorize various special_function_kinds. */ |
2323 | #define SFK_CTOR_P(sfk) \ |
2324 | ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor) |
2325 | #define SFK_DTOR_P(sfk) \ |
2326 | ((sfk) == sfk_destructor || (sfk) == sfk_virtual_destructor) |
2327 | #define SFK_ASSIGN_P(sfk) \ |
2328 | ((sfk) == sfk_copy_assignment || (sfk) == sfk_move_assignment) |
2329 | #define SFK_COPY_P(sfk) \ |
2330 | ((sfk) == sfk_copy_constructor || (sfk) == sfk_copy_assignment) |
2331 | #define SFK_MOVE_P(sfk) \ |
2332 | ((sfk) == sfk_move_constructor || (sfk) == sfk_move_assignment) |
2333 | |
2334 | /* Subroutine of synthesized_method_walk. Update SPEC_P, TRIVIAL_P and |
2335 | DELETED_P or give an error message MSG with argument ARG. */ |
2336 | |
2337 | static void |
2338 | process_subob_fn (tree fn, special_function_kind sfk, tree *spec_p, |
2339 | bool *trivial_p, bool *deleted_p, bool *constexpr_p, |
2340 | bool diag, tree arg, bool dtor_from_ctor = false) |
2341 | { |
2342 | if (!fn || fn == error_mark_node) |
2343 | { |
2344 | if (deleted_p) |
2345 | *deleted_p = true; |
2346 | return; |
2347 | } |
2348 | |
2349 | if (spec_p) |
2350 | { |
2351 | if (!maybe_instantiate_noexcept (fn)) |
2352 | *spec_p = error_mark_node; |
2353 | else |
2354 | { |
2355 | tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); |
2356 | *spec_p = merge_exception_specifiers (*spec_p, raises); |
2357 | } |
2358 | } |
2359 | |
2360 | if (!trivial_fn_p (fn) && !dtor_from_ctor) |
2361 | { |
2362 | if (trivial_p) |
2363 | *trivial_p = false; |
2364 | if (TREE_CODE (arg) == FIELD_DECL |
2365 | && TREE_CODE (DECL_CONTEXT (arg)) == UNION_TYPE) |
2366 | { |
2367 | if (deleted_p) |
2368 | *deleted_p = true; |
2369 | if (diag) |
2370 | error ("union member %q+D with non-trivial %qD" , arg, fn); |
2371 | } |
2372 | } |
2373 | |
2374 | if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn)) |
2375 | { |
2376 | *constexpr_p = false; |
2377 | if (diag) |
2378 | { |
2379 | inform (DECL_SOURCE_LOCATION (fn), |
2380 | SFK_DTOR_P (sfk) |
2381 | ? G_("defaulted destructor calls non-%<constexpr%> %qD" ) |
2382 | : G_("defaulted constructor calls non-%<constexpr%> %qD" ), |
2383 | fn); |
2384 | explain_invalid_constexpr_fn (fn); |
2385 | } |
2386 | } |
2387 | } |
2388 | |
2389 | /* Subroutine of synthesized_method_walk to allow recursion into anonymous |
2390 | aggregates. If DTOR_FROM_CTOR is true, we're walking subobject destructors |
2391 | called from a synthesized constructor, in which case we don't consider |
2392 | the triviality of the subobject destructor. */ |
2393 | |
2394 | static void |
2395 | walk_field_subobs (tree fields, special_function_kind sfk, tree fnname, |
2396 | int quals, tree *spec_p, bool *trivial_p, |
2397 | bool *deleted_p, bool *constexpr_p, |
2398 | bool diag, int flags, tsubst_flags_t complain, |
2399 | bool dtor_from_ctor) |
2400 | { |
2401 | if (!fields) |
2402 | return; |
2403 | |
2404 | tree ctx = DECL_CONTEXT (fields); |
2405 | |
2406 | /* CWG2084: A defaulted default ctor for a union with a DMI only initializes |
2407 | that member, so don't check other members. */ |
2408 | enum { unknown, no, yes } |
2409 | only_dmi_mem = (sfk == sfk_constructor && TREE_CODE (ctx) == UNION_TYPE |
2410 | ? unknown : no); |
2411 | |
2412 | again: |
2413 | for (tree field = fields; field; field = DECL_CHAIN (field)) |
2414 | { |
2415 | tree mem_type, argtype, rval; |
2416 | |
2417 | if (TREE_CODE (field) != FIELD_DECL |
2418 | || DECL_ARTIFICIAL (field) |
2419 | || DECL_UNNAMED_BIT_FIELD (field)) |
2420 | continue; |
2421 | |
2422 | /* Variant members only affect deletedness. In particular, they don't |
2423 | affect the exception-specification of a user-provided destructor, |
2424 | which we're figuring out via get_defaulted_eh_spec. So if we aren't |
2425 | asking if this is deleted, don't even look up the function; we don't |
2426 | want an error about a deleted function we aren't actually calling. */ |
2427 | if (sfk == sfk_destructor && deleted_p == NULL |
2428 | && TREE_CODE (ctx) == UNION_TYPE) |
2429 | break; |
2430 | |
2431 | if (only_dmi_mem != no) |
2432 | { |
2433 | if (DECL_INITIAL (field)) |
2434 | only_dmi_mem = yes; |
2435 | else |
2436 | /* Don't check this until we know there's no DMI. */ |
2437 | continue; |
2438 | } |
2439 | |
2440 | mem_type = strip_array_types (TREE_TYPE (field)); |
2441 | if (SFK_ASSIGN_P (sfk)) |
2442 | { |
2443 | bool bad = true; |
2444 | if (CP_TYPE_CONST_P (mem_type) && !CLASS_TYPE_P (mem_type)) |
2445 | { |
2446 | if (diag) |
2447 | error ("non-static const member %q#D, cannot use default " |
2448 | "assignment operator" , field); |
2449 | } |
2450 | else if (TYPE_REF_P (mem_type)) |
2451 | { |
2452 | if (diag) |
2453 | error ("non-static reference member %q#D, cannot use " |
2454 | "default assignment operator" , field); |
2455 | } |
2456 | else |
2457 | bad = false; |
2458 | |
2459 | if (bad && deleted_p) |
2460 | *deleted_p = true; |
2461 | } |
2462 | else if (sfk == sfk_constructor || sfk == sfk_inheriting_constructor) |
2463 | { |
2464 | bool bad; |
2465 | |
2466 | if (DECL_INITIAL (field)) |
2467 | { |
2468 | if (diag && DECL_INITIAL (field) == error_mark_node) |
2469 | inform (DECL_SOURCE_LOCATION (field), |
2470 | "initializer for %q#D is invalid" , field); |
2471 | if (trivial_p) |
2472 | *trivial_p = false; |
2473 | /* Core 1351: If the field has an NSDMI that could throw, the |
2474 | default constructor is noexcept(false). */ |
2475 | if (spec_p) |
2476 | { |
2477 | tree nsdmi = get_nsdmi (field, /*ctor*/false, complain); |
2478 | if (nsdmi == error_mark_node) |
2479 | *spec_p = error_mark_node; |
2480 | else if (*spec_p != error_mark_node |
2481 | && !expr_noexcept_p (nsdmi, tf_none)) |
2482 | *spec_p = noexcept_false_spec; |
2483 | } |
2484 | /* Don't do the normal processing. */ |
2485 | continue; |
2486 | } |
2487 | |
2488 | bad = false; |
2489 | if (CP_TYPE_CONST_P (mem_type) |
2490 | && default_init_uninitialized_part (mem_type)) |
2491 | { |
2492 | if (diag) |
2493 | { |
2494 | error ("uninitialized const member in %q#T" , |
2495 | current_class_type); |
2496 | inform (DECL_SOURCE_LOCATION (field), |
2497 | "%q#D should be initialized" , field); |
2498 | } |
2499 | bad = true; |
2500 | } |
2501 | else if (TYPE_REF_P (mem_type)) |
2502 | { |
2503 | if (diag) |
2504 | { |
2505 | error ("uninitialized reference member in %q#T" , |
2506 | current_class_type); |
2507 | inform (DECL_SOURCE_LOCATION (field), |
2508 | "%q#D should be initialized" , field); |
2509 | } |
2510 | bad = true; |
2511 | } |
2512 | |
2513 | if (bad && deleted_p) |
2514 | *deleted_p = true; |
2515 | |
2516 | /* Before C++20, for an implicitly-defined default constructor to |
2517 | be constexpr, every member must have a user-provided default |
2518 | constructor or an explicit initializer. */ |
2519 | if (constexpr_p |
2520 | && cxx_dialect < cxx20 |
2521 | && !CLASS_TYPE_P (mem_type) |
2522 | && TREE_CODE (ctx) != UNION_TYPE) |
2523 | { |
2524 | *constexpr_p = false; |
2525 | if (diag) |
2526 | inform (DECL_SOURCE_LOCATION (field), |
2527 | "defaulted default constructor does not " |
2528 | "initialize %q#D" , field); |
2529 | } |
2530 | } |
2531 | else if (sfk == sfk_copy_constructor) |
2532 | { |
2533 | /* 12.8p11b5 */ |
2534 | if (TYPE_REF_P (mem_type) |
2535 | && TYPE_REF_IS_RVALUE (mem_type)) |
2536 | { |
2537 | if (diag) |
2538 | error ("copying non-static data member %q#D of rvalue " |
2539 | "reference type" , field); |
2540 | if (deleted_p) |
2541 | *deleted_p = true; |
2542 | } |
2543 | } |
2544 | |
2545 | if (!CLASS_TYPE_P (mem_type)) |
2546 | continue; |
2547 | |
2548 | if (ANON_AGGR_TYPE_P (mem_type)) |
2549 | { |
2550 | walk_field_subobs (TYPE_FIELDS (mem_type), sfk, fnname, quals, |
2551 | spec_p, trivial_p, deleted_p, constexpr_p, |
2552 | diag, flags, complain, dtor_from_ctor); |
2553 | continue; |
2554 | } |
2555 | |
2556 | if (SFK_COPY_P (sfk) || SFK_MOVE_P (sfk)) |
2557 | { |
2558 | int mem_quals = cp_type_quals (mem_type) | quals; |
2559 | if (DECL_MUTABLE_P (field)) |
2560 | mem_quals &= ~TYPE_QUAL_CONST; |
2561 | argtype = build_stub_type (type: mem_type, quals: mem_quals, SFK_MOVE_P (sfk)); |
2562 | } |
2563 | else |
2564 | argtype = NULL_TREE; |
2565 | |
2566 | rval = locate_fn_flags (type: mem_type, name: fnname, argtype, flags, complain); |
2567 | |
2568 | process_subob_fn (fn: rval, sfk, spec_p, trivial_p, deleted_p, |
2569 | constexpr_p, diag, arg: field, dtor_from_ctor); |
2570 | } |
2571 | |
2572 | /* We didn't find a DMI in this union, now check all the members. */ |
2573 | if (only_dmi_mem == unknown) |
2574 | { |
2575 | only_dmi_mem = no; |
2576 | goto again; |
2577 | } |
2578 | } |
2579 | |
2580 | /* Base walker helper for synthesized_method_walk. Inspect a direct |
2581 | or virtual base. BINFO is the parent type's binfo. BASE_BINFO is |
2582 | the base binfo of interests. All other parms are as for |
2583 | synthesized_method_walk, or its local vars. */ |
2584 | |
2585 | static tree |
2586 | synthesized_method_base_walk (tree binfo, tree base_binfo, |
2587 | special_function_kind sfk, tree fnname, int quals, |
2588 | tree *inheriting_ctor, tree inherited_parms, |
2589 | int flags, bool diag, |
2590 | tree *spec_p, bool *trivial_p, |
2591 | bool *deleted_p, bool *constexpr_p) |
2592 | { |
2593 | bool inherited_binfo = false; |
2594 | tree argtype = NULL_TREE; |
2595 | deferring_kind defer = dk_no_deferred; |
2596 | |
2597 | if (SFK_COPY_P (sfk) || SFK_MOVE_P (sfk)) |
2598 | argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, SFK_MOVE_P (sfk)); |
2599 | else if (inheriting_ctor |
2600 | && (inherited_binfo |
2601 | = binfo_inherited_from (binfo, init_binfo: base_binfo, inh: *inheriting_ctor))) |
2602 | { |
2603 | argtype = inherited_parms; |
2604 | /* Don't check access on the inherited constructor. */ |
2605 | if (flag_new_inheriting_ctors) |
2606 | defer = dk_deferred; |
2607 | } |
2608 | else if (cxx_dialect >= cxx14 && sfk == sfk_virtual_destructor |
2609 | && BINFO_VIRTUAL_P (base_binfo) |
2610 | && ABSTRACT_CLASS_TYPE_P (BINFO_TYPE (binfo))) |
2611 | /* Don't check access when looking at vbases of abstract class's |
2612 | virtual destructor. */ |
2613 | defer = dk_no_check; |
2614 | |
2615 | if (defer != dk_no_deferred) |
2616 | push_deferring_access_checks (defer); |
2617 | tree rval = locate_fn_flags (type: base_binfo, name: fnname, argtype, flags, |
2618 | complain: diag ? tf_warning_or_error : tf_none); |
2619 | if (defer != dk_no_deferred) |
2620 | pop_deferring_access_checks (); |
2621 | |
2622 | /* Replace an inherited template with the appropriate specialization. */ |
2623 | if (inherited_binfo && rval |
2624 | && DECL_P (*inheriting_ctor) && DECL_P (rval) |
2625 | && DECL_CONTEXT (*inheriting_ctor) == DECL_CONTEXT (rval)) |
2626 | *inheriting_ctor = DECL_CLONED_FUNCTION (rval); |
2627 | |
2628 | process_subob_fn (fn: rval, sfk, spec_p, trivial_p, deleted_p, |
2629 | constexpr_p, diag, BINFO_TYPE (base_binfo)); |
2630 | if (SFK_CTOR_P (sfk) |
2631 | && (!BINFO_VIRTUAL_P (base_binfo) |
2632 | || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))) |
2633 | { |
2634 | /* In a constructor we also need to check the subobject |
2635 | destructors for cleanup of partially constructed objects. */ |
2636 | tree dtor = locate_fn_flags (type: base_binfo, complete_dtor_identifier, |
2637 | NULL_TREE, flags, |
2638 | complain: diag ? tf_warning_or_error : tf_none); |
2639 | /* Note that we don't pass down trivial_p; the subobject |
2640 | destructors don't affect triviality of the constructor. Nor |
2641 | do they affect constexpr-ness (a constant expression doesn't |
2642 | throw) or exception-specification (a throw from one of the |
2643 | dtors would be a double-fault). */ |
2644 | process_subob_fn (fn: dtor, sfk, NULL, NULL, deleted_p, NULL, diag: false, |
2645 | BINFO_TYPE (base_binfo), /*dtor_from_ctor*/true); |
2646 | } |
2647 | |
2648 | return rval; |
2649 | } |
2650 | |
2651 | /* The caller wants to generate an implicit declaration of SFK for |
2652 | CTYPE which is const if relevant and CONST_P is set. If SPEC_P, |
2653 | TRIVIAL_P, DELETED_P or CONSTEXPR_P are non-null, set their |
2654 | referent appropriately. If DIAG is true, we're either being called |
2655 | from maybe_explain_implicit_delete to give errors, or if |
2656 | CONSTEXPR_P is non-null, from explain_invalid_constexpr_fn. */ |
2657 | |
2658 | static void |
2659 | synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, |
2660 | tree *spec_p, bool *trivial_p, bool *deleted_p, |
2661 | bool *constexpr_p, bool diag, |
2662 | tree *inheriting_ctor, tree inherited_parms) |
2663 | { |
2664 | tree binfo, base_binfo; |
2665 | int i; |
2666 | |
2667 | /* SFK must be exactly one category. */ |
2668 | gcc_checking_assert (SFK_DTOR_P(sfk) + SFK_CTOR_P(sfk) |
2669 | + SFK_ASSIGN_P(sfk) == 1); |
2670 | |
2671 | if (spec_p) |
2672 | *spec_p = (cxx_dialect >= cxx11 ? noexcept_true_spec : empty_except_spec); |
2673 | |
2674 | if (deleted_p) |
2675 | { |
2676 | /* "The closure type associated with a lambda-expression has a deleted |
2677 | default constructor and a deleted copy assignment operator." |
2678 | This is diagnosed in maybe_explain_implicit_delete. |
2679 | In C++20, only lambda-expressions with lambda-captures have those |
2680 | deleted. */ |
2681 | if (LAMBDA_TYPE_P (ctype) |
2682 | && (sfk == sfk_constructor || sfk == sfk_copy_assignment) |
2683 | && (cxx_dialect < cxx20 |
2684 | || LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (ctype)) |
2685 | || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE |
2686 | (CLASSTYPE_LAMBDA_EXPR (ctype)) != CPLD_NONE)) |
2687 | { |
2688 | *deleted_p = true; |
2689 | return; |
2690 | } |
2691 | |
2692 | *deleted_p = false; |
2693 | } |
2694 | |
2695 | bool check_vdtor = false; |
2696 | tree fnname; |
2697 | |
2698 | if (SFK_DTOR_P (sfk)) |
2699 | { |
2700 | check_vdtor = true; |
2701 | /* The synthesized method will call base dtors, but check complete |
2702 | here to avoid having to deal with VTT. */ |
2703 | fnname = complete_dtor_identifier; |
2704 | } |
2705 | else if (SFK_ASSIGN_P (sfk)) |
2706 | fnname = assign_op_identifier; |
2707 | else |
2708 | fnname = complete_ctor_identifier; |
2709 | |
2710 | gcc_assert ((sfk == sfk_inheriting_constructor) |
2711 | == (inheriting_ctor && *inheriting_ctor != NULL_TREE)); |
2712 | |
2713 | /* If that user-written default constructor would satisfy the |
2714 | requirements of a constexpr constructor (7.1.5), the |
2715 | implicitly-defined default constructor is constexpr. |
2716 | |
2717 | C++20: |
2718 | The implicitly-defined copy/move assignment operator is constexpr if |
2719 | - X is a literal type, and |
2720 | - the assignment operator selected to copy/move each direct base class |
2721 | subobject is a constexpr function, and |
2722 | - for each non-static data member of X that is of class type (or array |
2723 | thereof), the assignment operator selected to copy/move that |
2724 | member is a constexpr function. |
2725 | |
2726 | C++23: |
2727 | The implicitly-defined copy/move assignment operator is constexpr. */ |
2728 | if (constexpr_p) |
2729 | *constexpr_p = (SFK_CTOR_P (sfk) |
2730 | || (SFK_ASSIGN_P (sfk) && cxx_dialect >= cxx14) |
2731 | || (SFK_DTOR_P (sfk) && cxx_dialect >= cxx20)); |
2732 | |
2733 | bool expected_trivial = type_has_trivial_fn (ctype, sfk); |
2734 | if (trivial_p) |
2735 | *trivial_p = expected_trivial; |
2736 | |
2737 | /* The TYPE_HAS_COMPLEX_* flags tell us about constraints from base |
2738 | class versions and other properties of the type. But a subobject |
2739 | class can be trivially copyable and yet have overload resolution |
2740 | choose a template constructor for initialization, depending on |
2741 | rvalueness and cv-quals. And furthermore, a member in a base might |
2742 | be trivial but deleted or otherwise not callable. So we can't exit |
2743 | early in C++0x. The same considerations apply in C++98/03, but |
2744 | there the definition of triviality does not consider overload |
2745 | resolution, so a constructor can be trivial even if it would otherwise |
2746 | call a non-trivial constructor. */ |
2747 | if (expected_trivial |
2748 | && (!(SFK_COPY_P (sfk) || SFK_MOVE_P (sfk)) || cxx_dialect < cxx11)) |
2749 | { |
2750 | if (constexpr_p && sfk == sfk_constructor) |
2751 | { |
2752 | bool cx = trivial_default_constructor_is_constexpr (ctype); |
2753 | *constexpr_p = cx; |
2754 | if (diag && !cx && TREE_CODE (ctype) == UNION_TYPE) |
2755 | /* A trivial constructor doesn't have any NSDMI. */ |
2756 | inform (input_location, "defaulted default constructor does " |
2757 | "not initialize any non-static data member" ); |
2758 | } |
2759 | if (!diag && cxx_dialect < cxx11) |
2760 | return; |
2761 | } |
2762 | |
2763 | bool push_to_top = maybe_push_to_top_level (TYPE_NAME (ctype)); |
2764 | ++cp_unevaluated_operand; |
2765 | ++c_inhibit_evaluation_warnings; |
2766 | push_deferring_access_checks (dk_no_deferred); |
2767 | |
2768 | tree scope = push_scope (ctype); |
2769 | |
2770 | int flags = LOOKUP_NORMAL | LOOKUP_SPECULATIVE; |
2771 | if (sfk != sfk_inheriting_constructor) |
2772 | flags |= LOOKUP_DEFAULTED; |
2773 | |
2774 | tsubst_flags_t complain = diag ? tf_warning_or_error : tf_none; |
2775 | if (diag && spec_p) |
2776 | /* We're in get_defaulted_eh_spec; we don't actually want any walking |
2777 | diagnostics, we just want complain set. */ |
2778 | diag = false; |
2779 | int quals = const_p ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED; |
2780 | |
2781 | for (binfo = TYPE_BINFO (ctype), i = 0; |
2782 | BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) |
2783 | { |
2784 | if (!SFK_ASSIGN_P (sfk) && BINFO_VIRTUAL_P (base_binfo)) |
2785 | /* We'll handle virtual bases below. */ |
2786 | continue; |
2787 | |
2788 | tree fn = synthesized_method_base_walk (binfo, base_binfo, |
2789 | sfk, fnname, quals, |
2790 | inheriting_ctor, inherited_parms, |
2791 | flags, diag, spec_p, trivial_p, |
2792 | deleted_p, constexpr_p); |
2793 | |
2794 | if (diag && SFK_ASSIGN_P (sfk) && SFK_MOVE_P (sfk) |
2795 | && BINFO_VIRTUAL_P (base_binfo) |
2796 | && fn && TREE_CODE (fn) == FUNCTION_DECL |
2797 | && move_fn_p (fn) && !trivial_fn_p (fn) |
2798 | && vbase_has_user_provided_move_assign (BINFO_TYPE (base_binfo))) |
2799 | warning (OPT_Wvirtual_move_assign, |
2800 | "defaulted move assignment for %qT calls a non-trivial " |
2801 | "move assignment operator for virtual base %qT" , |
2802 | ctype, BINFO_TYPE (base_binfo)); |
2803 | |
2804 | if (check_vdtor && type_has_virtual_destructor (BINFO_TYPE (base_binfo))) |
2805 | { |
2806 | /* Unlike for base ctor/op=/dtor, for operator delete it's fine |
2807 | to have a null fn (no class-specific op delete). */ |
2808 | fn = locate_fn_flags (type: ctype, name: ovl_op_identifier (isass: false, code: DELETE_EXPR), |
2809 | ptr_type_node, flags, complain: tf_none); |
2810 | if (fn && fn == error_mark_node) |
2811 | { |
2812 | if (complain & tf_error) |
2813 | locate_fn_flags (type: ctype, name: ovl_op_identifier (isass: false, code: DELETE_EXPR), |
2814 | ptr_type_node, flags, complain); |
2815 | if (deleted_p) |
2816 | *deleted_p = true; |
2817 | } |
2818 | check_vdtor = false; |
2819 | } |
2820 | } |
2821 | |
2822 | vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (ctype); |
2823 | if (SFK_ASSIGN_P (sfk)) |
2824 | /* Already examined vbases above. */; |
2825 | else if (vec_safe_is_empty (v: vbases)) |
2826 | /* No virtual bases to worry about. */; |
2827 | else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14 |
2828 | /* DR 1658 specifies that vbases of abstract classes are |
2829 | ignored for both ctors and dtors. Except DR 2336 |
2830 | overrides that skipping when determing the eh-spec of a |
2831 | virtual destructor. */ |
2832 | && sfk != sfk_virtual_destructor) |
2833 | /* Vbase cdtors are not relevant. */; |
2834 | else |
2835 | { |
2836 | if (constexpr_p) |
2837 | *constexpr_p = false; |
2838 | |
2839 | FOR_EACH_VEC_ELT (*vbases, i, base_binfo) |
2840 | synthesized_method_base_walk (binfo, base_binfo, sfk, fnname, quals, |
2841 | inheriting_ctor, inherited_parms, |
2842 | flags, diag, |
2843 | spec_p, trivial_p, deleted_p, constexpr_p); |
2844 | } |
2845 | |
2846 | /* Now handle the non-static data members. */ |
2847 | walk_field_subobs (TYPE_FIELDS (ctype), sfk, fnname, quals, |
2848 | spec_p, trivial_p, deleted_p, constexpr_p, |
2849 | diag, flags, complain, /*dtor_from_ctor*/false); |
2850 | if (SFK_CTOR_P (sfk)) |
2851 | walk_field_subobs (TYPE_FIELDS (ctype), sfk: sfk_destructor, |
2852 | complete_dtor_identifier, quals: TYPE_UNQUALIFIED, |
2853 | NULL, NULL, deleted_p, NULL, |
2854 | diag: false, flags, complain, /*dtor_from_ctor*/true); |
2855 | |
2856 | pop_scope (scope); |
2857 | |
2858 | pop_deferring_access_checks (); |
2859 | --cp_unevaluated_operand; |
2860 | --c_inhibit_evaluation_warnings; |
2861 | maybe_pop_from_top_level (push_to_top); |
2862 | } |
2863 | |
2864 | /* DECL is a defaulted function whose exception specification is now |
2865 | needed. Return what it should be. */ |
2866 | |
2867 | tree |
2868 | get_defaulted_eh_spec (tree decl, tsubst_flags_t complain) |
2869 | { |
2870 | /* For DECL_MAYBE_DELETED this should already have been handled by |
2871 | synthesize_method. */ |
2872 | gcc_assert (!DECL_MAYBE_DELETED (decl)); |
2873 | |
2874 | if (DECL_CLONED_FUNCTION_P (decl)) |
2875 | decl = DECL_CLONED_FUNCTION (decl); |
2876 | special_function_kind sfk = special_function_p (decl); |
2877 | tree ctype = DECL_CONTEXT (decl); |
2878 | tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); |
2879 | tree parm_type = TREE_VALUE (parms); |
2880 | bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); |
2881 | tree spec = empty_except_spec; |
2882 | bool diag = !DECL_DELETED_FN (decl) && (complain & tf_error); |
2883 | tree inh = DECL_INHERITED_CTOR (decl); |
2884 | if (SFK_DTOR_P (sfk) && DECL_VIRTUAL_P (decl)) |
2885 | /* We have to examine virtual bases even if abstract. */ |
2886 | sfk = sfk_virtual_destructor; |
2887 | bool pushed = false; |
2888 | if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) |
2889 | pushed = push_tinst_level (decl); |
2890 | synthesized_method_walk (ctype, sfk, const_p, spec_p: &spec, NULL, NULL, |
2891 | NULL, diag, inheriting_ctor: &inh, inherited_parms: parms); |
2892 | if (pushed) |
2893 | pop_tinst_level (); |
2894 | return spec; |
2895 | } |
2896 | |
2897 | /* DECL is a deleted function. If it's implicitly deleted, explain why and |
2898 | return true; else return false. */ |
2899 | |
2900 | bool |
2901 | maybe_explain_implicit_delete (tree decl) |
2902 | { |
2903 | /* If decl is a clone, get the primary variant. */ |
2904 | decl = DECL_ORIGIN (decl); |
2905 | gcc_assert (DECL_DELETED_FN (decl)); |
2906 | if (DECL_DEFAULTED_FN (decl)) |
2907 | { |
2908 | /* Not marked GTY; it doesn't need to be GC'd or written to PCH. */ |
2909 | static hash_set<tree> *explained; |
2910 | |
2911 | special_function_kind sfk; |
2912 | location_t loc; |
2913 | bool informed; |
2914 | tree ctype; |
2915 | |
2916 | if (!explained) |
2917 | explained = new hash_set<tree>; |
2918 | if (explained->add (k: decl)) |
2919 | return true; |
2920 | |
2921 | sfk = special_function_p (decl); |
2922 | ctype = DECL_CONTEXT (decl); |
2923 | loc = input_location; |
2924 | input_location = DECL_SOURCE_LOCATION (decl); |
2925 | |
2926 | informed = false; |
2927 | if (LAMBDA_TYPE_P (ctype)) |
2928 | { |
2929 | informed = true; |
2930 | if (sfk == sfk_constructor) |
2931 | inform (DECL_SOURCE_LOCATION (decl), |
2932 | "a lambda closure type has a deleted default constructor" ); |
2933 | else if (sfk == sfk_copy_assignment) |
2934 | inform (DECL_SOURCE_LOCATION (decl), |
2935 | "a lambda closure type has a deleted copy assignment operator" ); |
2936 | else |
2937 | informed = false; |
2938 | } |
2939 | else if (DECL_ARTIFICIAL (decl) |
2940 | && (sfk == sfk_copy_assignment || sfk == sfk_copy_constructor) |
2941 | && classtype_has_move_assign_or_move_ctor_p (ctype, user_declared: true)) |
2942 | { |
2943 | inform (DECL_SOURCE_LOCATION (decl), |
2944 | "%q#D is implicitly declared as deleted because %qT " |
2945 | "declares a move constructor or move assignment operator" , |
2946 | decl, ctype); |
2947 | informed = true; |
2948 | } |
2949 | else if (sfk == sfk_inheriting_constructor) |
2950 | { |
2951 | tree binfo = inherited_ctor_binfo (fndecl: decl); |
2952 | if (TREE_CODE (binfo) != TREE_BINFO) |
2953 | { |
2954 | inform (DECL_SOURCE_LOCATION (decl), |
2955 | "%q#D inherits from multiple base subobjects" , |
2956 | decl); |
2957 | informed = true; |
2958 | } |
2959 | } |
2960 | if (!informed && sfk == sfk_comparison) |
2961 | { |
2962 | inform (DECL_SOURCE_LOCATION (decl), |
2963 | "%q#D is implicitly deleted because the default " |
2964 | "definition would be ill-formed:" , decl); |
2965 | build_comparison_op (fndecl: decl, defining: false, complain: tf_warning_or_error); |
2966 | } |
2967 | else if (!informed) |
2968 | { |
2969 | tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); |
2970 | bool const_p = false; |
2971 | if (parms) |
2972 | { |
2973 | tree parm_type = TREE_VALUE (parms); |
2974 | const_p = CP_TYPE_CONST_P (non_reference (parm_type)); |
2975 | } |
2976 | tree raises = NULL_TREE; |
2977 | bool deleted_p = false; |
2978 | tree scope = push_scope (ctype); |
2979 | tree inh = DECL_INHERITED_CTOR (decl); |
2980 | |
2981 | synthesized_method_walk (ctype, sfk, const_p, |
2982 | spec_p: &raises, NULL, deleted_p: &deleted_p, NULL, diag: false, |
2983 | inheriting_ctor: &inh, inherited_parms: parms); |
2984 | if (deleted_p) |
2985 | { |
2986 | inform (DECL_SOURCE_LOCATION (decl), |
2987 | "%q#D is implicitly deleted because the default " |
2988 | "definition would be ill-formed:" , decl); |
2989 | synthesized_method_walk (ctype, sfk, const_p, |
2990 | NULL, NULL, deleted_p: &deleted_p, NULL, diag: true, |
2991 | inheriting_ctor: &inh, inherited_parms: parms); |
2992 | } |
2993 | else if (!comp_except_specs |
2994 | (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)), |
2995 | raises, ce_normal)) |
2996 | inform (DECL_SOURCE_LOCATION (decl), "%q#F is implicitly " |
2997 | "deleted because its exception-specification does not " |
2998 | "match the implicit exception-specification %qX" , |
2999 | decl, raises); |
3000 | else if (flag_checking) |
3001 | gcc_unreachable (); |
3002 | |
3003 | pop_scope (scope); |
3004 | } |
3005 | |
3006 | input_location = loc; |
3007 | return true; |
3008 | } |
3009 | return false; |
3010 | } |
3011 | |
3012 | /* DECL is a defaulted function which was declared constexpr. Explain why |
3013 | it can't be constexpr. */ |
3014 | |
3015 | void |
3016 | explain_implicit_non_constexpr (tree decl) |
3017 | { |
3018 | tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); |
3019 | bool const_p = CP_TYPE_CONST_P (non_reference (TREE_VALUE (parms))); |
3020 | tree inh = DECL_INHERITED_CTOR (decl); |
3021 | bool dummy; |
3022 | special_function_kind sfk = special_function_p (decl); |
3023 | if (sfk == sfk_comparison) |
3024 | { |
3025 | DECL_DECLARED_CONSTEXPR_P (decl) = true; |
3026 | build_comparison_op (fndecl: decl, defining: false, complain: tf_warning_or_error); |
3027 | DECL_DECLARED_CONSTEXPR_P (decl) = false; |
3028 | } |
3029 | else |
3030 | synthesized_method_walk (DECL_CLASS_CONTEXT (decl), |
3031 | sfk, const_p, |
3032 | NULL, NULL, NULL, constexpr_p: &dummy, diag: true, |
3033 | inheriting_ctor: &inh, inherited_parms: parms); |
3034 | } |
3035 | |
3036 | /* DECL is an instantiation of an inheriting constructor template. Deduce |
3037 | the correct exception-specification and deletedness for this particular |
3038 | specialization. Return true if the deduction succeeds; false otherwise. */ |
3039 | |
3040 | bool |
3041 | deduce_inheriting_ctor (tree decl) |
3042 | { |
3043 | decl = DECL_ORIGIN (decl); |
3044 | gcc_assert (DECL_INHERITED_CTOR (decl)); |
3045 | tree spec; |
3046 | bool trivial, constexpr_, deleted; |
3047 | tree inh = DECL_INHERITED_CTOR (decl); |
3048 | synthesized_method_walk (DECL_CONTEXT (decl), sfk: sfk_inheriting_constructor, |
3049 | const_p: false, spec_p: &spec, trivial_p: &trivial, deleted_p: &deleted, constexpr_p: &constexpr_, |
3050 | /*diag*/false, |
3051 | inheriting_ctor: &inh, |
3052 | FUNCTION_FIRST_USER_PARMTYPE (decl)); |
3053 | if (spec == error_mark_node) |
3054 | return false; |
3055 | if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO) |
3056 | /* Inherited the same constructor from different base subobjects. */ |
3057 | deleted = true; |
3058 | DECL_DELETED_FN (decl) = deleted; |
3059 | TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); |
3060 | SET_DECL_INHERITED_CTOR (decl, inh); |
3061 | |
3062 | tree clone; |
3063 | FOR_EACH_CLONE (clone, decl) |
3064 | { |
3065 | DECL_DELETED_FN (clone) = deleted; |
3066 | TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec); |
3067 | SET_DECL_INHERITED_CTOR (clone, inh); |
3068 | } |
3069 | |
3070 | return true; |
3071 | } |
3072 | |
3073 | /* Implicitly declare the special function indicated by KIND, as a |
3074 | member of TYPE. For copy constructors and assignment operators, |
3075 | CONST_P indicates whether these functions should take a const |
3076 | reference argument or a non-const reference. |
3077 | Returns the FUNCTION_DECL for the implicitly declared function. */ |
3078 | |
3079 | tree |
3080 | implicitly_declare_fn (special_function_kind kind, tree type, |
3081 | bool const_p, tree pattern_fn, |
3082 | tree inherited_parms) |
3083 | { |
3084 | tree fn; |
3085 | tree parameter_types = void_list_node; |
3086 | tree return_type; |
3087 | tree fn_type; |
3088 | tree raises = empty_except_spec; |
3089 | tree rhs_parm_type = NULL_TREE; |
3090 | tree this_parm; |
3091 | tree name; |
3092 | HOST_WIDE_INT saved_processing_template_decl; |
3093 | bool deleted_p = false; |
3094 | bool constexpr_p = false; |
3095 | tree inherited_ctor = (kind == sfk_inheriting_constructor |
3096 | ? pattern_fn : NULL_TREE); |
3097 | |
3098 | /* Because we create declarations for implicitly declared functions |
3099 | lazily, we may be creating the declaration for a member of TYPE |
3100 | while in some completely different context. However, TYPE will |
3101 | never be a dependent class (because we never want to do lookups |
3102 | for implicitly defined functions in a dependent class). */ |
3103 | gcc_assert (!dependent_type_p (type)); |
3104 | |
3105 | /* If the member-specification does not explicitly declare any member or |
3106 | friend named operator==, an == operator function is declared |
3107 | implicitly for each three-way comparison operator function defined as |
3108 | defaulted in the member-specification, with the same access and |
3109 | function-definition and in the same class scope as the respective |
3110 | three-way comparison operator function, except that the return type is |
3111 | replaced with bool and the declarator-id is replaced with |
3112 | operator==. |
3113 | |
3114 | [Note: Such an implicitly-declared == operator for a class X is |
3115 | defined as defaulted in the definition of X and has the same |
3116 | parameter-declaration-clause and trailing requires-clause as the |
3117 | respective three-way comparison operator. It is declared with friend, |
3118 | virtual, constexpr, or consteval if the three-way comparison operator |
3119 | function is so declared. If the three-way comparison operator function |
3120 | has no noexcept-specifier, the implicitly-declared == operator |
3121 | function has an implicit exception specification (14.5) that may |
3122 | differ from the implicit exception specification of the three-way |
3123 | comparison operator function. --end note] */ |
3124 | if (kind == sfk_comparison) |
3125 | { |
3126 | fn = copy_operator_fn (pattern_fn, code: EQ_EXPR); |
3127 | DECL_ARTIFICIAL (fn) = 1; |
3128 | apply_deduced_return_type (fn, boolean_type_node); |
3129 | return fn; |
3130 | } |
3131 | |
3132 | /* Furthermore, we must set PROCESSING_TEMPLATE_DECL to zero here |
3133 | because we only create clones for constructors and destructors |
3134 | when not in a template. */ |
3135 | saved_processing_template_decl = processing_template_decl; |
3136 | processing_template_decl = 0; |
3137 | |
3138 | type = TYPE_MAIN_VARIANT (type); |
3139 | |
3140 | if (targetm.cxx.cdtor_returns_this ()) |
3141 | { |
3142 | if (kind == sfk_destructor) |
3143 | /* See comment in check_special_function_return_type. */ |
3144 | return_type = build_pointer_type (void_type_node); |
3145 | else |
3146 | return_type = build_pointer_type (type); |
3147 | } |
3148 | else |
3149 | return_type = void_type_node; |
3150 | |
3151 | int this_quals = TYPE_UNQUALIFIED; |
3152 | switch (kind) |
3153 | { |
3154 | case sfk_destructor: |
3155 | /* Destructor. */ |
3156 | name = dtor_identifier; |
3157 | break; |
3158 | |
3159 | case sfk_constructor: |
3160 | /* Default constructor. */ |
3161 | name = ctor_identifier; |
3162 | break; |
3163 | |
3164 | case sfk_copy_constructor: |
3165 | case sfk_copy_assignment: |
3166 | case sfk_move_constructor: |
3167 | case sfk_move_assignment: |
3168 | case sfk_inheriting_constructor: |
3169 | { |
3170 | if (kind == sfk_copy_assignment |
3171 | || kind == sfk_move_assignment) |
3172 | { |
3173 | return_type = build_reference_type (type); |
3174 | name = assign_op_identifier; |
3175 | } |
3176 | else |
3177 | name = ctor_identifier; |
3178 | |
3179 | if (kind == sfk_inheriting_constructor) |
3180 | parameter_types = inherited_parms; |
3181 | else |
3182 | { |
3183 | if (const_p) |
3184 | rhs_parm_type = cp_build_qualified_type (type, TYPE_QUAL_CONST); |
3185 | else |
3186 | rhs_parm_type = type; |
3187 | bool move_p = (kind == sfk_move_assignment |
3188 | || kind == sfk_move_constructor); |
3189 | rhs_parm_type = cp_build_reference_type (rhs_parm_type, move_p); |
3190 | |
3191 | parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types); |
3192 | } |
3193 | break; |
3194 | } |
3195 | |
3196 | default: |
3197 | gcc_unreachable (); |
3198 | } |
3199 | |
3200 | bool trivial_p = false; |
3201 | |
3202 | if (inherited_ctor) |
3203 | { |
3204 | /* For an inheriting constructor, just copy these flags from the |
3205 | inherited constructor until deduce_inheriting_ctor. */ |
3206 | raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (inherited_ctor)); |
3207 | deleted_p = DECL_DELETED_FN (inherited_ctor); |
3208 | constexpr_p = DECL_DECLARED_CONSTEXPR_P (inherited_ctor); |
3209 | } |
3210 | else if (cxx_dialect >= cxx11) |
3211 | { |
3212 | raises = noexcept_deferred_spec; |
3213 | synthesized_method_walk (ctype: type, sfk: kind, const_p, NULL, trivial_p: &trivial_p, |
3214 | deleted_p: &deleted_p, constexpr_p: &constexpr_p, diag: false, |
3215 | inheriting_ctor: &inherited_ctor, inherited_parms); |
3216 | } |
3217 | else |
3218 | synthesized_method_walk (ctype: type, sfk: kind, const_p, spec_p: &raises, trivial_p: &trivial_p, |
3219 | deleted_p: &deleted_p, constexpr_p: &constexpr_p, diag: false, |
3220 | inheriting_ctor: &inherited_ctor, inherited_parms); |
3221 | /* Don't bother marking a deleted constructor as constexpr. */ |
3222 | if (deleted_p) |
3223 | constexpr_p = false; |
3224 | /* A trivial copy/move constructor is also a constexpr constructor, |
3225 | unless the class has virtual bases (7.1.5p4). */ |
3226 | else if (trivial_p |
3227 | && cxx_dialect >= cxx11 |
3228 | && (kind == sfk_copy_constructor |
3229 | || kind == sfk_move_constructor) |
3230 | && !CLASSTYPE_VBASECLASSES (type)) |
3231 | gcc_assert (constexpr_p); |
3232 | |
3233 | if (!trivial_p && type_has_trivial_fn (ctype: type, sfk: kind)) |
3234 | type_set_nontrivial_flag (ctype: type, sfk: kind); |
3235 | |
3236 | /* Create the function. */ |
3237 | tree this_type = cp_build_qualified_type (type, this_quals); |
3238 | fn_type = build_method_type_directly (this_type, return_type, |
3239 | parameter_types); |
3240 | |
3241 | if (raises) |
3242 | { |
3243 | if (raises != error_mark_node) |
3244 | fn_type = build_exception_variant (fn_type, raises); |
3245 | else |
3246 | { |
3247 | /* Can happen, e.g., in C++98 mode for an ill-formed non-static data |
3248 | member initializer (c++/89914). Also, in C++98, we might have |
3249 | failed to deduce RAISES, so try again but complain this time. */ |
3250 | if (cxx_dialect < cxx11) |
3251 | synthesized_method_walk (ctype: type, sfk: kind, const_p, spec_p: &raises, trivial_p: nullptr, |
3252 | deleted_p: nullptr, constexpr_p: nullptr, /*diag=*/true, |
3253 | inheriting_ctor: &inherited_ctor, inherited_parms); |
3254 | /* We should have seen an error at this point. */ |
3255 | gcc_assert (seen_error ()); |
3256 | } |
3257 | } |
3258 | fn = build_lang_decl (FUNCTION_DECL, name, fn_type); |
3259 | if (kind != sfk_inheriting_constructor) |
3260 | DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type)); |
3261 | |
3262 | if (IDENTIFIER_OVL_OP_P (name)) |
3263 | { |
3264 | const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (name); |
3265 | DECL_OVERLOADED_OPERATOR_CODE_RAW (fn) = op->ovl_op_code; |
3266 | } |
3267 | else if (IDENTIFIER_CTOR_P (name)) |
3268 | DECL_CXX_CONSTRUCTOR_P (fn) = true; |
3269 | else if (IDENTIFIER_DTOR_P (name)) |
3270 | DECL_CXX_DESTRUCTOR_P (fn) = true; |
3271 | else |
3272 | gcc_unreachable (); |
3273 | |
3274 | SET_DECL_ALIGN (fn, MINIMUM_METHOD_BOUNDARY); |
3275 | |
3276 | /* Create the explicit arguments. */ |
3277 | if (rhs_parm_type) |
3278 | { |
3279 | /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we |
3280 | want its type to be included in the mangled function |
3281 | name. */ |
3282 | tree decl = cp_build_parm_decl (fn, NULL_TREE, rhs_parm_type); |
3283 | TREE_READONLY (decl) = 1; |
3284 | retrofit_lang_decl (decl); |
3285 | DECL_PARM_INDEX (decl) = DECL_PARM_LEVEL (decl) = 1; |
3286 | DECL_ARGUMENTS (fn) = decl; |
3287 | } |
3288 | else if (kind == sfk_inheriting_constructor) |
3289 | { |
3290 | tree *p = &DECL_ARGUMENTS (fn); |
3291 | int index = 1; |
3292 | for (tree parm = inherited_parms; parm && parm != void_list_node; |
3293 | parm = TREE_CHAIN (parm)) |
3294 | { |
3295 | *p = cp_build_parm_decl (fn, NULL_TREE, TREE_VALUE (parm)); |
3296 | retrofit_lang_decl (*p); |
3297 | DECL_PARM_LEVEL (*p) = 1; |
3298 | DECL_PARM_INDEX (*p) = index++; |
3299 | p = &DECL_CHAIN (*p); |
3300 | } |
3301 | SET_DECL_INHERITED_CTOR (fn, inherited_ctor); |
3302 | DECL_NONCONVERTING_P (fn) = DECL_NONCONVERTING_P (inherited_ctor); |
3303 | /* A constructor so declared has the same access as the corresponding |
3304 | constructor in X. */ |
3305 | TREE_PRIVATE (fn) = TREE_PRIVATE (inherited_ctor); |
3306 | TREE_PROTECTED (fn) = TREE_PROTECTED (inherited_ctor); |
3307 | /* Copy constexpr from the inherited constructor even if the |
3308 | inheriting constructor doesn't satisfy the requirements. */ |
3309 | constexpr_p = DECL_DECLARED_CONSTEXPR_P (inherited_ctor); |
3310 | tree inherited_ctor_fn = STRIP_TEMPLATE (inherited_ctor); |
3311 | /* Also copy any attributes. */ |
3312 | DECL_ATTRIBUTES (fn) = clone_attrs (DECL_ATTRIBUTES (inherited_ctor_fn)); |
3313 | DECL_DISREGARD_INLINE_LIMITS (fn) |
3314 | = DECL_DISREGARD_INLINE_LIMITS (inherited_ctor_fn); |
3315 | } |
3316 | |
3317 | /* Add the "this" parameter. */ |
3318 | this_parm = build_this_parm (fn, fn_type, this_quals); |
3319 | DECL_CHAIN (this_parm) = DECL_ARGUMENTS (fn); |
3320 | DECL_ARGUMENTS (fn) = this_parm; |
3321 | |
3322 | grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL); |
3323 | |
3324 | DECL_IN_AGGR_P (fn) = 1; |
3325 | DECL_ARTIFICIAL (fn) = 1; |
3326 | DECL_DEFAULTED_FN (fn) = 1; |
3327 | if (cxx_dialect >= cxx11) |
3328 | { |
3329 | DECL_DELETED_FN (fn) = deleted_p; |
3330 | DECL_DECLARED_CONSTEXPR_P (fn) = constexpr_p; |
3331 | } |
3332 | DECL_EXTERNAL (fn) = true; |
3333 | DECL_NOT_REALLY_EXTERN (fn) = 1; |
3334 | DECL_DECLARED_INLINE_P (fn) = 1; |
3335 | set_linkage_according_to_type (type, fn); |
3336 | if (TREE_PUBLIC (fn)) |
3337 | DECL_COMDAT (fn) = 1; |
3338 | rest_of_decl_compilation (fn, namespace_bindings_p (), at_eof); |
3339 | gcc_assert (!TREE_USED (fn)); |
3340 | |
3341 | /* Propagate constraints from the inherited constructor. */ |
3342 | if (flag_concepts && inherited_ctor) |
3343 | if (tree orig_ci = get_constraints (inherited_ctor)) |
3344 | { |
3345 | tree new_ci = copy_node (orig_ci); |
3346 | set_constraints (fn, new_ci); |
3347 | } |
3348 | |
3349 | /* Restore PROCESSING_TEMPLATE_DECL. */ |
3350 | processing_template_decl = saved_processing_template_decl; |
3351 | |
3352 | if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL) |
3353 | fn = add_inherited_template_parms (fn, inherited_ctor); |
3354 | |
3355 | /* Warn about calling a non-trivial move assignment in a virtual base. */ |
3356 | if (kind == sfk_move_assignment && !deleted_p && !trivial_p |
3357 | && CLASSTYPE_VBASECLASSES (type)) |
3358 | { |
3359 | location_t loc = input_location; |
3360 | input_location = DECL_SOURCE_LOCATION (fn); |
3361 | synthesized_method_walk (ctype: type, sfk: kind, const_p, |
3362 | NULL, NULL, NULL, NULL, diag: true, |
3363 | NULL, NULL_TREE); |
3364 | input_location = loc; |
3365 | } |
3366 | |
3367 | return fn; |
3368 | } |
3369 | |
3370 | /* Gives any errors about defaulted functions which need to be deferred |
3371 | until the containing class is complete. */ |
3372 | |
3373 | void |
3374 | defaulted_late_check (tree fn) |
3375 | { |
3376 | /* Complain about invalid signature for defaulted fn. */ |
3377 | tree ctx = DECL_CONTEXT (fn); |
3378 | special_function_kind kind = special_function_p (fn); |
3379 | |
3380 | if (kind == sfk_comparison) |
3381 | { |
3382 | /* If the function was declared constexpr, check that the definition |
3383 | qualifies. Otherwise we can define the function lazily. */ |
3384 | if (DECL_DECLARED_CONSTEXPR_P (fn) && !DECL_INITIAL (fn)) |
3385 | { |
3386 | /* Prevent GC. */ |
3387 | function_depth++; |
3388 | synthesize_method (fndecl: fn); |
3389 | function_depth--; |
3390 | } |
3391 | return; |
3392 | } |
3393 | |
3394 | bool fn_const_p = (copy_fn_p (fn) == 2); |
3395 | tree implicit_fn = implicitly_declare_fn (kind, type: ctx, const_p: fn_const_p, |
3396 | NULL, NULL); |
3397 | tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn)); |
3398 | |
3399 | /* Includes special handling for a default xobj operator. */ |
3400 | auto compare_fn_params = [](tree fn, tree implicit_fn){ |
3401 | tree fn_parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); |
3402 | tree implicit_fn_parms = TYPE_ARG_TYPES (TREE_TYPE (implicit_fn)); |
3403 | |
3404 | if (DECL_XOBJ_MEMBER_FUNCTION_P (fn)) |
3405 | { |
3406 | tree fn_obj_ref_type = TREE_VALUE (fn_parms); |
3407 | /* We can't default xobj operators with an xobj parameter that is not |
3408 | an lvalue reference, even if it would correspond. */ |
3409 | if (!TYPE_REF_P (fn_obj_ref_type) |
3410 | || TYPE_REF_IS_RVALUE (fn_obj_ref_type) |
3411 | || !object_parms_correspond (fn, implicit_fn, |
3412 | DECL_CONTEXT (implicit_fn))) |
3413 | return false; |
3414 | /* We just compared the object parameters, skip over them before |
3415 | passing to compparms. */ |
3416 | fn_parms = TREE_CHAIN (fn_parms); |
3417 | implicit_fn_parms = TREE_CHAIN (implicit_fn_parms); |
3418 | } |
3419 | return compparms (fn_parms, implicit_fn_parms); |
3420 | }; |
3421 | |
3422 | if (!same_type_p (TREE_TYPE (TREE_TYPE (fn)), |
3423 | TREE_TYPE (TREE_TYPE (implicit_fn))) |
3424 | || !compare_fn_params (fn, implicit_fn)) |
3425 | { |
3426 | error ("defaulted declaration %q+D does not match the " |
3427 | "expected signature" , fn); |
3428 | inform (DECL_SOURCE_LOCATION (fn), |
3429 | "expected signature: %qD" , implicit_fn); |
3430 | } |
3431 | |
3432 | if (DECL_DELETED_FN (implicit_fn)) |
3433 | { |
3434 | DECL_DELETED_FN (fn) = 1; |
3435 | return; |
3436 | } |
3437 | |
3438 | /* If a function is explicitly defaulted on its first declaration without an |
3439 | exception-specification, it is implicitly considered to have the same |
3440 | exception-specification as if it had been implicitly declared. */ |
3441 | if (!TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)) |
3442 | && DECL_DEFAULTED_IN_CLASS_P (fn)) |
3443 | TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec); |
3444 | |
3445 | if (DECL_DEFAULTED_IN_CLASS_P (fn) |
3446 | && DECL_DECLARED_CONSTEXPR_P (implicit_fn)) |
3447 | { |
3448 | /* Hmm...should we do this for out-of-class too? Should it be OK to |
3449 | add constexpr later like inline, rather than requiring |
3450 | declarations to match? */ |
3451 | DECL_DECLARED_CONSTEXPR_P (fn) = true; |
3452 | if (kind == sfk_constructor) |
3453 | TYPE_HAS_CONSTEXPR_CTOR (ctx) = true; |
3454 | } |
3455 | |
3456 | if (!DECL_DECLARED_CONSTEXPR_P (implicit_fn) |
3457 | && DECL_DECLARED_CONSTEXPR_P (fn)) |
3458 | { |
3459 | if (!CLASSTYPE_TEMPLATE_INSTANTIATION (ctx)) |
3460 | { |
3461 | error ("explicitly defaulted function %q+D cannot be declared " |
3462 | "%qs because the implicit declaration is not %qs:" , fn, |
3463 | DECL_IMMEDIATE_FUNCTION_P (fn) ? "consteval" : "constexpr" , |
3464 | "constexpr" ); |
3465 | explain_implicit_non_constexpr (decl: fn); |
3466 | } |
3467 | DECL_DECLARED_CONSTEXPR_P (fn) = false; |
3468 | } |
3469 | } |
3470 | |
3471 | /* Returns true iff FN can be explicitly defaulted, and gives any |
3472 | errors if defaulting FN is ill-formed. */ |
3473 | |
3474 | bool |
3475 | defaultable_fn_check (tree fn) |
3476 | { |
3477 | special_function_kind kind = sfk_none; |
3478 | |
3479 | if (template_parm_scope_p ()) |
3480 | { |
3481 | error ("a template cannot be defaulted" ); |
3482 | return false; |
3483 | } |
3484 | |
3485 | if (DECL_CONSTRUCTOR_P (fn)) |
3486 | { |
3487 | if (FUNCTION_FIRST_USER_PARMTYPE (fn) == void_list_node) |
3488 | kind = sfk_constructor; |
3489 | else if (copy_fn_p (fn) > 0 |
3490 | && (TREE_CHAIN (FUNCTION_FIRST_USER_PARMTYPE (fn)) |
3491 | == void_list_node)) |
3492 | kind = sfk_copy_constructor; |
3493 | else if (move_fn_p (fn)) |
3494 | kind = sfk_move_constructor; |
3495 | } |
3496 | else if (DECL_DESTRUCTOR_P (fn)) |
3497 | kind = sfk_destructor; |
3498 | else if (DECL_ASSIGNMENT_OPERATOR_P (fn) |
3499 | && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR)) |
3500 | { |
3501 | if (copy_fn_p (fn)) |
3502 | kind = sfk_copy_assignment; |
3503 | else if (move_fn_p (fn)) |
3504 | kind = sfk_move_assignment; |
3505 | } |
3506 | else if (DECL_OVERLOADED_OPERATOR_CODE_RAW (fn) >= OVL_OP_EQ_EXPR |
3507 | && DECL_OVERLOADED_OPERATOR_CODE_RAW (fn) <= OVL_OP_SPACESHIP_EXPR) |
3508 | { |
3509 | kind = sfk_comparison; |
3510 | if (!early_check_defaulted_comparison (fn)) |
3511 | return false; |
3512 | } |
3513 | |
3514 | /* FIXME: We need to check for xobj member functions here to give better |
3515 | diagnostics for weird cases where unrelated xobj parameters are given. |
3516 | We just want to do better than 'cannot be defaulted'. */ |
3517 | |
3518 | if (kind == sfk_none) |
3519 | { |
3520 | error ("%qD cannot be defaulted" , fn); |
3521 | return false; |
3522 | } |
3523 | else |
3524 | { |
3525 | for (tree t = FUNCTION_FIRST_USER_PARMTYPE (fn); |
3526 | t && t != void_list_node; t = TREE_CHAIN (t)) |
3527 | if (TREE_PURPOSE (t)) |
3528 | { |
3529 | error ("defaulted function %q+D with default argument" , fn); |
3530 | break; |
3531 | } |
3532 | |
3533 | /* Avoid do_warn_unused_parameter warnings. */ |
3534 | for (tree p = FUNCTION_FIRST_USER_PARM (fn); p; p = DECL_CHAIN (p)) |
3535 | if (DECL_NAME (p)) |
3536 | suppress_warning (p, OPT_Wunused_parameter); |
3537 | |
3538 | if (current_class_type && TYPE_BEING_DEFINED (current_class_type)) |
3539 | /* Defer checking. */; |
3540 | else if (!processing_template_decl) |
3541 | defaulted_late_check (fn); |
3542 | |
3543 | return true; |
3544 | } |
3545 | } |
3546 | |
3547 | /* Add an implicit declaration to TYPE for the kind of function |
3548 | indicated by SFK. Return the FUNCTION_DECL for the new implicit |
3549 | declaration. */ |
3550 | |
3551 | tree |
3552 | lazily_declare_fn (special_function_kind sfk, tree type) |
3553 | { |
3554 | tree fn; |
3555 | /* Whether or not the argument has a const reference type. */ |
3556 | bool const_p = false; |
3557 | |
3558 | type = TYPE_MAIN_VARIANT (type); |
3559 | |
3560 | switch (sfk) |
3561 | { |
3562 | case sfk_constructor: |
3563 | CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0; |
3564 | break; |
3565 | case sfk_copy_constructor: |
3566 | const_p = TYPE_HAS_CONST_COPY_CTOR (type); |
3567 | CLASSTYPE_LAZY_COPY_CTOR (type) = 0; |
3568 | break; |
3569 | case sfk_move_constructor: |
3570 | CLASSTYPE_LAZY_MOVE_CTOR (type) = 0; |
3571 | break; |
3572 | case sfk_copy_assignment: |
3573 | const_p = TYPE_HAS_CONST_COPY_ASSIGN (type); |
3574 | CLASSTYPE_LAZY_COPY_ASSIGN (type) = 0; |
3575 | break; |
3576 | case sfk_move_assignment: |
3577 | CLASSTYPE_LAZY_MOVE_ASSIGN (type) = 0; |
3578 | break; |
3579 | case sfk_destructor: |
3580 | CLASSTYPE_LAZY_DESTRUCTOR (type) = 0; |
3581 | break; |
3582 | default: |
3583 | gcc_unreachable (); |
3584 | } |
3585 | |
3586 | /* Declare the function. */ |
3587 | fn = implicitly_declare_fn (kind: sfk, type, const_p, NULL, NULL); |
3588 | |
3589 | /* [class.copy]/8 If the class definition declares a move constructor or |
3590 | move assignment operator, the implicitly declared copy constructor is |
3591 | defined as deleted.... */ |
3592 | if ((sfk == sfk_copy_assignment || sfk == sfk_copy_constructor) |
3593 | && cxx_dialect >= cxx11) |
3594 | { |
3595 | if (classtype_has_move_assign_or_move_ctor_p (type, user_declared: true)) |
3596 | DECL_DELETED_FN (fn) = true; |
3597 | else if (classtype_has_depr_implicit_copy (type)) |
3598 | /* The implicit definition of a copy constructor as defaulted is |
3599 | deprecated if the class has a user-declared copy assignment operator |
3600 | or a user-declared destructor. The implicit definition of a copy |
3601 | assignment operator as defaulted is deprecated if the class has a |
3602 | user-declared copy constructor or a user-declared destructor (15.4, |
3603 | 15.8). */ |
3604 | TREE_DEPRECATED (fn) = true; |
3605 | } |
3606 | |
3607 | /* Destructors and assignment operators may be virtual. */ |
3608 | if (sfk == sfk_destructor |
3609 | || sfk == sfk_move_assignment |
3610 | || sfk == sfk_copy_assignment) |
3611 | check_for_override (fn, type); |
3612 | |
3613 | /* Add it to the class */ |
3614 | bool added = add_method (type, fn, false); |
3615 | gcc_assert (added || errorcount); |
3616 | |
3617 | /* Add it to TYPE_FIELDS. */ |
3618 | if (sfk == sfk_destructor |
3619 | && DECL_VIRTUAL_P (fn)) |
3620 | /* The ABI requires that a virtual destructor go at the end of the |
3621 | vtable. */ |
3622 | TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), fn); |
3623 | else |
3624 | { |
3625 | DECL_CHAIN (fn) = TYPE_FIELDS (type); |
3626 | TYPE_FIELDS (type) = fn; |
3627 | } |
3628 | /* Propagate TYPE_FIELDS. */ |
3629 | fixup_type_variants (type); |
3630 | |
3631 | maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); |
3632 | if (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn)) |
3633 | /* Create appropriate clones. */ |
3634 | clone_cdtor (fn, /*update_methods=*/true); |
3635 | |
3636 | /* Classes, structs or unions TYPE marked with hotness attributes propagate |
3637 | the attribute to all methods. This is typically done in |
3638 | check_bases_and_members, but we must also inject them here for deferred |
3639 | lazily-declared functions. */ |
3640 | maybe_propagate_warmth_attributes (fn, type); |
3641 | |
3642 | return fn; |
3643 | } |
3644 | |
3645 | /* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST |
3646 | as there are artificial parms in FN. */ |
3647 | |
3648 | tree |
3649 | skip_artificial_parms_for (const_tree fn, tree list) |
3650 | { |
3651 | if (DECL_IOBJ_MEMBER_FUNCTION_P (fn)) |
3652 | list = TREE_CHAIN (list); |
3653 | else |
3654 | return list; |
3655 | |
3656 | if (DECL_HAS_IN_CHARGE_PARM_P (fn)) |
3657 | list = TREE_CHAIN (list); |
3658 | if (DECL_HAS_VTT_PARM_P (fn)) |
3659 | list = TREE_CHAIN (list); |
3660 | return list; |
3661 | } |
3662 | |
3663 | /* Given a FUNCTION_DECL FN and a chain LIST, return the number of |
3664 | artificial parms in FN. */ |
3665 | |
3666 | int |
3667 | num_artificial_parms_for (const_tree fn) |
3668 | { |
3669 | int count = 0; |
3670 | |
3671 | if (DECL_IOBJ_MEMBER_FUNCTION_P (fn)) |
3672 | count++; |
3673 | else |
3674 | return 0; |
3675 | |
3676 | if (DECL_HAS_IN_CHARGE_PARM_P (fn)) |
3677 | count++; |
3678 | if (DECL_HAS_VTT_PARM_P (fn)) |
3679 | count++; |
3680 | return count; |
3681 | } |
3682 | |
3683 | |
3684 | #include "gt-cp-method.h" |
3685 | |