00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "config.h"
00031 #include "system.h"
00032 #include "coretypes.h"
00033 #include "tm.h"
00034 #include "tree.h"
00035 #include "cp-tree.h"
00036 #include "rtl.h"
00037 #include "expr.h"
00038 #include "output.h"
00039 #include "flags.h"
00040 #include "toplev.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "diagnostic.h"
00044
00045
00046
00047 enum mangling_flags
00048 {
00049
00050 mf_none = 0,
00051
00052
00053
00054
00055 mf_maybe_uninstantiated = 1,
00056
00057
00058 mf_use_underscores_around_value = 2
00059 };
00060
00061 typedef enum mangling_flags mangling_flags;
00062
00063 static tree thunk_adjust (tree, bool, HOST_WIDE_INT, tree);
00064 static void do_build_assign_ref (tree);
00065 static void do_build_copy_constructor (tree);
00066 static tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *);
00067 static tree locate_dtor (tree, void *);
00068 static tree locate_ctor (tree, void *);
00069 static tree locate_copy (tree, void *);
00070 static tree make_alias_for_thunk (tree);
00071
00072
00073
00074 void
00075 init_method (void)
00076 {
00077 init_mangle ();
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 tree
00090 make_thunk (tree function, bool this_adjusting,
00091 tree fixed_offset, tree virtual_offset)
00092 {
00093 HOST_WIDE_INT d;
00094 tree thunk;
00095
00096 gcc_assert (TREE_CODE (function) == FUNCTION_DECL);
00097
00098 gcc_assert (!DECL_THIS_THUNK_P (function));
00099 gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting);
00100
00101
00102 if (this_adjusting && virtual_offset)
00103 virtual_offset
00104 = size_binop (MULT_EXPR,
00105 virtual_offset,
00106 convert (ssizetype,
00107 TYPE_SIZE_UNIT (vtable_entry_type)));
00108
00109 d = tree_low_cst (fixed_offset, 0);
00110
00111
00112
00113
00114 for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
00115 if (DECL_THIS_THUNK_P (thunk) == this_adjusting
00116 && THUNK_FIXED_OFFSET (thunk) == d
00117 && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk)
00118 && (!virtual_offset
00119 || (this_adjusting
00120 ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),
00121 virtual_offset)
00122 : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)))
00123 return thunk;
00124
00125
00126
00127
00128 gcc_assert (!TREE_ASM_WRITTEN (function));
00129
00130
00131 gcc_assert (TYPE_SIZE (DECL_CONTEXT (function))
00132 && TYPE_BEING_DEFINED (DECL_CONTEXT (function)));
00133
00134 thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
00135 DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
00136 cxx_dup_lang_specific_decl (thunk);
00137 DECL_THUNKS (thunk) = NULL_TREE;
00138
00139 DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
00140 TREE_READONLY (thunk) = TREE_READONLY (function);
00141 TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
00142 TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
00143 if (flag_weak)
00144 comdat_linkage (thunk);
00145 SET_DECL_THUNK_P (thunk, this_adjusting);
00146 THUNK_TARGET (thunk) = function;
00147 THUNK_FIXED_OFFSET (thunk) = d;
00148 THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
00149 THUNK_ALIAS (thunk) = NULL_TREE;
00150
00151
00152
00153 DECL_INTERFACE_KNOWN (thunk) = 1;
00154 DECL_NOT_REALLY_EXTERN (thunk) = 1;
00155 DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
00156 DECL_DESTRUCTOR_P (thunk) = 0;
00157 DECL_CONSTRUCTOR_P (thunk) = 0;
00158 DECL_EXTERNAL (thunk) = 1;
00159 DECL_ARTIFICIAL (thunk) = 1;
00160
00161
00162 DECL_NO_STATIC_CHAIN (thunk) = 1;
00163
00164 DECL_PENDING_INLINE_P (thunk) = 0;
00165 DECL_INLINE (thunk) = 0;
00166 DECL_DECLARED_INLINE_P (thunk) = 0;
00167
00168 DECL_DEFERRED_FN (thunk) = 0;
00169
00170
00171 TREE_CHAIN (thunk) = DECL_THUNKS (function);
00172 DECL_THUNKS (function) = thunk;
00173
00174 return thunk;
00175 }
00176
00177
00178
00179 void
00180 finish_thunk (tree thunk)
00181 {
00182 tree function, name;
00183 tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk));
00184 tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk);
00185
00186 gcc_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk));
00187 if (virtual_offset && DECL_RESULT_THUNK_P (thunk))
00188 virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
00189 function = THUNK_TARGET (thunk);
00190 name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
00191 fixed_offset, virtual_offset);
00192
00193
00194
00195
00196
00197
00198 if (DECL_RESULT_THUNK_P (thunk))
00199 {
00200 tree cov_probe;
00201
00202 for (cov_probe = DECL_THUNKS (function);
00203 cov_probe; cov_probe = TREE_CHAIN (cov_probe))
00204 if (DECL_NAME (cov_probe) == name)
00205 {
00206 gcc_assert (!DECL_THUNKS (thunk));
00207 THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe)
00208 ? THUNK_ALIAS (cov_probe) : cov_probe);
00209 break;
00210 }
00211 }
00212
00213 DECL_NAME (thunk) = name;
00214 SET_DECL_ASSEMBLER_NAME (thunk, name);
00215 }
00216
00217
00218
00219
00220
00221
00222 static tree
00223 thunk_adjust (tree ptr, bool this_adjusting,
00224 HOST_WIDE_INT fixed_offset, tree virtual_offset)
00225 {
00226 if (this_adjusting)
00227
00228 ptr = fold (build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
00229 ssize_int (fixed_offset)));
00230
00231
00232
00233 if (virtual_offset)
00234 {
00235 tree vtable;
00236
00237 ptr = save_expr (ptr);
00238
00239 vtable = build1 (NOP_EXPR,
00240 build_pointer_type (build_pointer_type
00241 (vtable_entry_type)),
00242 ptr);
00243
00244 vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
00245
00246 vtable = build2 (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset);
00247
00248 vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
00249
00250 ptr = fold (build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable));
00251 }
00252
00253 if (!this_adjusting)
00254
00255 ptr = fold (build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
00256 ssize_int (fixed_offset)));
00257
00258 return ptr;
00259 }
00260
00261 static GTY (()) int thunk_labelno;
00262
00263
00264
00265 static tree
00266 make_alias_for_thunk (tree function)
00267 {
00268 tree alias;
00269 char buf[256];
00270
00271 ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
00272 thunk_labelno++;
00273 alias = build_decl (FUNCTION_DECL, get_identifier (buf),
00274 TREE_TYPE (function));
00275 DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
00276 cxx_dup_lang_specific_decl (alias);
00277 DECL_CONTEXT (alias) = NULL;
00278 TREE_READONLY (alias) = TREE_READONLY (function);
00279 TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
00280 TREE_PUBLIC (alias) = 0;
00281 DECL_INTERFACE_KNOWN (alias) = 1;
00282 DECL_NOT_REALLY_EXTERN (alias) = 1;
00283 DECL_THIS_STATIC (alias) = 1;
00284 DECL_SAVED_FUNCTION_DATA (alias) = NULL;
00285 DECL_DESTRUCTOR_P (alias) = 0;
00286 DECL_CONSTRUCTOR_P (alias) = 0;
00287 DECL_CLONED_FUNCTION (alias) = NULL_TREE;
00288 DECL_EXTERNAL (alias) = 0;
00289 DECL_ARTIFICIAL (alias) = 1;
00290 DECL_NO_STATIC_CHAIN (alias) = 1;
00291 DECL_PENDING_INLINE_P (alias) = 0;
00292 DECL_INLINE (alias) = 0;
00293 DECL_DECLARED_INLINE_P (alias) = 0;
00294 DECL_DEFERRED_FN (alias) = 0;
00295 DECL_USE_TEMPLATE (alias) = 0;
00296 DECL_TEMPLATE_INSTANTIATED (alias) = 0;
00297 DECL_TEMPLATE_INFO (alias) = NULL;
00298 DECL_INITIAL (alias) = error_mark_node;
00299 TREE_ADDRESSABLE (alias) = 1;
00300 TREE_USED (alias) = 1;
00301 SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
00302 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
00303 if (!flag_syntax_only)
00304 assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
00305 return alias;
00306 }
00307
00308
00309
00310
00311
00312 void
00313 use_thunk (tree thunk_fndecl, bool emit_p)
00314 {
00315 tree a, t, function, alias;
00316 tree virtual_offset;
00317 HOST_WIDE_INT fixed_offset, virtual_value;
00318 bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
00319
00320
00321 gcc_assert (DECL_NAME (thunk_fndecl));
00322
00323
00324
00325 gcc_assert (!THUNK_ALIAS (thunk_fndecl));
00326
00327 if (TREE_ASM_WRITTEN (thunk_fndecl))
00328 return;
00329
00330 function = THUNK_TARGET (thunk_fndecl);
00331 if (DECL_RESULT (thunk_fndecl))
00332
00333
00334 return;
00335
00336 if (DECL_THUNK_P (function))
00337
00338 use_thunk (function, emit_p);
00339
00340
00341 TREE_ADDRESSABLE (thunk_fndecl) = 1;
00342
00343
00344
00345 TREE_ADDRESSABLE (function) = 1;
00346 mark_used (function);
00347 if (!emit_p)
00348 return;
00349
00350 if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function))
00351 alias = make_alias_for_thunk (function);
00352 else
00353 alias = function;
00354
00355 fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
00356 virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
00357
00358 if (virtual_offset)
00359 {
00360 if (!this_adjusting)
00361 virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
00362 virtual_value = tree_low_cst (virtual_offset, 0);
00363 gcc_assert (virtual_value);
00364 }
00365 else
00366 virtual_value = 0;
00367
00368
00369 mark_used (thunk_fndecl);
00370
00371 DECL_EXTERNAL (thunk_fndecl) = 0;
00372
00373
00374 TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
00375 DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
00376 DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
00377 = DECL_VISIBILITY_SPECIFIED (function);
00378 if (flag_weak && TREE_PUBLIC (thunk_fndecl))
00379 comdat_linkage (thunk_fndecl);
00380
00381 if (flag_syntax_only)
00382 {
00383 TREE_ASM_WRITTEN (thunk_fndecl) = 1;
00384 return;
00385 }
00386
00387 push_to_top_level ();
00388
00389 if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)
00390 && targetm.have_named_sections)
00391 {
00392 resolve_unique_section (function, 0, flag_function_sections);
00393
00394 if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function))
00395 {
00396 resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
00397
00398
00399 DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
00400 }
00401 }
00402
00403 #ifdef KEY
00404 if (flag_spin_file)
00405 gspin_gxx_emits_thunk_decl (thunk_fndecl);
00406 #endif
00407
00408
00409
00410 DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
00411
00412
00413 t = NULL_TREE;
00414 for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
00415 {
00416 tree x = copy_node (a);
00417 TREE_CHAIN (x) = t;
00418 DECL_CONTEXT (x) = thunk_fndecl;
00419 SET_DECL_RTL (x, NULL_RTX);
00420 t = x;
00421 }
00422 a = nreverse (t);
00423 DECL_ARGUMENTS (thunk_fndecl) = a;
00424 BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a;
00425
00426 if (this_adjusting
00427 && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
00428 virtual_value, alias))
00429 {
00430 const char *fnname;
00431 current_function_decl = thunk_fndecl;
00432 DECL_RESULT (thunk_fndecl)
00433 = build_decl (RESULT_DECL, 0, integer_type_node);
00434 fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
00435 init_function_start (thunk_fndecl);
00436 current_function_is_thunk = 1;
00437 assemble_start_function (thunk_fndecl, fnname);
00438
00439 targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
00440 fixed_offset, virtual_value, alias);
00441
00442 assemble_end_function (thunk_fndecl, fnname);
00443 current_function_decl = 0;
00444 cfun = 0;
00445 TREE_ASM_WRITTEN (thunk_fndecl) = 1;
00446 }
00447 else
00448 {
00449
00450
00451
00452
00453
00454 if (varargs_function_p (function))
00455 error ("generic thunk code fails for method %q#D which uses %<...%>",
00456 function);
00457
00458 DECL_RESULT (thunk_fndecl) = NULL_TREE;
00459
00460 start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
00461
00462
00463
00464 push_deferring_access_checks (dk_no_check);
00465
00466 t = a;
00467 if (this_adjusting)
00468 t = thunk_adjust (t, 1,
00469 fixed_offset, virtual_offset);
00470
00471
00472 t = tree_cons (NULL_TREE, t, NULL_TREE);
00473 for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
00474 t = tree_cons (NULL_TREE, a, t);
00475 t = nreverse (t);
00476 t = build_call (alias, t);
00477 CALL_FROM_THUNK_P (t) = 1;
00478
00479 if (VOID_TYPE_P (TREE_TYPE (t)))
00480 finish_expr_stmt (t);
00481 else
00482 {
00483 if (!this_adjusting)
00484 {
00485 tree cond = NULL_TREE;
00486
00487 if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
00488 {
00489
00490
00491
00492
00493 t = save_expr (t);
00494 cond = cp_convert (boolean_type_node, t);
00495 }
00496
00497 t = thunk_adjust (t, 0,
00498 fixed_offset, virtual_offset);
00499 if (cond)
00500 t = build3 (COND_EXPR, TREE_TYPE (t), cond, t,
00501 cp_convert (TREE_TYPE (t), integer_zero_node));
00502 }
00503 t = force_target_expr (TREE_TYPE (t), t);
00504 finish_return_stmt (t);
00505 }
00506
00507
00508
00509 mark_decl_referenced (thunk_fndecl);
00510
00511
00512 DECL_IGNORED_P (thunk_fndecl) = 1;
00513
00514
00515 pop_deferring_access_checks ();
00516
00517 expand_body (finish_function (0));
00518 }
00519
00520 pop_from_top_level ();
00521 }
00522
00523
00524
00525
00526
00527 static void
00528 do_build_copy_constructor (tree fndecl)
00529 {
00530 tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
00531
00532 parm = convert_from_reference (parm);
00533
00534 if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
00535 && is_empty_class (current_class_type))
00536
00537 ;
00538 else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
00539 {
00540 tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
00541 finish_expr_stmt (t);
00542 }
00543 else
00544 {
00545 tree fields = TYPE_FIELDS (current_class_type);
00546 tree member_init_list = NULL_TREE;
00547 int cvquals = cp_type_quals (TREE_TYPE (parm));
00548 int i;
00549 tree binfo, base_binfo;
00550 VEC (tree) *vbases;
00551
00552
00553
00554
00555
00556
00557 for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
00558 VEC_iterate (tree, vbases, i, binfo); i++)
00559 {
00560 member_init_list
00561 = tree_cons (binfo,
00562 build_tree_list (NULL_TREE,
00563 build_base_path (PLUS_EXPR, parm,
00564 binfo, 1)),
00565 member_init_list);
00566 }
00567
00568 for (binfo = TYPE_BINFO (current_class_type), i = 0;
00569 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
00570 {
00571 if (BINFO_VIRTUAL_P (base_binfo))
00572 continue;
00573
00574 member_init_list
00575 = tree_cons (base_binfo,
00576 build_tree_list (NULL_TREE,
00577 build_base_path (PLUS_EXPR, parm,
00578 base_binfo, 1)),
00579 member_init_list);
00580 }
00581
00582 for (; fields; fields = TREE_CHAIN (fields))
00583 {
00584 tree init = parm;
00585 tree field = fields;
00586 tree expr_type;
00587
00588 if (TREE_CODE (field) != FIELD_DECL)
00589 continue;
00590
00591 expr_type = TREE_TYPE (field);
00592 if (DECL_NAME (field))
00593 {
00594 if (VFIELD_NAME_P (DECL_NAME (field)))
00595 continue;
00596 }
00597 else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
00598
00599 ;
00600 else
00601 continue;
00602
00603
00604
00605
00606
00607
00608 if (TREE_CODE (expr_type) != REFERENCE_TYPE)
00609 {
00610 int quals = cvquals;
00611
00612 if (DECL_MUTABLE_P (field))
00613 quals &= ~TYPE_QUAL_CONST;
00614 expr_type = cp_build_qualified_type (expr_type, quals);
00615 }
00616
00617 init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
00618 init = build_tree_list (NULL_TREE, init);
00619
00620 member_init_list = tree_cons (field, init, member_init_list);
00621 }
00622 finish_mem_initializers (member_init_list);
00623 }
00624 }
00625
00626 static void
00627 do_build_assign_ref (tree fndecl)
00628 {
00629 tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
00630 tree compound_stmt;
00631
00632 compound_stmt = begin_compound_stmt (0);
00633 parm = convert_from_reference (parm);
00634
00635 if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
00636 && is_empty_class (current_class_type))
00637
00638 ;
00639 else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
00640 {
00641 tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm);
00642 finish_expr_stmt (t);
00643 }
00644 else
00645 {
00646 tree fields;
00647 int cvquals = cp_type_quals (TREE_TYPE (parm));
00648 int i;
00649 tree binfo, base_binfo;
00650
00651
00652 for (binfo = TYPE_BINFO (current_class_type), i = 0;
00653 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
00654 {
00655 tree converted_parm;
00656
00657
00658
00659 converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
00660
00661 finish_expr_stmt
00662 (build_special_member_call (current_class_ref,
00663 ansi_assopname (NOP_EXPR),
00664 build_tree_list (NULL_TREE,
00665 converted_parm),
00666 base_binfo,
00667 LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
00668 }
00669
00670
00671 for (fields = TYPE_FIELDS (current_class_type);
00672 fields;
00673 fields = TREE_CHAIN (fields))
00674 {
00675 tree comp = current_class_ref;
00676 tree init = parm;
00677 tree field = fields;
00678 tree expr_type;
00679 int quals;
00680
00681 if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
00682 continue;
00683
00684 expr_type = TREE_TYPE (field);
00685
00686 if (CP_TYPE_CONST_P (expr_type))
00687 {
00688 error ("non-static const member %q#D, can't use default "
00689 "assignment operator", field);
00690 continue;
00691 }
00692 else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
00693 {
00694 error ("non-static reference member %q#D, can't use "
00695 "default assignment operator", field);
00696 continue;
00697 }
00698
00699 if (DECL_NAME (field))
00700 {
00701 if (VFIELD_NAME_P (DECL_NAME (field)))
00702 continue;
00703 }
00704 else if (ANON_AGGR_TYPE_P (expr_type)
00705 && TYPE_FIELDS (expr_type) != NULL_TREE)
00706
00707 ;
00708 else
00709 continue;
00710
00711 comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);
00712
00713
00714 quals = cvquals;
00715 if (DECL_MUTABLE_P (field))
00716 quals &= ~TYPE_QUAL_CONST;
00717 expr_type = cp_build_qualified_type (expr_type, quals);
00718
00719 init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
00720
00721 if (DECL_NAME (field))
00722 init = build_modify_expr (comp, NOP_EXPR, init);
00723 else
00724 init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
00725 finish_expr_stmt (init);
00726 }
00727 }
00728 finish_return_stmt (current_class_ref);
00729 finish_compound_stmt (compound_stmt);
00730 }
00731
00732
00733
00734 void
00735 synthesize_method (tree fndecl)
00736 {
00737 bool nested = (current_function_decl != NULL_TREE);
00738 tree context = decl_function_context (fndecl);
00739 bool need_body = true;
00740 tree stmt;
00741 location_t save_input_location = input_location;
00742 int error_count = errorcount;
00743 int warning_count = warningcount;
00744
00745
00746
00747 DECL_SOURCE_LOCATION (fndecl)
00748 = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl)));
00749
00750
00751
00752
00753 if (DECL_CLONED_FUNCTION_P (fndecl))
00754 fndecl = DECL_CLONED_FUNCTION (fndecl);
00755
00756
00757
00758 push_deferring_access_checks (dk_no_deferred);
00759
00760 if (! context)
00761 push_to_top_level ();
00762 else if (nested)
00763 push_function_context_to (context);
00764
00765 input_location = DECL_SOURCE_LOCATION (fndecl);
00766
00767 start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
00768 stmt = begin_function_body ();
00769
00770 if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
00771 {
00772 do_build_assign_ref (fndecl);
00773 need_body = false;
00774 }
00775 else if (DECL_CONSTRUCTOR_P (fndecl))
00776 {
00777 tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
00778 if (arg_chain != void_list_node)
00779 do_build_copy_constructor (fndecl);
00780 else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
00781 finish_mem_initializers (NULL_TREE);
00782 }
00783
00784
00785
00786 if (need_body)
00787 {
00788 tree compound_stmt;
00789 compound_stmt = begin_compound_stmt (BCS_FN_BODY);
00790 finish_compound_stmt (compound_stmt);
00791 }
00792
00793 finish_function_body (stmt);
00794 expand_or_defer_fn (finish_function (0));
00795
00796 input_location = save_input_location;
00797
00798 if (! context)
00799 pop_from_top_level ();
00800 else if (nested)
00801 pop_function_context_from (context);
00802
00803 pop_deferring_access_checks ();
00804
00805 if (error_count != errorcount || warning_count != warningcount)
00806 warning ("%Hsynthesized method %qD first required here ",
00807 &input_location, fndecl);
00808 }
00809
00810
00811
00812
00813
00814
00815
00816 static tree
00817 synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
00818 void *client)
00819 {
00820 tree raises = empty_except_spec;
00821 tree fields = TYPE_FIELDS (type);
00822 tree binfo, base_binfo;
00823 int i;
00824
00825 for (binfo = TYPE_BINFO (type), i = 0;
00826 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
00827 {
00828 tree fn = (*extractor) (BINFO_TYPE (base_binfo), client);
00829 if (fn)
00830 {
00831 tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
00832
00833 raises = merge_exception_specifiers (raises, fn_raises);
00834 }
00835 }
00836 for (; fields; fields = TREE_CHAIN (fields))
00837 {
00838 tree type = TREE_TYPE (fields);
00839 tree fn;
00840
00841 if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
00842 continue;
00843 while (TREE_CODE (type) == ARRAY_TYPE)
00844 type = TREE_TYPE (type);
00845 if (TREE_CODE (type) != RECORD_TYPE)
00846 continue;
00847
00848 fn = (*extractor) (type, client);
00849 if (fn)
00850 {
00851 tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
00852
00853 raises = merge_exception_specifiers (raises, fn_raises);
00854 }
00855 }
00856 return raises;
00857 }
00858
00859
00860
00861 static tree
00862 locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
00863 {
00864 return CLASSTYPE_DESTRUCTORS (type);
00865 }
00866
00867
00868
00869 static tree
00870 locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
00871 {
00872 tree fns;
00873
00874 if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
00875 return NULL_TREE;
00876
00877
00878
00879 if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
00880 return lazily_declare_fn (sfk_constructor, type);
00881
00882 for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
00883 {
00884 tree fn = OVL_CURRENT (fns);
00885 tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
00886
00887 if (sufficient_parms_p (TREE_CHAIN (parms)))
00888 return fn;
00889 }
00890 return NULL_TREE;
00891 }
00892
00893 struct copy_data
00894 {
00895 tree name;
00896 int quals;
00897 };
00898
00899
00900
00901
00902
00903 static tree
00904 locate_copy (tree type, void *client_)
00905 {
00906 struct copy_data *client = (struct copy_data *)client_;
00907 tree fns;
00908 tree best = NULL_TREE;
00909 bool excess_p = false;
00910
00911 if (client->name)
00912 {
00913 int ix;
00914 ix = lookup_fnfields_1 (type, client->name);
00915 if (ix < 0)
00916 return NULL_TREE;
00917 fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
00918 }
00919 else if (TYPE_HAS_INIT_REF (type))
00920 {
00921
00922
00923 if (CLASSTYPE_LAZY_COPY_CTOR (type))
00924 lazily_declare_fn (sfk_copy_constructor, type);
00925 fns = CLASSTYPE_CONSTRUCTORS (type);
00926 }
00927 else
00928 return NULL_TREE;
00929 for (; fns; fns = OVL_NEXT (fns))
00930 {
00931 tree fn = OVL_CURRENT (fns);
00932 tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
00933 tree src_type;
00934 int excess;
00935 int quals;
00936
00937 parms = TREE_CHAIN (parms);
00938 if (!parms)
00939 continue;
00940 src_type = non_reference (TREE_VALUE (parms));
00941 if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
00942 continue;
00943 if (!sufficient_parms_p (TREE_CHAIN (parms)))
00944 continue;
00945 quals = cp_type_quals (src_type);
00946 if (client->quals & ~quals)
00947 continue;
00948 excess = quals & ~client->quals;
00949 if (!best || (excess_p && !excess))
00950 {
00951 best = fn;
00952 excess_p = excess;
00953 }
00954 else
00955
00956 return NULL_TREE;
00957 }
00958 return best;
00959 }
00960
00961
00962
00963
00964
00965
00966
00967 tree
00968 implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
00969 {
00970 tree fn;
00971 tree parameter_types = void_list_node;
00972 tree return_type;
00973 tree fn_type;
00974 tree raises = empty_except_spec;
00975 tree rhs_parm_type = NULL_TREE;
00976 tree name;
00977 HOST_WIDE_INT saved_processing_template_decl;
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987 gcc_assert (!dependent_type_p (type));
00988 saved_processing_template_decl = processing_template_decl;
00989 processing_template_decl = 0;
00990
00991 type = TYPE_MAIN_VARIANT (type);
00992
00993 if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type))
00994 {
00995 if (kind == sfk_destructor)
00996
00997 return_type = build_pointer_type (void_type_node);
00998 else
00999 return_type = build_pointer_type (type);
01000 }
01001 else
01002 return_type = void_type_node;
01003
01004 switch (kind)
01005 {
01006 case sfk_destructor:
01007
01008 name = constructor_name (type);
01009 raises = synthesize_exception_spec (type, &locate_dtor, 0);
01010 break;
01011
01012 case sfk_constructor:
01013
01014 name = constructor_name (type);
01015 raises = synthesize_exception_spec (type, &locate_ctor, 0);
01016 break;
01017
01018 case sfk_copy_constructor:
01019 case sfk_assignment_operator:
01020 {
01021 struct copy_data data;
01022
01023 data.name = NULL;
01024 data.quals = 0;
01025 if (kind == sfk_assignment_operator)
01026 {
01027 return_type = build_reference_type (type);
01028 name = ansi_assopname (NOP_EXPR);
01029 data.name = name;
01030 }
01031 else
01032 name = constructor_name (type);
01033
01034 if (const_p)
01035 {
01036 data.quals = TYPE_QUAL_CONST;
01037 rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST);
01038 }
01039 else
01040 rhs_parm_type = type;
01041 rhs_parm_type = build_reference_type (rhs_parm_type);
01042 parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
01043 raises = synthesize_exception_spec (type, &locate_copy, &data);
01044 break;
01045 }
01046 default:
01047 gcc_unreachable ();
01048 }
01049
01050
01051 fn_type = build_method_type_directly (type, return_type, parameter_types);
01052 if (raises)
01053 fn_type = build_exception_variant (fn_type, raises);
01054 fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
01055 DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
01056 if (kind == sfk_constructor || kind == sfk_copy_constructor)
01057 DECL_CONSTRUCTOR_P (fn) = 1;
01058 else if (kind == sfk_destructor)
01059 DECL_DESTRUCTOR_P (fn) = 1;
01060 else
01061 {
01062 DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
01063 SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
01064 }
01065
01066
01067 if (rhs_parm_type)
01068 {
01069
01070
01071
01072 DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
01073 TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
01074 }
01075
01076 grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
01077 TYPE_UNQUALIFIED);
01078 grok_special_member_properties (fn);
01079 set_linkage_according_to_type (type, fn);
01080 rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
01081 DECL_IN_AGGR_P (fn) = 1;
01082 DECL_ARTIFICIAL (fn) = 1;
01083 DECL_NOT_REALLY_EXTERN (fn) = 1;
01084 DECL_DECLARED_INLINE_P (fn) = 1;
01085 DECL_INLINE (fn) = 1;
01086 gcc_assert (!TREE_USED (fn));
01087
01088
01089 processing_template_decl = saved_processing_template_decl;
01090
01091 return fn;
01092 }
01093
01094
01095
01096
01097
01098 tree
01099 lazily_declare_fn (special_function_kind sfk, tree type)
01100 {
01101 tree fn;
01102 bool const_p;
01103
01104
01105
01106 if (sfk == sfk_copy_constructor)
01107 const_p = TYPE_HAS_CONST_INIT_REF (type);
01108 else if (sfk == sfk_assignment_operator)
01109 const_p = TYPE_HAS_CONST_ASSIGN_REF (type);
01110 else
01111
01112 const_p = false;
01113
01114 fn = implicitly_declare_fn (sfk, type, const_p);
01115
01116 if (sfk == sfk_destructor)
01117 check_for_override (fn, type);
01118
01119 add_method (type, fn, NULL_TREE);
01120
01121 if (sfk == sfk_destructor
01122 && DECL_VIRTUAL_P (fn)
01123 && abi_version_at_least (2))
01124
01125
01126 TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
01127 else
01128 {
01129
01130
01131
01132 if (warn_abi && DECL_VIRTUAL_P (fn))
01133 warning ("vtable layout for class %qT may not be ABI-compliant"
01134 "and may change in a future version of GCC due to "
01135 "implicit virtual destructor",
01136 type);
01137 TREE_CHAIN (fn) = TYPE_METHODS (type);
01138 TYPE_METHODS (type) = fn;
01139 }
01140 maybe_add_class_template_decl_list (type, fn, 0);
01141 if (sfk == sfk_assignment_operator)
01142 CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
01143 else
01144 {
01145
01146 if (sfk == sfk_constructor)
01147 CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0;
01148 else if (sfk == sfk_copy_constructor)
01149 CLASSTYPE_LAZY_COPY_CTOR (type) = 0;
01150 else if (sfk == sfk_destructor)
01151 CLASSTYPE_LAZY_DESTRUCTOR (type) = 0;
01152
01153 clone_function_decl (fn, true);
01154 }
01155
01156 return fn;
01157 }
01158
01159
01160
01161
01162 tree
01163 skip_artificial_parms_for (tree fn, tree list)
01164 {
01165 if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
01166 list = TREE_CHAIN (list);
01167 else
01168 return list;
01169
01170 if (DECL_HAS_IN_CHARGE_PARM_P (fn))
01171 list = TREE_CHAIN (list);
01172 if (DECL_HAS_VTT_PARM_P (fn))
01173 list = TREE_CHAIN (list);
01174 return list;
01175 }
01176
01177 #include "gt-cp-method.h"