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