diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-06-09 16:26:24 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-06-09 16:26:24 +0000 |
commit | 442fd60af07bdb442548e3a06d38d205572ce8b8 (patch) | |
tree | fdc9f3bc814a3a9dc10638c0528a97fecd63ad7b /gcc | |
parent | a6260fc7cbd357861d5a9b52ece9180843c26ebe (diff) | |
download | gcc-442fd60af07bdb442548e3a06d38d205572ce8b8.tar.gz |
revert mangling patch
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34471 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 133 | ||||
-rw-r--r-- | gcc/cp/call.c | 3 | ||||
-rw-r--r-- | gcc/cp/class.c | 38 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 25 | ||||
-rw-r--r-- | gcc/cp/decl.c | 76 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 55 | ||||
-rw-r--r-- | gcc/cp/init.c | 5 | ||||
-rw-r--r-- | gcc/cp/lex.c | 6 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 56 | ||||
-rw-r--r-- | gcc/cp/method.c | 1828 | ||||
-rw-r--r-- | gcc/cp/operators.def | 124 | ||||
-rw-r--r-- | gcc/cp/pt.c | 156 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 45 | ||||
-rw-r--r-- | gcc/cp/tinfo2.cc | 16 | ||||
-rw-r--r-- | gcc/invoke.texi | 28 |
16 files changed, 2281 insertions, 318 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb2a6ba1c34..754b656bab5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -41,11 +41,6 @@ (value_format, case dw_val_class_const): Use sdata format. (output_die): Call output_sleb128. -2000-06-08 Mark Mitchell <mark@codesourcery.com> - - * invoke.texi: Remove documentation for -fsquangle and - -fname-mangling-version. - 2000-06-08 James E. Wilson <wilson@cygnus.com> * dwarf2out.c (ASM_OUTPUT_DWARF_DATA8): Add new macro that uses diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b05f3396017..ed1fdabac03 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -11,139 +11,6 @@ * lex.c (DEF_OPERATOR): Say `operator@' -not- `operator @' whenever @ is a symbolic name. -2000-06-08 Mark Mitchell <mark@codesourcery.com> - - Remove old ABI mangling code. - * cp-tree.h (cp_tree_index): Remove CPTI_TINFO_DECL_ID and - CPTI_TINFO_VAR_ID. - (tinfo_decl_id): Remove. - (tinfo_var_id): Likewise. - (name_mangling_version): Likewise. - (flag_do_squangling): Likewise. - (get_vtt_name): Likewise. - (init_method): Likewise. - (build_overload_name): Likewise. - (build_static_name): Likewise. - (build_decl_overload_real): Likewise. - (build_overload_with_type): Likewise. - (build_destructor_name): Likewise. - (get_id_2): Likewise. - (get_ctor_vtbl_name): Likewise. - (mangle_typeinfo_fn_for_type): New function. - (mangle_java_reflection_var_for_type): Likewise. - * call.c (build_new_method_call): Use mangle_vtt_for_type. - * class.c (get_vtable_name): Remove. - (get_vtt_name): Remove. - (get_vtable_decl): Use mangle_vtbl_for_type. - (build_vtt): Likewise. - (build_ctor_vtbl_group): Remove old ABI mangling support. - * decl.c (pushtag): Likewise. - (maybe_commonize_var): Use set_mangled_name_for_decl. - (grokfndecl): Remove old ABI mangling support. - (grokvardecl): Likewise. - (grokdeclarator): Likewise. - (grok_op_properties): Adjust use of DEF_OPERATOR. - * decl2.c (name_mangling_version): Remove. - (lang_f_options): Remove squangle. - (unsupported_options): Add squangle. - (lang_decode_options): Don't set flag_do_squangling. Issue a - warning for -fname-mangling-version. - (grokclassfn): Remove old ABI mangling support. - (finish_static_data_member_decl): Likewise. - (grokfield): Likewise. - (grokoptypename): Likewise. - (get_sentry): Likewise. - * init.c (build_java_class_ref): Use - mangle_java_reflection_var_for_type. - * lex.c (init_operators): Adjust use of DEF_OPERATOR. - (init_parse): Call init_mangle, not init_method. - * mangle.c (write_special_name_constructor): Handle - maybe-in-charge constructors. - (write_special_name_destructor): Handle - maybe-in-charge destructors. - (write_expression): Tweak code to handle non-type template - arguments with reference type. - (mangle_typeinfo_fn_for_type): New function. - (mangle_java_reflection_var_for_type): Likewise. - (mangle_conv_op_name_for_type): Don't use a name that the user - could type. - * method.c (enum mangling_flags): Remove. - (mangling_flags): Likewise. - (obstack_chunk_alloc): Likewise. - (obstack_chunk_free): Likewise. - (OB_INIT): Likewise. - (OB_PUTC): Likewise. - (OB_PUTC2): Likewise. - (OB_PUTS): Likewise. - (OB_PUTID): Likewise. - (OB_PUTCP): Likewise. - (OB_FINISH): Likewise. - (OB_LAST): Likewise. - (btypelist): Likewise. - (ktypelist): Likewise. - (maxbtype): Likewise. - (maxktype): Likewise. - (typevec): Likewise. - (maxtype): Likewise. - (init_method): Likewise. - (digit_buffer): Likewise. - (nofold): Likewise. - (start_squangling): Likewise. - (end_squangling): Likewise. - (icat): Likewise. - (dicat): Likewise. - (old_backref_index): Likewise. - (flush_repeats): Likewise. - (is_back_referenceable_type): Likewise. - (issue_nrepeats): Likewise. - (check_ktype): Likewise. - (issue_ktype): Likewise. - (build_overload_nested_name): Likewise. - (build_underscore_int): Likewise. - (build_overload_scope_ref): Likewise. - (mangle_expression): Likewise. - (build_overload_int): Likewise. - (mangled_C9x_name): Likewise. - (build_overload_value): Likewise. - (build_template_template_parm_names): Likewise. - (build_template_parm_names): Likewise. - (build_overload_identifier): Likewise. - (build_qualified_name): Likewise. - (build_mangled_name_for_type_with_Gcode): Likewise. - (build_mangled_name_for_type): Likewise. - (build_overload_name): Likewise. - (build_mangled_name): Likewise. - (process_modifiers): Likewise. - (check_btype): Likewise. - (process_overload_item): Likewise. - (build_static_name): Likewise. - (build_decl_overload_real): Likewise. - (set_mangled_name_for_decl): Remove old ABI mangling support. - (build_typename_overload): Remove. - (build_overload_with_type): Remove. - (get_id_2): Remove. - (get_ctor_vtbl_name): Remove. - (build_destructor_name): Likewise. - (set_mangled_name_for_decl): Likewise. - (make_thunk): Remove old ABI mangling support. - * operators.def: Likewise. - * pt.c (check_explicit_specialization): Don't call - set_mangled_name_for_template_decl. - (lookup_template_class): Remove old ABI mangling support. - (tsubst_friend_function): Update comment. - (tsubst_decl): Remove old ABI mangling support. - (tsubst_copy): Likewise. - (set_mangled_name_for_template_decl): Remove. - * rtti.c (init_rtti_processing): Use std_identifier. Don't set - tinfo_decl_id or tinfo_var_id. - (get_tinfo_var): Use mangle_typeinfo_for_type. - (tinfo_name): Remove old ABI mangling support. - (get_tinfo_decl): Likewise. - (tinfo_base_init): Likewise. - (create_real_tinfo_var): Use a name that the user can't type. - - * tinfo2.cc (BUILTIN): Adjust to use new mangling. - 2000-06-08 Jakub Jelinek <jakub@redhat.com> * method.c (make_thunk): Clear DECL_VTT_PARM in thunk. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 27f012d35df..5cabf137b92 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4332,8 +4332,7 @@ build_new_method_call (instance, name, args, basetype_path, flags) /* If the current function is a complete object constructor or destructor, then we fetch the VTT directly. Otherwise, we look it up using the VTT we were given. */ - vtt = IDENTIFIER_GLOBAL_VALUE (mangle_vtt_for_type - (current_class_type)); + vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type)); vtt = build_unary_op (ADDR_EXPR, vtt, /*noconvert=*/1); vtt = build (COND_EXPR, TREE_TYPE (vtt), DECL_USE_VTT_PARM (current_function_decl), diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 922c2e6a754..77a5b7e6499 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -91,6 +91,7 @@ static tree get_vfield_name PARAMS ((tree)); static void finish_struct_anon PARAMS ((tree)); static tree build_vbase_pointer PARAMS ((tree, tree)); static tree build_vtable_entry PARAMS ((tree, tree, tree)); +static tree get_vtable_name PARAMS ((tree)); static tree get_derived_offset PARAMS ((tree, tree)); static tree get_basefndecls PARAMS ((tree, tree)); static int build_primary_vtable PARAMS ((tree, tree)); @@ -627,6 +628,34 @@ build_vfn_ref (ptr_to_instptr, instance, idx) return build_component_ref (aref, pfn_identifier, NULL_TREE, 0); } +/* Return the name of the virtual function table (as an IDENTIFIER_NODE) + for the given TYPE. */ + +static tree +get_vtable_name (type) + tree type; +{ + if (flag_new_abi) + return mangle_vtbl_for_type (type); + else + return build_overload_with_type (get_identifier (VTABLE_NAME_PREFIX), + type); +} + +/* Return an IDENTIFIER_NODE for the name of the virtual table table + for TYPE. */ + +tree +get_vtt_name (type) + tree type; +{ + if (flag_new_abi) + return mangle_vtt_for_type (type); + else + return build_overload_with_type (get_identifier (VTT_NAME_PREFIX), + type); +} + /* Return the offset to the main vtable for a given base BINFO. */ tree @@ -703,7 +732,7 @@ get_vtable_decl (type, complete) tree type; int complete; { - tree name = mangle_vtbl_for_type (type); + tree name = get_vtable_name (type); tree decl = IDENTIFIER_GLOBAL_VALUE (name); if (decl) @@ -6558,7 +6587,7 @@ build_vtt (t) type = build_cplus_array_type (const_ptr_type_node, type); /* Now, build the VTT object itself. */ - vtt = build_vtable (t, mangle_vtt_for_type (t), type); + vtt = build_vtable (t, get_vtt_name (t), type); pushdecl_top_level (vtt); initialize_array (vtt, inits); } @@ -6742,7 +6771,10 @@ build_ctor_vtbl_group (binfo, t) tree id; /* See if we've already create this construction vtable group. */ - id = mangle_ctor_vtbl_for_type (t, binfo); + if (flag_new_abi) + id = mangle_ctor_vtbl_for_type (t, binfo); + else + id = get_ctor_vtbl_name (t, binfo); if (IDENTIFIER_GLOBAL_VALUE (id)) return; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 108c441cab7..1b65b6a55a4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -555,7 +555,9 @@ enum cp_tree_index CPTI_STD, CPTI_ABI, CPTI_TYPE_INFO_TYPE, + CPTI_TINFO_DECL_ID, CPTI_TINFO_DECL_TYPE, + CPTI_TINFO_VAR_ID, CPTI_ABORT_FNDECL, CPTI_GLOBAL_DELETE_FNDECL, @@ -647,7 +649,9 @@ extern tree cp_global_trees[CPTI_MAX]; #define std_node cp_global_trees[CPTI_STD] #define abi_node cp_global_trees[CPTI_ABI] #define type_info_type_node cp_global_trees[CPTI_TYPE_INFO_TYPE] +#define tinfo_decl_id cp_global_trees[CPTI_TINFO_DECL_ID] #define tinfo_decl_type cp_global_trees[CPTI_TINFO_DECL_TYPE] +#define tinfo_var_id cp_global_trees[CPTI_TINFO_VAR_ID] #define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL] #define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL] @@ -1173,10 +1177,19 @@ extern int flag_ansi; extern int flag_default_inline; +/* The name-mangling scheme to use. Versions of gcc before 2.8 use + version 0. */ +extern int name_mangling_version; + /* Nonzero if wchar_t should be `unsigned short' instead of whatever it would normally be, for use with WINE. */ extern int flag_short_wchar; +/* Nonzero if squashed mangling is to be performed. + This uses the B and K codes to reference previously seen class types + and class qualifiers. */ +extern int flag_do_squangling; + /* Nonzero means generate separate instantiation control files and juggle them at link time. */ extern int flag_use_repository; @@ -3912,6 +3925,7 @@ extern void maybe_note_name_used_in_class PARAMS ((tree, tree)); extern void note_name_declared_in_class PARAMS ((tree, tree)); extern tree get_vtbl_decl_for_binfo PARAMS ((tree)); extern tree in_charge_arg_for_name PARAMS ((tree)); +extern tree get_vtt_name PARAMS ((tree)); /* in cvt.c */ extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree)); @@ -4278,14 +4292,23 @@ extern void yyhook PARAMS ((int)); extern int cp_type_qual_from_rid PARAMS ((tree)); /* in method.c */ +extern void init_method PARAMS ((void)); +extern char *build_overload_name PARAMS ((tree, int, int)); +extern tree build_static_name PARAMS ((tree, tree)); +extern tree build_decl_overload_real PARAMS ((tree, tree, tree, tree, + tree, int)); extern void set_mangled_name_for_decl PARAMS ((tree)); extern tree build_typename_overload PARAMS ((tree)); +extern tree build_overload_with_type PARAMS ((tree, tree)); +extern tree build_destructor_name PARAMS ((tree)); extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree)); extern tree hack_identifier PARAMS ((tree, tree)); extern tree make_thunk PARAMS ((tree, int, int)); extern void emit_thunk PARAMS ((tree)); extern void synthesize_method PARAMS ((tree)); +extern tree get_id_2 PARAMS ((const char *, tree)); extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int)); +extern tree get_ctor_vtbl_name PARAMS ((tree, tree)); /* In optimize.c */ extern void optimize_function PARAMS ((tree)); @@ -4724,8 +4747,6 @@ extern tree mangle_ctor_vtbl_for_type PARAMS ((tree, tree)); extern tree mangle_thunk PARAMS ((tree, int, int)); extern tree mangle_conv_op_name_for_type PARAMS ((tree)); extern tree mangle_guard_variable PARAMS ((tree)); -extern tree mangle_typeinfo_fn_for_type PARAMS ((tree)); -extern tree mangle_java_reflection_var_for_type PARAMS ((tree)); /* -- end of C++ */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 73e5a61f942..f9f52fac630 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -254,7 +254,9 @@ tree error_mark_list; tree global_delete_fndecl; Used by RTTI - tree type_info_type_node, tinfo_decl_type; + tree type_info_type_node, tinfo_decl_id, tinfo_decl_type; + tree tinfo_var_id; + */ tree cp_global_trees[CPTI_MAX]; @@ -2890,7 +2892,13 @@ pushtag (name, type, globalize) VARRAY_PUSH_TREE (local_classes, type); if (!uses_template_parms (type)) - DECL_ASSEMBLER_NAME (d) = mangle_type (type); + { + if (flag_new_abi) + DECL_ASSEMBLER_NAME (d) = mangle_type (type); + else + DECL_ASSEMBLER_NAME (d) + = get_identifier (build_overload_name (type, 1, 1)); + } } if (b->parm_flag == 2) { @@ -7618,7 +7626,8 @@ maybe_commonize_var (decl) which we can't if it has been initialized. */ if (TREE_PUBLIC (decl)) - set_mangled_name_for_decl (decl); + DECL_ASSEMBLER_NAME (decl) + = build_static_name (current_function_decl, DECL_NAME (decl)); else { cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl); @@ -8968,9 +8977,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, add_defarg_fn (decl); /* Plain overloading: will not be grok'd by grokclassfn. */ - if (! ctype && ! processing_template_decl + if (! ctype && ! processing_template_decl && !DECL_EXTERN_C_P (decl) - && !DECL_USE_TEMPLATE (decl)) + && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1)) set_mangled_name_for_decl (decl); if (funcdef_flag) @@ -9085,7 +9094,13 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) /* DECL_ASSEMBLER_NAME is needed only for full-instantiated templates. */ if (!uses_template_parms (decl)) - DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + { + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + else + DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, + declarator); + } } else { @@ -9110,7 +9125,13 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) context = DECL_CONTEXT (decl); if (declarator && context && current_lang_name != lang_name_c) - DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + { + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + else + DECL_ASSEMBLER_NAME (decl) + = build_static_name (context, declarator); + } } if (in_namespace) @@ -11145,7 +11166,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)) = TYPE_IDENTIFIER (type); - DECL_ASSEMBLER_NAME (decl) = mangle_type (type); + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_type (type); + else + { + /* XXX Temporarily set the scope. + When returning, start_decl expects it as NULL_TREE, + and will then then set it using pushdecl. */ + my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404); + if (current_class_type) + DECL_CONTEXT (decl) = current_class_type; + else + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + + DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl); + DECL_ASSEMBLER_NAME (decl) + = get_identifier (build_overload_name (type, 1, 1)); + DECL_CONTEXT (decl) = NULL_TREE; + } /* FIXME remangle member functions; member functions of a type with external linkage have external linkage. */ @@ -12298,17 +12336,17 @@ grok_op_properties (decl, virtualp, friendp) else do { -#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \ - if (ansi_opname (CODE) == name) \ - { \ - operator_code = CODE; \ - break; \ - } \ - else if (ansi_assopname (CODE) == name) \ - { \ - operator_code = CODE; \ - DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \ - break; \ +#define DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGING, ARITY, ASSN_P) \ + if (ansi_opname (CODE) == name) \ + { \ + operator_code = CODE; \ + break; \ + } \ + else if (ansi_assopname (CODE) == name) \ + { \ + operator_code = CODE; \ + DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \ + break; \ } #include "operators.def" diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 872290d1a15..6fc7bb5b98e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -466,6 +466,11 @@ int flag_inline_trees = 0; int max_tinst_depth = 17; +/* The name-mangling scheme to use. Must be 1 or greater to support + template functions with identical types, but different template + arguments. */ +int name_mangling_version = 2; + /* Nonzero if wchar_t should be `unsigned short' instead of whatever it would normally be, for use with WINE. */ int flag_short_wchar; @@ -547,6 +552,7 @@ lang_f_options[] = {"permissive", &flag_permissive, 1}, {"repo", &flag_use_repository, 1}, {"rtti", &flag_rtti, 1}, + {"squangle", &flag_do_squangling, 1}, {"stats", &flag_detailed_statistics, 1}, {"strict-prototype", &flag_strict_prototype, 1}, {"use-cxa-atexit", &flag_use_cxa_atexit, 1}, @@ -564,8 +570,7 @@ static const char * const unsupported_options[] = { "enum-int-equiv", "guiding-decls", "nonnull-objects", - "squangle", - "this-is-variable" + "this-is-variable", }; /* Compare two option strings, pointed two by P1 and P2, for use with @@ -660,20 +665,22 @@ lang_decode_option (argc, argv) else if (!strcmp (p, "new-abi")) { flag_new_abi = 1; + flag_do_squangling = 1; flag_vtable_thunks = 1; } else if (!strcmp (p, "no-new-abi")) - flag_new_abi = 0; + { + flag_new_abi = 0; + flag_do_squangling = 0; + } else if ((option_value = skip_leading_substring (p, "template-depth-"))) max_tinst_depth = read_integral_parameter (option_value, p - 2, max_tinst_depth); else if ((option_value = skip_leading_substring (p, "name-mangling-version-"))) - { - warning ("-f%s is no longer supported", p); - return 1; - } + name_mangling_version + = read_integral_parameter (option_value, p - 2, name_mangling_version); else if ((option_value = skip_leading_substring (p, "dump-translation-unit-"))) { @@ -1097,10 +1104,16 @@ grokclassfn (ctype, function, flags, quals) if (flags == DTOR_FLAG) { DECL_DESTRUCTOR_P (function) = 1; + + if (flag_new_abi) + set_mangled_name_for_decl (function); + else + DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype); + TYPE_HAS_DESTRUCTOR (ctype) = 1; } - - set_mangled_name_for_decl (function); + else + set_mangled_name_for_decl (function); } /* Work on the expr used by alignof (this is only called by the parser). */ @@ -1567,7 +1580,11 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags) if (!asmspec && current_class_type) { DECL_INITIAL (decl) = error_mark_node; - DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + else + DECL_ASSEMBLER_NAME (decl) + = build_static_name (current_class_type, DECL_NAME (decl)); } if (! processing_template_decl) { @@ -1698,7 +1715,13 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) name for this TYPE_DECL. */ DECL_ASSEMBLER_NAME (value) = DECL_NAME (value); if (!uses_template_parms (value)) - DECL_ASSEMBLER_NAME (value) = mangle_type (TREE_TYPE (value)); + { + if (flag_new_abi) + DECL_ASSEMBLER_NAME (value) = mangle_type (TREE_TYPE (value)); + else + DECL_ASSEMBLER_NAME (value) = + get_identifier (build_overload_name (TREE_TYPE (value), 1, 1)); + } if (processing_template_decl) value = push_template_decl (value); @@ -1884,7 +1907,10 @@ grokoptypename (declspecs, declarator) tree declspecs, declarator; { tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); - return mangle_conv_op_name_for_type (t); + if (flag_new_abi) + return mangle_conv_op_name_for_type (t); + else + return build_typename_overload (t); } /* When a function is declared with an initializer, @@ -2845,7 +2871,10 @@ get_sentry (decl) tree sname; tree sentry; - sname = mangle_guard_variable (decl); + if (!flag_new_abi) + sname = get_id_2 ("__sn", DECL_ASSEMBLER_NAME (decl)); + else + sname = mangle_guard_variable (decl); /* For struct X foo __attribute__((weak)), there is a counter __snfoo. Since base is already an assembler name, sname should diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 02f9ac9c7c6..238b7fceefa 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2138,6 +2138,9 @@ build_java_class_ref (type) tree type; { tree name, class_decl; + static tree CL_prefix = NULL_TREE; + if (CL_prefix == NULL_TREE) + CL_prefix = get_identifier("_CL_"); if (jclass_node == NULL_TREE) { jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass")); @@ -2145,7 +2148,7 @@ build_java_class_ref (type) fatal("call to Java constructor, while `jclass' undefined"); jclass_node = TREE_TYPE (jclass_node); } - name = mangle_java_reflection_var_for_type (type); + name = build_overload_with_type (CL_prefix, type); class_decl = IDENTIFIER_GLOBAL_VALUE (name); if (class_decl == NULL_TREE) { diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 9df7b1c6e3e..8fbbbc40ec4 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -466,7 +466,7 @@ init_operators () char buffer[256]; struct operator_name_info_t *oni; -#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \ +#define DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, ASSN_P) \ my_friendly_assert ((strlen ("operator ") + strlen (NAME) + 1 \ + ISALPHA (NAME[0]) <= 256), \ 20000526); \ @@ -479,7 +479,7 @@ init_operators () : &operator_name_info[(int) CODE]); \ oni->identifier = identifier; \ oni->name = NAME; \ - oni->mangled_name = MANGLING; + oni->mangled_name = flag_new_abi ? NEW_MANGLING : OLD_MANGLING; #include "operators.def" #undef DEF_OPERATOR @@ -592,7 +592,7 @@ init_parse (filename) (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *)); init_operators (); - init_mangle (); + init_method (); init_error (); gcc_obstack_init (&inline_text_obstack); inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index ed4692945a5..2bba09f518b 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -998,10 +998,8 @@ write_special_name_constructor (ctor) write_string ("C1"); else if (DECL_BASE_CONSTRUCTOR_P (ctor)) write_string ("C2"); - else if (flag_new_abi) - write_string ("C*INTERNAL*"); else - write_string ("C1"); + write_string ("C*INTERNAL*"); } /* Handle destructor productions of non-terminal <special-name>. @@ -1025,10 +1023,9 @@ write_special_name_destructor (dtor) write_string ("D1"); else if (DECL_BASE_DESTRUCTOR_P (dtor)) write_string ("D2"); - else if (flag_new_abi) - write_string ("D*INTERNAL*"); else - write_string ("D0"); + /* Old-ABI destructor. */ + write_string ("D*INTERNAL*"); } /* Return the discriminator for ENTITY appearing inside @@ -1567,17 +1564,8 @@ write_expression (expr) if (TREE_CODE (expr) == ADDR_EXPR && TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE) - { - expr = TREE_OPERAND (expr, 0); - if (DECL_P (expr)) - { - write_expression (expr); - return; - } + expr = TREE_OPERAND (expr, 0); - code = TREE_CODE (expr); - } - /* If it wasn't any of those, recursively expand the expression. */ write_string (operator_name_info[(int) code].mangled_name); @@ -1981,27 +1969,6 @@ mangle_typeinfo_for_type (type) return mangle_special_for_type (type, "TI"); } -/* Return the mangled name of the function that returns the typeinfo - for TYPE. */ - -tree -mangle_typeinfo_fn_for_type (type) - tree type; -{ - my_friendly_assert (!new_abi_rtti_p (), 20000608); - return mangle_special_for_type (type, "TF"); -} - -/* Return the name of the variable that represents TYPE at runtime in - Java. */ - -tree -mangle_java_reflection_var_for_type (type) - tree type; -{ - return mangle_special_for_type (type, "TJ"); -} - /* Create an identifier for the mangled name of the NTBS containing the mangled name of TYPE. */ @@ -2118,7 +2085,15 @@ mangle_thunk (fn_decl, offset, vcall_offset) /* Return an identifier for the mangled unqualified name for a conversion operator to TYPE. This mangling is not specified by the - ABI spec; it is only used internally. */ + ABI spec; it is only used internally. + + For compatibility with existing conversion operator mechanisms, + the mangled form is `__op<type>' where <type> is the mangled + representation of TYPE. + + FIXME: Though identifiers with starting with __op are reserved for + the implementation, it would eventually be nice to use inaccessible + names for these operators. */ tree mangle_conv_op_name_for_type (type) @@ -2129,10 +2104,11 @@ mangle_conv_op_name_for_type (type) /* Build the mangling for TYPE. */ const char *mangled_type = mangle_type_string (type); /* Allocate a temporary buffer for the complete name. */ - char *op_name = (char *) xmalloc (strlen ("operator ") + char *op_name = (char *) xmalloc (strlen (OPERATOR_TYPENAME_FORMAT) + strlen (mangled_type) + 1); /* Assemble the mangling. */ - sprintf (op_name, "operator %s", mangled_type); + strcpy (op_name, OPERATOR_TYPENAME_FORMAT); + strcat (op_name, mangled_type); /* Find or create an identifier. */ identifier = get_identifier (op_name); /* Done with the temporary buffer. */ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 349ed758878..f145650e8f3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -37,26 +37,1825 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "tm_p.h" +/* Various flags to control the mangling process. */ + +enum mangling_flags +{ + /* No flags. */ + mf_none = 0, + /* The thing we are presently mangling is part of a template type, + rather than a fully instantiated type. Therefore, we may see + complex expressions where we would normally expect to see a + simple integer constant. */ + mf_maybe_uninstantiated = 1, + /* When mangling a numeric value, use the form `_XX_' (instead of + just `XX') if the value has more than one digit. */ + mf_use_underscores_around_value = 2, +}; + +typedef enum mangling_flags mangling_flags; + /* TREE_LIST of the current inline functions that need to be processed. */ struct pending_inline *pending_inlines; +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +/* Obstack where we build text strings for overloading, etc. */ +static struct obstack scratch_obstack; +static char *scratch_firstobj; + +static void icat PARAMS ((HOST_WIDE_INT)); +static void dicat PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT)); +static int old_backref_index PARAMS ((tree)); +static int flush_repeats PARAMS ((int, tree)); +static void build_overload_identifier PARAMS ((tree)); +static void build_overload_nested_name PARAMS ((tree)); +static void mangle_expression PARAMS ((tree)); +static void build_overload_int PARAMS ((tree, mangling_flags)); +static void build_overload_identifier PARAMS ((tree)); +static void build_qualified_name PARAMS ((tree)); +static void build_overload_value PARAMS ((tree, tree, mangling_flags)); +static void issue_nrepeats PARAMS ((int, tree)); +static char *build_mangled_name PARAMS ((tree,int,int)); +static void process_modifiers PARAMS ((tree)); +static void process_overload_item PARAMS ((tree,int)); static void do_build_assign_ref PARAMS ((tree)); static void do_build_copy_constructor PARAMS ((tree)); +static void build_template_template_parm_names PARAMS ((tree)); +static void build_template_parm_names PARAMS ((tree, tree)); +static void build_underscore_int PARAMS ((int)); +static void start_squangling PARAMS ((void)); +static void end_squangling PARAMS ((void)); +static int check_ktype PARAMS ((tree, int)); +static int issue_ktype PARAMS ((tree)); +static void build_overload_scope_ref PARAMS ((tree)); +static void build_mangled_template_parm_index PARAMS ((const char *, tree)); +#if HOST_BITS_PER_WIDE_INT >= 64 +static void build_mangled_C9x_name PARAMS ((int)); +#endif +static int is_back_referenceable_type PARAMS ((tree)); +static int check_btype PARAMS ((tree)); +static void build_mangled_name_for_type PARAMS ((tree)); +static void build_mangled_name_for_type_with_Gcode PARAMS ((tree, int)); + +# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) +# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) +# define OB_PUTC2(C1,C2) \ + (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2))) +# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1)) +# define OB_PUTID(ID) \ + (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \ + IDENTIFIER_LENGTH (ID))) +# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) +# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) +# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1]) + +/* type tables for K and B type compression */ +static varray_type btypelist; +static varray_type ktypelist; + +/* number of each type seen */ +static size_t maxbtype; +static size_t maxktype; + +/* Array of types seen so far in top-level call to `build_mangled_name'. + Allocated and deallocated by caller. */ +static varray_type typevec; + +/* Number of types interned by `build_mangled_name' so far. */ +static size_t maxtype; + +/* Called once to initialize method.c. */ + +void +init_method () +{ + gcc_obstack_init (&scratch_obstack); + scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0); + ggc_add_tree_varray_root (&btypelist, 1); + ggc_add_tree_varray_root (&ktypelist, 1); + ggc_add_tree_varray_root (&typevec, 1); + if (flag_new_abi) + init_mangle (); +} + +/* This must be large enough to hold any printed integer or floating-point + value. */ +static char digit_buffer[128]; +/* Here is where overload code starts. */ + +/* Nonzero if we should not try folding parameter types. */ +static int nofold; + +/* Nonzero if an underscore is required before adding a digit to the + mangled name currently being built. */ +static int numeric_output_need_bar; + +static inline void +start_squangling () +{ + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200005222); + + if (flag_do_squangling) + { + nofold = 0; + maxbtype = 0; + maxktype = 0; + VARRAY_TREE_INIT (btypelist, 50, "btypelist"); + VARRAY_TREE_INIT (ktypelist, 50, "ktypelist"); + } +} + +static inline void +end_squangling () +{ + if (flag_do_squangling) + { + VARRAY_FREE (ktypelist); + VARRAY_FREE (btypelist); + maxbtype = 0; + maxktype = 0; + } +} + +/* Code to concatenate an asciified integer to a string. */ + +static inline void +icat (i) + HOST_WIDE_INT i; +{ + unsigned HOST_WIDE_INT ui; + + /* Handle this case first, to go really quickly. For many common values, + the result of ui/10 below is 1. */ + if (i == 1) + { + OB_PUTC ('1'); + return; + } + + if (i >= 0) + ui = i; + else + { + OB_PUTC ('m'); + ui = -i; + } + + if (ui >= 10) + icat (ui / 10); + + OB_PUTC ('0' + (ui % 10)); +} + +static void +dicat (lo, hi) + HOST_WIDE_INT lo, hi; +{ + unsigned HOST_WIDE_INT ulo, uhi, qlo, qhi; + + if (hi >= 0) + { + uhi = hi; + ulo = lo; + } + else + { + uhi = (lo == 0 ? -hi : -hi-1); + ulo = -lo; + } + if (uhi == 0 + && ulo < ((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1))) + { + icat (ulo); + return; + } + /* Divide 2^HOST_WIDE_INT*uhi+ulo by 10. */ + qhi = uhi / 10; + uhi = uhi % 10; + qlo = uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) / 5); + qlo += ulo / 10; + ulo = ulo % 10; + ulo += uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) % 5) + * 2; + qlo += ulo / 10; + ulo = ulo % 10; + /* Quotient is 2^HOST_WIDE_INT*qhi+qlo, remainder is ulo. */ + dicat (qlo, qhi); + OB_PUTC ('0' + ulo); +} + +/* Returns the index of TYPE in the typevec, or -1 if it's not there. */ + +static inline int +old_backref_index (type) + tree type; +{ + size_t tindex; + + if (! is_back_referenceable_type (type)) + return -1; + + /* The entry for this parm is at maxtype-1, so don't look there for + something to repeat. */ + for (tindex = 0; tindex < maxtype - 1; ++tindex) + if (same_type_p (VARRAY_TREE (typevec, tindex), type)) + break; + + if (tindex == maxtype - 1) + return -1; + + return tindex; +} + +/* Old mangling style: If TYPE has already been used in the parameter list, + emit a backward reference and return non-zero; otherwise, return 0. + + NREPEATS is the number of repeats we've recorded of this type, or 0 if + this is the first time we've seen it and we're just looking to see if + it had been used before. */ + +static inline int +flush_repeats (nrepeats, type) + int nrepeats; + tree type; +{ + int tindex = old_backref_index (type); + + if (tindex == -1) + { + my_friendly_assert (nrepeats == 0, 990316); + return 0; + } + + if (nrepeats > 1) + { + OB_PUTC ('N'); + icat (nrepeats); + if (nrepeats > 9) + OB_PUTC ('_'); + } + else + OB_PUTC ('T'); + icat (tindex); + if (tindex > 9) + OB_PUTC ('_'); + + return 1; +} + +/* Returns nonzero iff this is a type to which we will want to make + back-references (using the `B' code). */ + +static int +is_back_referenceable_type (type) + tree type; +{ + /* For some reason, the Java folks don't want back refs on these. */ + if (TYPE_FOR_JAVA (type)) + return 0; + + switch (TREE_CODE (type)) + { + case BOOLEAN_TYPE: + if (!flag_do_squangling) + /* Even though the mangling of this is just `b', we did + historically generate back-references for it. */ + return 1; + /* Fall through. */ + + case INTEGER_TYPE: + case REAL_TYPE: + case VOID_TYPE: + /* These types have single-character manglings, so there's no + point in generating back-references. */ + return 0; + + case TEMPLATE_TYPE_PARM: + /* It would be a bit complex to demangle signatures correctly if + we generated back-references to these, and the manglings of + type parameters are short. */ + return 0; + + default: + return 1; + } +} + +/* Issue the squangling code indicating NREPEATS repetitions of TYPE, + which was the last parameter type output. */ + +static void +issue_nrepeats (nrepeats, type) + int nrepeats; + tree type; +{ + if (nrepeats == 1 && !is_back_referenceable_type (type)) + /* For types whose manglings are short, don't bother using the + repetition code if there's only one repetition, since the + repetition code will be about as long as the ordinary mangling. */ + build_mangled_name_for_type (type); + else + { + OB_PUTC ('n'); + icat (nrepeats); + if (nrepeats > 9) + OB_PUTC ('_'); + } +} + +/* Check to see if a tree node has been entered into the Kcode typelist. + If not, add it. Returns -1 if it isn't found, otherwise returns the + index. */ + +static int +check_ktype (node, add) + tree node; + int add; +{ + size_t x; + tree localnode = node; + + if (ktypelist == NULL) + return -1; + + if (TREE_CODE (node) == TYPE_DECL) + localnode = TREE_TYPE (node); + + for (x = 0; x < maxktype; x++) + { + if (same_type_p (localnode, VARRAY_TREE (ktypelist, x))) + return x; + } + /* Didn't find it, so add it here. */ + if (add) + { + if (VARRAY_SIZE (ktypelist) <= maxktype) + VARRAY_GROW (ktypelist, + VARRAY_SIZE (ktypelist) * 3 / 2); + VARRAY_TREE (ktypelist, maxktype) = localnode; + maxktype++; + } + return -1; +} + + +static inline int +issue_ktype (decl) + tree decl; +{ + int kindex; + kindex = check_ktype (decl, FALSE); + if (kindex != -1) + { + OB_PUTC ('K'); + icat (kindex); + if (kindex > 9) + OB_PUTC ('_'); + return TRUE; + } + return FALSE; +} + +/* Build a representation for DECL, which may be an entity not at + global scope. If so, a marker indicating that the name is + qualified has already been output, but the qualifying context has + not. */ + +static void +build_overload_nested_name (decl) + tree decl; +{ + tree context; + + if (ktypelist && issue_ktype (decl)) + return; + + if (decl == global_namespace) + return; + + context = CP_DECL_CONTEXT (decl); + + /* try to issue a K type, and if we can't continue the normal path */ + if (!(ktypelist && issue_ktype (context))) + { + /* For a template type parameter, we want to output an 'Xn' + rather than 'T' or some such. */ + if (TREE_CODE (context) == TEMPLATE_TYPE_PARM + || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM) + build_mangled_name_for_type (context); + else + { + if (TYPE_P (context)) + context = TYPE_NAME (context); + build_overload_nested_name (context); + } + } + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + static int static_labelno; + + tree name = DECL_ASSEMBLER_NAME (decl); + char *label; + + ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), static_labelno); + static_labelno++; + + if (numeric_output_need_bar) + OB_PUTC ('_'); + icat (strlen (label)); + OB_PUTCP (label); + numeric_output_need_bar = 1; + } + else if (TREE_CODE (decl) == NAMESPACE_DECL) + build_overload_identifier (DECL_NAME (decl)); + else /* TYPE_DECL */ + build_overload_identifier (decl); +} + +/* Output the decimal representation of I. If I > 9, the decimal + representation is preceeded and followed by an underscore. */ + +static void +build_underscore_int (i) + int i; +{ + if (i > 9) + OB_PUTC ('_'); + icat (i); + if (i > 9) + OB_PUTC ('_'); +} + +static void +build_overload_scope_ref (value) + tree value; +{ + OB_PUTC2 ('Q', '2'); + numeric_output_need_bar = 0; + build_mangled_name_for_type (TREE_OPERAND (value, 0)); + build_overload_identifier (TREE_OPERAND (value, 1)); +} + +/* VALUE is a complex expression. Produce an appropriate mangling. + (We are forced to mangle complex expressions when dealing with + templates, and an expression involving template parameters appears + in the type of a function parameter.) */ + +static void +mangle_expression (value) + tree value; +{ + if (TREE_CODE (value) == SCOPE_REF) + { + build_overload_scope_ref (value); + return; + } + + OB_PUTC ('E'); + numeric_output_need_bar = 0; + + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value)))) + { + int i; + int operands = TREE_CODE_LENGTH (TREE_CODE (value)); + const char *name; + + name = operator_name_info[TREE_CODE (value)].mangled_name; + if (name == NULL) + /* On some erroneous inputs, we can get here with VALUE a + LOOKUP_EXPR. We must survive this routine in order to issue + a sensible error message, so we fall through to the case + below. */ + goto bad_value; + + for (i = 0; i < operands; ++i) + { + tree operand; + enum tree_code tc; + + /* We just outputted either the `E' or the name of the + operator. */ + numeric_output_need_bar = 0; + + if (i != 0) + /* Skip the leading underscores. */ + OB_PUTCP (name + 2); + + operand = TREE_OPERAND (value, i); + tc = TREE_CODE (operand); + + if (TREE_CODE_CLASS (tc) == 't') + /* We can get here with sizeof, e.g.: + + template <class T> void f(A<sizeof(T)>); */ + build_mangled_name_for_type (operand); + else + build_overload_value (TREE_TYPE (operand), + operand, + mf_maybe_uninstantiated); + } + } + else + { + /* We don't ever want this output, but it's + inconvenient not to be able to build the string. + This should cause assembler errors we'll notice. */ + + static int n; + bad_value: + sprintf (digit_buffer, " *%d", n++); + OB_PUTCP (digit_buffer); + } + + OB_PUTC ('W'); + numeric_output_need_bar = 0; +} + +/* Encoding for an INTEGER_CST value. */ + +static void +build_overload_int (value, flags) + tree value; + mangling_flags flags; +{ + int multiple_words_p = 0; + int multiple_digits_p = 0; + + if ((flags & mf_maybe_uninstantiated) && TREE_CODE (value) != INTEGER_CST) + { + mangle_expression (value); + return; + } + + /* Unless we were looking at an uninstantiated template, integers + should always be represented by constants. */ + my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); + + /* If value doesn't fit in a single HOST_WIDE_INT, we must use a + special output routine that can deal with this. */ + if (! host_integerp (value, 0)) + { + multiple_words_p = 1; + /* And there is certainly going to be more than one digit. */ + multiple_digits_p = 1; + } + else + multiple_digits_p = ((HOST_WIDE_INT) TREE_INT_CST_LOW (value) > 9 + || (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < -9); + + /* If necessary, add a leading underscore. */ + if (multiple_digits_p && (flags & mf_use_underscores_around_value)) + OB_PUTC ('_'); + + /* Output the number itself. */ + if (multiple_words_p) + dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); + else + icat (TREE_INT_CST_LOW (value)); + + if (flags & mf_use_underscores_around_value) + { + if (multiple_digits_p) + OB_PUTC ('_'); + /* Whether or not there were multiple digits, we don't need an + underscore. We've either terminated the number with an + underscore, or else it only had one digit. */ + numeric_output_need_bar = 0; + } + else + /* We just output a numeric value. */ + numeric_output_need_bar = 1; +} + + +/* Output S followed by a representation of the TEMPLATE_PARM_INDEX + supplied in INDEX. */ + +static void +build_mangled_template_parm_index (s, index) + const char *s; + tree index; +{ + OB_PUTCP (s); + build_underscore_int (TEMPLATE_PARM_IDX (index)); + /* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a + representation of the function from the point of view of its + type. */ + build_underscore_int (TEMPLATE_PARM_LEVEL (index)); +} + + +/* Mangling for C9X integer types (and Cygnus extensions for 128-bit + and other types) is based on the letter "I" followed by the hex + representations of the bitsize for the type in question. For + encodings that result in larger than two digits, a leading and + trailing underscore is added. + + Thus: + int1_t = 001 = I01 + int8_t = 008 = I08 + int16_t = 010 = I10 + int24_t = 018 = I18 + int32_t = 020 = I20 + int64_t = 040 = I40 + int80_t = 050 = I50 + int128_t = 080 = I80 + int256_t = 100 = I_100_ + int512_t = 200 = I_200_ + + Given an integer in decimal format, mangle according to this scheme. */ + +#if HOST_BITS_PER_WIDE_INT >= 64 +static void +build_mangled_C9x_name (bits) + int bits; +{ + char mangled[10] = ""; + + if (bits > 255) + sprintf (mangled, "I_%x_", bits); + else + sprintf (mangled, "I%.2x", bits); + + OB_PUTCP (mangled); +} +#endif + +static void +build_overload_value (type, value, flags) + tree type, value; + mangling_flags flags; +{ + my_friendly_assert (TYPE_P (type), 0); + + while (TREE_CODE (value) == NON_LVALUE_EXPR + || TREE_CODE (value) == NOP_EXPR) + value = TREE_OPERAND (value, 0); + + if (numeric_output_need_bar) + { + OB_PUTC ('_'); + numeric_output_need_bar = 0; + } + + if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) + { + build_mangled_template_parm_index ("Y", value); + return; + } + + if (TYPE_PTRMEM_P (type)) + { + if (TREE_CODE (value) != PTRMEM_CST) + /* We should have already rejected this pointer to member, + since it is not a constant. */ + my_friendly_abort (0); + + /* Get the actual FIELD_DECL. */ + value = PTRMEM_CST_MEMBER (value); + my_friendly_assert (TREE_CODE (value) == FIELD_DECL, 0); + + /* Output the name of the field. */ + build_overload_identifier (DECL_NAME (value)); + return; + } + else if (INTEGRAL_TYPE_P (type)) + { + build_overload_int (value, flags); + return; + } + + /* The only case where we use the extra underscores here is when + forming the mangling for an integral non-type template argument. + If that didn't happen, stop now. */ + flags &= ~mf_use_underscores_around_value; + + switch (TREE_CODE (type)) + { + case REAL_TYPE: + { + REAL_VALUE_TYPE val; + char *bufp = digit_buffer; + + /* We must handle non-constants in templates. */ + if (TREE_CODE (value) != REAL_CST) + { + mangle_expression (value); + break; + } + + val = TREE_REAL_CST (value); + if (REAL_VALUE_ISNAN (val)) + { + sprintf (bufp, "NaN"); + } + else + { + if (REAL_VALUE_NEGATIVE (val)) + { + val = REAL_VALUE_NEGATE (val); + *bufp++ = 'm'; + } + if (REAL_VALUE_ISINF (val)) + { + sprintf (bufp, "Infinity"); + } + else + { + REAL_VALUE_TO_DECIMAL (val, "%.20e", bufp); + bufp = (char *) index (bufp, 'e'); + if (!bufp) + strcat (digit_buffer, "e0"); + else + { + char *p; + bufp++; + if (*bufp == '-') + { + *bufp++ = 'm'; + } + p = bufp; + if (*p == '+') + p++; + while (*p == '0') + p++; + if (*p == 0) + { + *bufp++ = '0'; + *bufp = 0; + } + else if (p != bufp) + { + while (*p) + *bufp++ = *p++; + *bufp = 0; + } + } +#ifdef NO_DOT_IN_LABEL + bufp = (char *) index (bufp, '.'); + if (bufp) + *bufp = '_'; +#endif + } + } + OB_PUTCP (digit_buffer); + numeric_output_need_bar = 1; + return; + } + case POINTER_TYPE: + if (TREE_CODE (value) == INTEGER_CST) + { + build_overload_int (value, flags); + return; + } + else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) + { + build_mangled_template_parm_index ("", value); + numeric_output_need_bar = 1; + return; + } + + value = TREE_OPERAND (value, 0); + + /* Fall through. */ + + case REFERENCE_TYPE: + if (TREE_CODE (value) == ADDR_EXPR) + value = TREE_OPERAND (value, 0); + + if (TREE_CODE (value) == VAR_DECL) + { + my_friendly_assert (DECL_NAME (value) != 0, 245); + build_overload_identifier (DECL_ASSEMBLER_NAME (value)); + return; + } + else if (TREE_CODE (value) == FUNCTION_DECL) + { + my_friendly_assert (DECL_NAME (value) != 0, 246); + build_overload_identifier (DECL_ASSEMBLER_NAME (value)); + return; + } + else if (TREE_CODE (value) == SCOPE_REF) + build_overload_scope_ref (value); + else + my_friendly_abort (71); + break; /* not really needed */ + + case RECORD_TYPE: + { + tree delta; + tree idx; + tree pfn; + tree delta2; + tree fn; + + my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 0); + + /* We'll get a ADDR_EXPR of a SCOPE_REF here if we're + mangling, an instantiation of something like: + + template <class T, void (T::*fp)()> class C {}; + template <class T> C<T, &T::f> x(); + + We mangle the return type of the function, and that + contains template parameters. */ + if (TREE_CODE (value) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (value, 0)) == SCOPE_REF) + { + build_overload_scope_ref (TREE_OPERAND (value, 0)); + break; + } + + my_friendly_assert (TREE_CODE (value) == PTRMEM_CST, 0); + + expand_ptrmemfunc_cst (value, &delta, &idx, &pfn, &delta2); + fn = PTRMEM_CST_MEMBER (value); + build_overload_int (delta, flags); + OB_PUTC ('_'); + if (!flag_new_abi) + { + build_overload_int (idx, flags); + OB_PUTC ('_'); + } + else if (DECL_VIRTUAL_P (fn)) + { + build_overload_int (DECL_VINDEX (fn), flags); + OB_PUTC ('_'); + } + + if (!DECL_VIRTUAL_P (fn)) + { + numeric_output_need_bar = 0; + build_overload_identifier (DECL_ASSEMBLER_NAME (fn)); + } + else if (!flag_new_abi) + { + OB_PUTC ('i'); + build_overload_int (delta2, flags); + } + } + break; + + default: + sorry ("conversion of %s as template parameter", + tree_code_name [(int) TREE_CODE (type)]); + my_friendly_abort (72); + } +} + + +/* Add encodings for the declaration of template template parameters. + PARMLIST must be a TREE_VEC. */ + +static void +build_template_template_parm_names (parmlist) + tree parmlist; +{ + int i, nparms; + + my_friendly_assert (TREE_CODE (parmlist) == TREE_VEC, 246.5); + nparms = TREE_VEC_LENGTH (parmlist); + icat (nparms); + for (i = 0; i < nparms; i++) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); + if (TREE_CODE (parm) == TYPE_DECL) + { + /* This parameter is a type. */ + OB_PUTC ('Z'); + } + else if (TREE_CODE (parm) == TEMPLATE_DECL) + { + /* This parameter is a template. */ + OB_PUTC ('z'); + build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm)); + } + else + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); + } +} + + +/* Add encodings for the vector of template parameters in PARMLIST, + given the vector of arguments to be substituted in ARGLIST. */ + +static void +build_template_parm_names (parmlist, arglist) + tree parmlist; + tree arglist; +{ + int i, nparms; + tree inner_args = INNERMOST_TEMPLATE_ARGS (arglist); + + nparms = TREE_VEC_LENGTH (parmlist); + icat (nparms); + for (i = 0; i < nparms; i++) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); + tree arg = TREE_VEC_ELT (inner_args, i); + if (TREE_CODE (parm) == TYPE_DECL) + { + /* This parameter is a type. */ + OB_PUTC ('Z'); + build_mangled_name_for_type (arg); + } + else if (TREE_CODE (parm) == TEMPLATE_DECL) + { + /* This parameter is a template. */ + if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + /* Output parameter declaration, argument index and level. */ + build_mangled_name_for_type (arg); + else + { + /* A TEMPLATE_DECL node, output the parameter declaration + and template name */ + + OB_PUTC ('z'); + build_template_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (parm)); + icat (IDENTIFIER_LENGTH (DECL_NAME (arg))); + OB_PUTID (DECL_NAME (arg)); + } + } + else + { + parm = tsubst (parm, arglist, /*complain=*/1, NULL_TREE); + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); + build_overload_value (TREE_TYPE (parm), arg, + ((mf_maybe_uninstantiated + * uses_template_parms (arglist)) + | mf_use_underscores_around_value)); + } + } + } + +/* Output the representation for NAME, which is either a TYPE_DECL or + an IDENTIFIER. */ + +static void +build_overload_identifier (name) + tree name; +{ + if (TREE_CODE (name) == TYPE_DECL + && CLASS_TYPE_P (TREE_TYPE (name)) + && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)) + && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name))) + || (TREE_CODE (CP_DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE + (TREE_TYPE (name)))) + == FUNCTION_DECL))) + { + /* NAME is the TYPE_DECL for a template specialization. */ + tree template, parmlist, arglist, tname; + template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)); + arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name)); + tname = DECL_NAME (template); + parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); + OB_PUTC ('t'); + icat (IDENTIFIER_LENGTH (tname)); + OB_PUTID (tname); + build_template_parm_names (parmlist, arglist); + } + else + { + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + if (numeric_output_need_bar) + { + OB_PUTC ('_'); + numeric_output_need_bar = 0; + } + icat (IDENTIFIER_LENGTH (name)); + OB_PUTID (name); + } +} + +/* Given DECL, either a class TYPE, TYPE_DECL or FUNCTION_DECL, produce + the mangling for it. Used by build_mangled_name and build_static_name. */ + +static void +build_qualified_name (decl) + tree decl; +{ + tree context; + int i = 1; + + if (TYPE_P (decl)) + decl = TYPE_NAME (decl); + + /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ + if (TREE_CODE (decl) == TYPE_DECL + && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling) + { + tree id = DECL_ASSEMBLER_NAME (decl); + OB_PUTID (id); + if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1])) + numeric_output_need_bar = 1; + return; + } + + context = decl; + /* If we can't find a Ktype, do it the hard way. */ + if (check_ktype (context, FALSE) == -1) + { + /* Count type and namespace scopes. */ + while (1) + { + context = CP_DECL_CONTEXT (context); + if (context == global_namespace) + break; + i += 1; + if (check_ktype (context, FALSE) != -1) + /* Found one! */ + break; + if (TYPE_P (context)) + context = TYPE_NAME (context); + } + } + + if (i > 1) + { + OB_PUTC ('Q'); + build_underscore_int (i); + numeric_output_need_bar = 0; + } + build_overload_nested_name (decl); +} + +/* Output the mangled representation for TYPE. If EXTRA_GCODE is + non-zero, mangled names for structure/union types are intentionally + mangled differently from the method described in the ARM. */ + +static void +build_mangled_name_for_type_with_Gcode (type, extra_Gcode) + tree type; + int extra_Gcode; +{ + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + process_modifiers (type); + process_overload_item (type, extra_Gcode); +} + +/* Like build_mangled_name_for_type_with_Gcode, but never outputs the + `G'. */ + +static void +build_mangled_name_for_type (type) + tree type; +{ + build_mangled_name_for_type_with_Gcode (type, 0); +} + +/* Given a list of parameters in PARMTYPES, create an unambiguous + overload string. Should distinguish any type that C (or C++) can + distinguish. I.e., pointers to functions are treated correctly. + + Caller must deal with whether a final `e' goes on the end or not. + + Any default conversions must take place before this function + is called. + + BEGIN and END control initialization and finalization of the + obstack where we build the string. */ + +char * +build_overload_name (parmtypes, begin, end) + tree parmtypes; + int begin, end; +{ + char *ret; + + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200005221); + + start_squangling (); + ret = build_mangled_name (parmtypes, begin, end); + end_squangling (); + return ret ; +} + +/* Output the mangled representation for PARMTYPES. If PARMTYPES is a + TREE_LIST, then it is a list of parameter types. Otherwise, + PARMTYPES must be a single type. */ + +static char * +build_mangled_name (parmtypes, begin, end) + tree parmtypes; + int begin, end; +{ + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200004105); + + if (begin) + OB_INIT (); + + if (TREE_CODE (parmtypes) != TREE_LIST) + /* There is only one type. */ + build_mangled_name_for_type (parmtypes); + else + { + /* There are several types in a parameter list. */ + int nrepeats = 0; + int old_style_repeats = !flag_do_squangling && !nofold && typevec; + tree last_type = NULL_TREE; + + for (; parmtypes && parmtypes != void_list_node; + parmtypes = TREE_CHAIN (parmtypes)) + { + /* We used to call canonical_type_variant here, but that isn't + good enough; it doesn't handle pointers to typedef types. So + we can't just set TREE_USED to say we've seen a type already; + we have to check each of the earlier types with same_type_p. */ + tree parmtype = TREE_VALUE (parmtypes); + + if (old_style_repeats) + { + /* Every argument gets counted. */ + my_friendly_assert (maxtype < VARRAY_SIZE (typevec), 387); + VARRAY_TREE (typevec, maxtype) = parmtype; + maxtype++; + } + + if (last_type && same_type_p (parmtype, last_type)) + { + if (flag_do_squangling + || (old_style_repeats + && is_back_referenceable_type (parmtype))) + { + /* The next type is the same as this one. Keep + track of the repetition, and output the repeat + count later. */ + nrepeats++; + continue; + } + } + else if (nrepeats != 0) + { + /* Indicate how many times the previous parameter was + repeated. */ + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + last_type = parmtype; + + /* Note that for bug-compatibility with 2.7.2, we can't build up + repeats of types other than the most recent one. So we call + flush_repeats every round, if we get this far. */ + if (old_style_repeats && flush_repeats (0, parmtype)) + continue; + + /* Output the PARMTYPE. */ + build_mangled_name_for_type_with_Gcode (parmtype, 1); + } + + /* Output the repeat count for the last parameter, if + necessary. */ + if (nrepeats != 0) + { + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + if (!parmtypes) + /* The parameter list ends in an ellipsis. */ + OB_PUTC ('e'); + } + + if (end) + OB_FINISH (); + return (char *) obstack_base (&scratch_obstack); +} + +/* Emit modifiers such as constant, read-only, and volatile. */ + +static void +process_modifiers (parmtype) + tree parmtype; +{ + /* Note that here we do not use CP_TYPE_CONST_P and friends because + we describe types recursively; we will get the `const' in + `const int ()[10]' when processing the `const int' part. */ + if (TYPE_READONLY (parmtype)) + OB_PUTC ('C'); + if (TREE_CODE (parmtype) == INTEGER_TYPE + && parmtype != char_type_node + && parmtype != wchar_type_node + && (TYPE_MAIN_VARIANT (parmtype) + == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) + && ! TYPE_FOR_JAVA (parmtype)) + OB_PUTC ('U'); + if (TYPE_VOLATILE (parmtype)) + OB_PUTC ('V'); + /* It would be better to use `R' for `restrict', but that's already + used for reference types. And `r' is used for `long double'. */ + if (TYPE_RESTRICT (parmtype)) + OB_PUTC ('u'); +} + +/* Check to see if TYPE has been entered into the Bcode typelist. If + so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE + to the list of back-referenceable types and return 0. */ + +static int +check_btype (type) + tree type; +{ + size_t x; + + if (btypelist == NULL) + return 0; + + if (!is_back_referenceable_type (type)) + return 0; + + for (x = 0; x < maxbtype; x++) + if (same_type_p (type, VARRAY_TREE (btypelist, x))) + { + OB_PUTC ('B'); + icat (x); + if (x > 9) + OB_PUTC ('_'); + return 1 ; + } + + if (VARRAY_SIZE (btypelist) <= maxbtype) + /* Enlarge the table. */ + VARRAY_GROW (btypelist, + VARRAY_SIZE (btypelist) * 3 / 2); + + /* Register the TYPE. */ + VARRAY_TREE (btypelist, maxbtype) = type; + maxbtype++; + + return 0; +} + +/* Emit the correct code for various node types. */ + +static void +process_overload_item (parmtype, extra_Gcode) + tree parmtype; + int extra_Gcode; +{ + numeric_output_need_bar = 0; + + /* Our caller should have already handed any qualifiers, so pull out the + TYPE_MAIN_VARIANT to avoid typedef confusion. Except we can't do that + for arrays, because they are transparent to qualifiers. Sigh. */ + if (TREE_CODE (parmtype) == ARRAY_TYPE) + parmtype = canonical_type_variant (parmtype); + else + parmtype = TYPE_MAIN_VARIANT (parmtype); + + /* These tree types are considered modifiers for B code squangling, + and therefore should not get entries in the Btypelist. They are, + however, repeatable types. */ + + switch (TREE_CODE (parmtype)) + { + case REFERENCE_TYPE: + OB_PUTC ('R'); + goto more; + + case ARRAY_TYPE: + { + OB_PUTC ('A'); + if (TYPE_DOMAIN (parmtype) == NULL_TREE) + OB_PUTC ('_'); + else + { + tree length = array_type_nelts (parmtype); + if (TREE_CODE (length) != INTEGER_CST || flag_do_squangling) + { + length = fold (build (PLUS_EXPR, TREE_TYPE (length), + length, integer_one_node)); + STRIP_NOPS (length); + } + build_overload_value (sizetype, length, 1); + } + if (numeric_output_need_bar && ! flag_do_squangling) + OB_PUTC ('_'); + goto more; + } + + case POINTER_TYPE: + OB_PUTC ('P'); + more: + build_mangled_name_for_type (TREE_TYPE (parmtype)); + return; + break; + + default: + break; + } + + if (flag_do_squangling && check_btype (parmtype)) + /* If PARMTYPE is already in the list of back-referenceable types, + then check_btype will output the appropriate reference, and + there's nothing more to do. */ + return; + + switch (TREE_CODE (parmtype)) + { + case OFFSET_TYPE: + OB_PUTC ('O'); + build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype)); + OB_PUTC ('_'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + break; + + case FUNCTION_TYPE: + case METHOD_TYPE: + { + tree parms = TYPE_ARG_TYPES (parmtype); + + /* Rather than implementing a reentrant TYPEVEC, we turn off + repeat codes here, unless we're squangling. Squangling + doesn't make use of the TYPEVEC, so there's no reentrancy + problem. */ + int old_nofold = nofold; + if (!flag_do_squangling) + nofold = 1; + + if (TREE_CODE (parmtype) == METHOD_TYPE) + { + /* Mark this as a method. */ + OB_PUTC ('M'); + /* Output the class of which this method is a member. */ + build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype)); + /* Output any qualifiers for the `this' parameter. */ + process_modifiers (TREE_TYPE (TREE_VALUE (parms))); + } + + /* Output the parameter types. */ + OB_PUTC ('F'); + if (parms == NULL_TREE) + OB_PUTC ('e'); + else if (parms == void_list_node) + OB_PUTC ('v'); + else + build_mangled_name (parms, 0, 0); + + /* Output the return type. */ + OB_PUTC ('_'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + + nofold = old_nofold; + break; + } + + case INTEGER_TYPE: + if (parmtype == integer_type_node + || parmtype == unsigned_type_node + || parmtype == java_int_type_node) + OB_PUTC ('i'); + else if (parmtype == long_integer_type_node + || parmtype == long_unsigned_type_node) + OB_PUTC ('l'); + else if (parmtype == short_integer_type_node + || parmtype == short_unsigned_type_node + || parmtype == java_short_type_node) + OB_PUTC ('s'); + else if (parmtype == signed_char_type_node) + { + OB_PUTC ('S'); + OB_PUTC ('c'); + } + else if (parmtype == char_type_node + || parmtype == unsigned_char_type_node + || parmtype == java_byte_type_node) + OB_PUTC ('c'); + else if (parmtype == wchar_type_node + || parmtype == java_char_type_node) + OB_PUTC ('w'); + else if (parmtype == long_long_integer_type_node + || parmtype == long_long_unsigned_type_node + || parmtype == java_long_type_node) + OB_PUTC ('x'); + else if (parmtype == java_boolean_type_node) + OB_PUTC ('b'); +#if HOST_BITS_PER_WIDE_INT >= 64 + else + { + int bits = TREE_INT_CST_LOW (TYPE_SIZE (parmtype)); + build_mangled_C9x_name (bits); + } +#else + else + my_friendly_abort (73); +#endif + break; + + case BOOLEAN_TYPE: + OB_PUTC ('b'); + break; + + case REAL_TYPE: + if (parmtype == long_double_type_node) + OB_PUTC ('r'); + else if (parmtype == double_type_node + || parmtype == java_double_type_node) + OB_PUTC ('d'); + else if (parmtype == float_type_node + || parmtype == java_float_type_node) + OB_PUTC ('f'); + else my_friendly_abort (74); + break; + + case COMPLEX_TYPE: + OB_PUTC ('J'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + break; + + case VOID_TYPE: + OB_PUTC ('v'); + break; + + case ERROR_MARK: /* not right, but nothing is anyway */ + break; + + /* have to do these */ + case UNION_TYPE: + case RECORD_TYPE: + { + if (extra_Gcode) + OB_PUTC ('G'); /* make it look incompatible with AT&T */ + /* drop through into next case */ + } + case ENUMERAL_TYPE: + { + tree name = TYPE_NAME (parmtype); + + my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248); + + build_qualified_name (name); + break; + } + + case UNKNOWN_TYPE: + /* This will take some work. */ + OB_PUTC ('?'); + break; + + case TEMPLATE_TEMPLATE_PARM: + /* Find and output the original template parameter + declaration. */ + if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parmtype)) + { + build_mangled_template_parm_index ("tzX", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + build_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (parmtype)), + TYPE_TI_ARGS (parmtype)); + } + else + { + build_mangled_template_parm_index ("ZzX", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + build_template_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype))); + } + break; + + case TEMPLATE_TYPE_PARM: + build_mangled_template_parm_index ("X", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + break; + + case TYPENAME_TYPE: + /* When mangling the type of a function template whose + declaration looks like: + + template <class T> void foo(typename T::U) + + we have to mangle these. */ + build_qualified_name (parmtype); + break; + + default: + my_friendly_abort (75); + } + +} + +/* Produce the mangling for a variable named NAME in CONTEXT, which can + be either a class TYPE or a FUNCTION_DECL. */ + +tree +build_static_name (context, name) + tree context, name; +{ + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200004106); + + OB_INIT (); + numeric_output_need_bar = 0; + start_squangling (); +#ifdef JOINER + OB_PUTC ('_'); + build_qualified_name (context); + OB_PUTC (JOINER); +#else + OB_PUTS ("__static_"); + build_qualified_name (context); + OB_PUTC ('_'); +#endif + OB_PUTID (name); + OB_FINISH (); + end_squangling (); + + return get_identifier ((char *)obstack_base (&scratch_obstack)); +} + +/* FOR_METHOD should be 1 if the declaration in question is for a member + of a class (including a static member) and 2 if the declaration is + for a constructor. */ +tree +build_decl_overload_real (decl, parms, ret_type, tparms, targs, + for_method) + tree decl; + tree parms; + tree ret_type; + tree tparms; + tree targs; + int for_method; +{ + const char *name; + enum tree_code operator_code; + + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 20000410); + + operator_code = DECL_OVERLOADED_OPERATOR_P (decl); + if (!DECL_CONV_FN_P (decl) && operator_code) + { + /* member operators new and delete look like methods at this + point. */ + if (! for_method && CP_DECL_CONTEXT (decl) == global_namespace + && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST + && TREE_CHAIN (parms) == void_list_node) + switch (operator_code) + { + case DELETE_EXPR: + return get_identifier ("__builtin_delete"); + case VEC_DELETE_EXPR: + return get_identifier ("__builtin_vec_delete"); + case NEW_EXPR: + return get_identifier ("__builtin_new"); + case VEC_NEW_EXPR: + return get_identifier ("__builtin_vec_new"); + default: + break; + } + + if (DECL_ASSIGNMENT_OPERATOR_P (decl)) + name = assignment_operator_name_info[(int) operator_code].mangled_name; + else + name = operator_name_info[(int) operator_code].mangled_name; + } + else + name = IDENTIFIER_POINTER (DECL_NAME (decl)); + + start_squangling (); + OB_INIT (); + if (for_method != 2) + OB_PUTCP (name); + /* Otherwise, we can divine that this is a constructor, + and figure out its name without any extra encoding. */ + + OB_PUTC2 ('_', '_'); + numeric_output_need_bar = 0; + + if (tparms) + { + OB_PUTC ('H'); + build_template_parm_names (tparms, targs); + OB_PUTC ('_'); + } + else if (!for_method && CP_DECL_CONTEXT (decl) == global_namespace) + OB_PUTC ('F'); + + if (!for_method && CP_DECL_CONTEXT (decl) != global_namespace) + /* qualify with namespace */ + build_qualified_name (CP_DECL_CONTEXT (decl)); + + if (parms == NULL_TREE) + OB_PUTC ('e'); + else if (parms == void_list_node) + OB_PUTC ('v'); + else + { + if (!flag_do_squangling) + { + /* Allocate typevec array. */ + size_t typevec_size = list_length (parms); + maxtype = 0; + if (!for_method && CP_DECL_CONTEXT (decl) != global_namespace) + /* The namespace of a global function needs one slot. */ + typevec_size++; + VARRAY_TREE_INIT (typevec, typevec_size, "typevec"); + } + nofold = 0; + + if (for_method) + { + tree this_type = TREE_TYPE (TREE_VALUE (parms)); + + build_mangled_name_for_type (this_type); + + if (!flag_do_squangling) + { + my_friendly_assert (maxtype < VARRAY_SIZE (typevec), 387); + VARRAY_TREE (typevec, maxtype) = this_type; + maxtype++; + } + + if (TREE_CHAIN (parms)) + build_mangled_name (TREE_CHAIN (parms), 0, 0); + else + OB_PUTC ('e'); + } + else + { + /* the namespace qualifier for a global function + will count as type */ + if (CP_DECL_CONTEXT (decl) != global_namespace + && !flag_do_squangling) + { + my_friendly_assert (maxtype < VARRAY_SIZE (typevec), 387); + VARRAY_TREE (typevec, maxtype) = CP_DECL_CONTEXT (decl); + maxtype++; + } + build_mangled_name (parms, 0, 0); + } + + if (!flag_do_squangling) + /* Deallocate typevec array. */ + VARRAY_FREE (typevec); + } + + if (ret_type != NULL_TREE && for_method != 2) + { + /* Add the return type. */ + OB_PUTC ('_'); + build_mangled_name_for_type (ret_type); + } + + OB_FINISH (); + end_squangling (); + { + tree n = get_identifier (obstack_base (&scratch_obstack)); + return n; + } +} + /* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ void set_mangled_name_for_decl (decl) tree decl; { + tree parm_types; + if (processing_template_decl) /* There's no need to mangle the name of a template function. */ return; - DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); - return; + if (flag_new_abi) + { + DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + return; + } + + parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); + + if (DECL_STATIC_FUNCTION_P (decl)) + parm_types = + hash_tree_chain (build_pointer_type (DECL_CONTEXT (decl)), + parm_types); + else + /* The only member functions whose type is a FUNCTION_TYPE, rather + than a METHOD_TYPE, should be static members. */ + my_friendly_assert (!DECL_CONTEXT (decl) + || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl))) + || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE, + 0); + + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload_real (decl, parm_types, NULL_TREE, + NULL_TREE, NULL_TREE, + DECL_FUNCTION_MEMBER_P (decl) + + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)); +} + +/* Build an overload name for the type expression TYPE. */ + +tree +build_typename_overload (type) + tree type; +{ + tree id; + + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200004108); + + OB_INIT (); + OB_PUTS (OPERATOR_TYPENAME_FORMAT); + nofold = 1; + start_squangling (); + build_mangled_name (type, 0, 1); + id = get_identifier (obstack_base (&scratch_obstack)); + IDENTIFIER_OPNAME_P (id) = 1; + IDENTIFIER_TYPENAME_P (id) = 1; + TREE_TYPE (id) = type; + end_squangling (); + return id; +} + +tree +build_overload_with_type (name, type) + tree name, type; +{ + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200004109); + + OB_INIT (); + OB_PUTID (name); + nofold = 1; + + start_squangling (); + build_mangled_name (type, 0, 1); + end_squangling (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +tree +get_id_2 (name, name2) + const char *name; + tree name2; +{ + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 20000411); + + OB_INIT (); + OB_PUTCP (name); + OB_PUTID (name2); + OB_FINISH (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +/* Returns the name of a construction vtable group. TYPE is the most + derived class in the hierarhcy. BINFO is the most derived class in + the construction vtable group. */ + +tree +get_ctor_vtbl_name (type, binfo) + tree type; + tree binfo; +{ + /* This function is obsoleted by the new ABI. */ + my_friendly_assert (!flag_new_abi, 200005220); + + start_squangling (); + OB_INIT (); + OB_PUTCP (CTOR_VTBL_NAME_PREFIX); + build_mangled_name (type, 0, 0); + OB_PUTC ('_'); + build_mangled_name (BINFO_TYPE (binfo), 0, 0); + OB_PUTC ('_'); + build_overload_int (BINFO_OFFSET (binfo), mf_none); + OB_FINISH (); + end_squangling (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */ + +tree +build_destructor_name (type) + tree type; +{ + return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX), + type); } /* Given a tree_code CODE, and some arguments (at least one), @@ -281,7 +2080,30 @@ make_thunk (function, delta, vcall_index) if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); - thunk_id = mangle_thunk (TREE_OPERAND (function, 0), delta, vcall_offset); + if (flag_new_abi) + thunk_id = mangle_thunk (TREE_OPERAND (function, 0), delta, vcall_offset); + else + { + OB_INIT (); + OB_PUTS ("__thunk_"); + if (delta > 0) + { + OB_PUTC ('n'); + icat (delta); + } + else + icat (-delta); + OB_PUTC ('_'); + if (vcall_index) + { + icat (vcall_index); + OB_PUTC ('_'); + } + OB_PUTID (DECL_ASSEMBLER_NAME (func_decl)); + OB_FINISH (); + thunk_id = get_identifier (obstack_base (&scratch_obstack)); + } + thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); if (thunk && !DECL_THUNK_P (thunk)) { diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def index 588e2c53618..ec0838c2917 100644 --- a/gcc/cp/operators.def +++ b/gcc/cp/operators.def @@ -40,12 +40,16 @@ Boston, MA 02111-1307, USA. */ assignment operators, the same tree-codes are reused; i.e., `operator +' will also have PLUS_EXPR as its CODE. - MANGLING + NEW_MANGLING The mangling prefix for the operator, as a C string, and as mangled under the new ABI. For `operator +', for example, this would be "pl". + OLD_MANGLING + + Analagous, but for the old ABI. + ARITY The arity of the operator, or -1 if any arity is allowed. (As @@ -67,84 +71,84 @@ Boston, MA 02111-1307, USA. */ arguments are as for DEF_OPERATOR, but there is no need to provide an ASSIGNMENT_P argument; it is always zero. */ -#define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, ARITY) \ - DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, 0) +#define DEF_SIMPLE_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY) \ + DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, 0) /* Use DEF_ASSN_OPERATOR to define an assignment operator. Its arguments are as for DEF_OPERATOR, but there is no need to provide an ASSIGNMENT_P argument; it is always one. */ -#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, ARITY) \ - DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, 1) +#define DEF_ASSN_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY) \ + DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, 1) /* Memory allocation operators. */ -DEF_SIMPLE_OPERATOR ("new", NEW_EXPR, "nw", -1) -DEF_SIMPLE_OPERATOR ("new []", VEC_NEW_EXPR, "na", -1) -DEF_SIMPLE_OPERATOR ("delete", DELETE_EXPR, "dl", -1) -DEF_SIMPLE_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", -1) +DEF_SIMPLE_OPERATOR ("new", NEW_EXPR, "nw", "__nw", -1) +DEF_SIMPLE_OPERATOR ("new []", VEC_NEW_EXPR, "na", "__vn", -1) +DEF_SIMPLE_OPERATOR ("delete", DELETE_EXPR, "dl", "__dl", -1) +DEF_SIMPLE_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", "__vd", -1) /* Unary operators. */ -DEF_SIMPLE_OPERATOR ("+", CONVERT_EXPR, "ps", 1) -DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", 1) -DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", 1) -DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", 1) -DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", 1) -DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", 1) -DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", 1) -DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", 1) -DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", 1) +DEF_SIMPLE_OPERATOR ("+", CONVERT_EXPR, "ps", "__pl", 1) +DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", "__mi", 1) +DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", "__ad", 1) +DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", "__ml", 1) +DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", "__co", 1) +DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", "__nt", 1) +DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", "__pp", 1) +DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", "__mm", 1) +DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", "__sz", 1) /* This is an extension. */ -DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "vx7alignof", 1) +DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "vx7alignof", "__al", 1) /* The cast operator. */ -DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", 1) +DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", OPERATOR_TYPENAME_FORMAT, 1) /* Binary operators. */ -DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", 2) -DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", 2) -DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", 2) -DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", 2) -DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", 2) -DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", 2) -DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", 2) -DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", 2) -DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", 2) -DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", 2) -DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", 2) -DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", 2) -DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", 2) -DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", 2) -DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", 2) -DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", 2) -DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2) -DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2) -DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2) -DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2) -DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2) -DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2) -DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2) -DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2) +DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", "__pl", 2) +DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", "__mi", 2) +DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", "__ml", 2) +DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", "__dv", 2) +DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", "__md", 2) +DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", "__ad", 2) +DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", "__or", 2) +DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", "__er", 2) +DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", "__ls", 2) +DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", "__rs", 2) +DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", "__eq", 2) +DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", "__ne", 2) +DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", "__lt", 2) +DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", "__gt", 2) +DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", "__le", 2) +DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", "__ge", 2) +DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", "__aa", 2) +DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", "__oo", 2) +DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", "__cm", 2) +DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", "__rm", 2) +DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", "__rf", 2) +DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", "__vc", 2) +DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", "__pp", 2) +DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", "__mm", 2) /* These are extensions. */ -DEF_SIMPLE_OPERATOR ("<?", MIN_EXPR, "vx3min", 2) -DEF_SIMPLE_OPERATOR (">?", MAX_EXPR, "vx3max", 2) +DEF_SIMPLE_OPERATOR ("<?", MIN_EXPR, "vx3min", "__mn", 2) +DEF_SIMPLE_OPERATOR (">?", MAX_EXPR, "vx3max", "__mx", 2) /* This one is needed for mangling. */ -DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", 2); +DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", NULL, 2); /* Assignment operators. */ -DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", 2) -DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", 2) -DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", 2) -DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", 2) -DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", 2) -DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", 2) -DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", 2) -DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", 2) -DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", 2) -DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", 2) -DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", 2) +DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", "__as", 2) +DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", "__apl", 2) +DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", "__ami", 2) +DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", "__aml", 2) +DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", "__adv", 2) +DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", "__amd", 2) +DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", "__aad", 2) +DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", "__aor", 2) +DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", "__aer", 2) +DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", "__als", 2) +DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", "__ars", 2) /* Ternary operators. */ -DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3) +DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", "__cn", 3) /* Miscellaneous. */ -DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1) +DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", "__cl", -1) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ae8bc88709e..aab25c90b22 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -143,6 +143,7 @@ static tree tsubst_template_parms PARAMS ((tree, tree, int)); static void regenerate_decl_from_template PARAMS ((tree, tree)); static tree most_specialized PARAMS ((tree, tree, tree)); static tree most_specialized_class PARAMS ((tree, tree)); +static void set_mangled_name_for_template_decl PARAMS ((tree)); static int template_class_depth_real PARAMS ((tree, int)); static tree tsubst_aggr_type PARAMS ((tree, tree, int, tree, int)); static tree tsubst_decl PARAMS ((tree, tree, tree, tree)); @@ -1556,8 +1557,9 @@ check_explicit_specialization (declarator, decl, template_count, flags) treatment. We do this here so that the ordinary, non-template, name-mangling algorithm will not be used later. */ - if (is_member_template (tmpl) || ctype == NULL_TREE) - set_mangled_name_for_decl (decl); + if ((is_member_template (tmpl) || ctype == NULL_TREE) + && name_mangling_version >= 1) + set_mangled_name_for_template_decl (decl); if (is_friend && !have_def) /* This is not really a declaration of a specialization. @@ -4077,7 +4079,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl); if (!is_partial_instantiation) { - DECL_ASSEMBLER_NAME (type_decl) = mangle_decl (type_decl); + if (flag_new_abi) + DECL_ASSEMBLER_NAME (type_decl) = mangle_decl (type_decl); + else + DECL_ASSEMBLER_NAME (type_decl) + = get_identifier (build_overload_name (t, 1, 1)); /* For backwards compatibility; code that uses -fexternal-templates expects looking up a template to @@ -4503,10 +4509,11 @@ tsubst_friend_function (decl, args) DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0; /* The mangled name for the NEW_FRIEND is incorrect. The call to - tsubst will have resulted in a call to set_mangled_name_for_decl. - But, the function is not a template instantiation and should not - be mangled like one. Therefore, we remangle the function name. - We don't have to do this if the NEW_FRIEND is a template since + tsubst will have resulted in a call to + set_mangled_name_for_template_decl. But, the function is not a + template instantiation and should not be mangled like one. + Therefore, we remangle the function name. We don't have to do + this if the NEW_FRIEND is a template since set_mangled_name_for_template_decl doesn't do anything if the function declaration still uses template arguments. */ if (TREE_CODE (new_friend) != TEMPLATE_DECL) @@ -5697,9 +5704,14 @@ tsubst_decl (t, args, type, in_decl) /*entering_scope=*/1); if (member && DECL_CONV_FN_P (r)) - /* Type-conversion operator. Reconstruct the name, in - case it's the name of one of the template's parameters. */ - DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type)); + { + /* Type-conversion operator. Reconstruct the name, in + case it's the name of one of the template's parameters. */ + if (flag_new_abi) + DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type)); + else + DECL_NAME (r) = build_typename_overload (TREE_TYPE (type)); + } DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, /*complain=*/1, t); @@ -5733,7 +5745,30 @@ tsubst_decl (t, args, type, in_decl) register_specialization (r, gen_tmpl, argvec); /* Set the mangled name for R. */ - set_mangled_name_for_decl (r); + if (DECL_DESTRUCTOR_P (t)) + { + if (flag_new_abi) + set_mangled_name_for_decl (r); + else + DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx); + } + else + { + /* Instantiations of template functions must be mangled + specially, in order to conform to 14.5.5.1 + [temp.over.link]. */ + tree tmpl = DECL_TI_TEMPLATE (t); + + /* TMPL will be NULL if this is a specialization of a + member function of a template class. */ + if (name_mangling_version < 1 + || tmpl == NULL_TREE + || (member && !is_member_template (tmpl) + && !DECL_TEMPLATE_INFO (tmpl))) + set_mangled_name_for_decl (r); + else + set_mangled_name_for_template_decl (r); + } DECL_RTL (r) = 0; make_decl_rtl (r, NULL_PTR, 1); @@ -7050,7 +7085,10 @@ tsubst_copy (t, args, complain, in_decl) if (IDENTIFIER_TYPENAME_P (t)) { tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); - return mangle_conv_op_name_for_type (new_type); + if (flag_new_abi) + return mangle_conv_op_name_for_type (new_type); + else + return (build_typename_overload (new_type)); } else return t; @@ -9962,3 +10000,97 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp) return fn_type; } + +/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that + is either an instantiation or specialization of a template + function. */ + +static void +set_mangled_name_for_template_decl (decl) + tree decl; +{ + tree context = NULL_TREE; + tree fn_type; + tree ret_type; + tree parm_types; + tree tparms; + tree targs; + + my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0); + my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0); + + /* Under the new ABI, we don't need special machinery. */ + if (flag_new_abi) + { + set_mangled_name_for_decl (decl); + return; + } + + /* The names of template functions must be mangled so as to indicate + what template is being specialized with what template arguments. + For example, each of the following three functions must get + different mangled names: + + void f(int); + template <> void f<7>(int); + template <> void f<8>(int); */ + + targs = DECL_TI_ARGS (decl); + if (uses_template_parms (targs)) + /* This DECL is for a partial instantiation. There's no need to + mangle the name of such an entity. */ + return; + + /* We now compute the PARMS and RET_TYPE to give to + build_decl_overload_real. The PARMS and RET_TYPE are the + parameter and return types of the template, after all but the + innermost template arguments have been substituted, not the + parameter and return types of the function DECL. For example, + given: + + template <class T> T f(T); + + both PARMS and RET_TYPE should be `T' even if DECL is `int f(int)'. + A more subtle example is: + + template <class T> struct S { template <class U> void f(T, U); } + + Here, if DECL is `void S<int>::f(int, double)', PARMS should be + {int, U}. Thus, the args that we want to subsitute into the + return and parameter type for the function are those in TARGS, + with the innermost level omitted. */ + fn_type = get_mostly_instantiated_function_type (decl, &context, &tparms); + + /* Now, get the innermost parameters and arguments, and figure out + the parameter and return types. */ + tparms = INNERMOST_TEMPLATE_PARMS (tparms); + targs = INNERMOST_TEMPLATE_ARGS (targs); + ret_type = TREE_TYPE (fn_type); + parm_types = TYPE_ARG_TYPES (fn_type); + + /* For a static member function, we generate a fake `this' pointer, + for the purposes of mangling. This indicates of which class the + function is a member. Because of: + + [class.static] + + There shall not be a static and a nonstatic member function + with the same name and the same parameter types + + we don't have to worry that this will result in a clash with a + non-static member function. */ + if (DECL_STATIC_FUNCTION_P (decl)) + parm_types = hash_tree_chain (build_pointer_type (context), parm_types); + + /* There should be the same number of template parameters as + template arguments. */ + my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs), + 0); + + /* Actually set the DECL_ASSEMBLER_NAME. */ + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload_real (decl, parm_types, ret_type, + tparms, targs, + DECL_FUNCTION_MEMBER_P (decl) + + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)); +} diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 9696d3217a2..45c4c64d12e 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -83,22 +83,29 @@ void init_rtti_processing () { if (flag_honor_std) - push_namespace (std_identifier); + push_namespace (get_identifier ("std")); type_info_type_node = xref_tag (class_type_node, get_identifier ("type_info"), 1); if (flag_honor_std) pop_namespace (); if (!new_abi_rtti_p ()) { + tinfo_decl_id = get_identifier ("__tf"); tinfo_decl_type = build_function_type (build_reference_type (build_qualified_type (type_info_type_node, TYPE_QUAL_CONST)), void_list_node); + tinfo_var_id = get_identifier ("__ti"); } else - tinfo_decl_type = build_qualified_type - (type_info_type_node, TYPE_QUAL_CONST); + { + /* FIXME: These identifier prefixes are not set in stone yet. */ + tinfo_decl_id = get_identifier ("__ti"); + tinfo_var_id = get_identifier ("__tn"); + tinfo_decl_type = build_qualified_type + (type_info_type_node, TYPE_QUAL_CONST); + } } /* Given a pointer to an object with at least one virtual table @@ -326,12 +333,11 @@ static tree get_tinfo_var (type) tree type; { - tree tname; + tree tname = build_overload_with_type (tinfo_var_id, type); tree arrtype; int size; my_friendly_assert (!new_abi_rtti_p (), 20000118); - tname = mangle_typeinfo_for_type (type); if (IDENTIFIER_GLOBAL_VALUE (tname)) return IDENTIFIER_GLOBAL_VALUE (tname); @@ -367,7 +373,6 @@ get_tinfo_var (type) } /* Generate the NTBS name of a type. */ - static tree tinfo_name (type) tree type; @@ -375,7 +380,10 @@ tinfo_name (type) const char *name; tree name_string; - name = mangle_type_string (type); + if (flag_new_abi) + name = mangle_type_string (type); + else + name = build_overload_name (type, 1, 1); name_string = combine_strings (build_string (strlen (name) + 1, name)); return name_string; } @@ -401,10 +409,11 @@ get_tinfo_decl (type) type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); - if (new_abi_rtti_p ()) + if (flag_new_abi) name = mangle_typeinfo_for_type (type); else - name = mangle_typeinfo_fn_for_type (type); + name = build_overload_with_type (tinfo_decl_id, type); + d = IDENTIFIER_GLOBAL_VALUE (name); if (d) /* OK */; @@ -1306,7 +1315,10 @@ tinfo_base_init (desc, target) NULL_TREE); tree name_string = tinfo_name (target); - name_name = mangle_typeinfo_for_type (target); + if (flag_new_abi) + name_name = mangle_typeinfo_for_type (target); + else + name_name = build_overload_with_type (tinfo_var_id, target); name_decl = build_lang_decl (VAR_DECL, name_name, name_type); DECL_ARTIFICIAL (name_decl) = 1; @@ -1315,8 +1327,13 @@ tinfo_base_init (desc, target) DECL_EXTERNAL (name_decl) = 0; TREE_PUBLIC (name_decl) = 1; comdat_linkage (name_decl); - DECL_ASSEMBLER_NAME (name_decl) - = mangle_typeinfo_string_for_type (target); + if (flag_new_abi) + /* The new ABI specifies the external name of the string + containing the type's name. */ + DECL_ASSEMBLER_NAME (name_decl) + = mangle_typeinfo_string_for_type (target); + else + DECL_ASSEMBLER_NAME (name_decl) = DECL_NAME (name_decl); DECL_INITIAL (name_decl) = name_string; cp_finish_decl (name_decl, name_string, NULL_TREE, 0); } @@ -1682,7 +1699,9 @@ create_real_tinfo_var (name, type, init, non_public) tree hidden_name; char hidden[30]; - sprintf (hidden, "tinfo var %d", count++); + sprintf (hidden, "%.*s_%d", + IDENTIFIER_LENGTH (tinfo_decl_id), IDENTIFIER_POINTER (tinfo_decl_id), + count++); hidden_name = get_identifier (hidden); decl = build_lang_decl (VAR_DECL, hidden_name, diff --git a/gcc/cp/tinfo2.cc b/gcc/cp/tinfo2.cc index 39fe98c3be6..d74d4c8f9da 100644 --- a/gcc/cp/tinfo2.cc +++ b/gcc/cp/tinfo2.cc @@ -436,17 +436,17 @@ __dynamic_cast_2 (const type_info& (*from)(void), const type_info& (*to)(void), // must match the mangling in gcc/cp/rtti.c. #define BUILTIN(mangled) \ -unsigned char _ZTI##mangled [sizeof (__builtin_type_info)] \ +unsigned char __ti##mangled [sizeof (__builtin_type_info)] \ __attribute__ ((aligned (__alignof__ (void *)))); \ -extern "C" const type_info &_ZTF##mangled (void) { \ - if ((*(void **) _ZTI##mangled) == 0) \ - new (_ZTI##mangled) __builtin_type_info (#mangled); \ - return *(type_info *)_ZTI##mangled; \ +extern "C" const type_info &__tf##mangled (void) { \ + if ((*(void **) __ti##mangled) == 0) \ + new (__ti##mangled) __builtin_type_info (#mangled); \ + return *(type_info *)__ti##mangled; \ } BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b); -BUILTIN (c); BUILTIN (w); BUILTIN (e); BUILTIN (d); BUILTIN (f); -BUILTIN (j); BUILTIN (m); BUILTIN (y); BUILTIN (t); BUILTIN (h); -BUILTIN (a); +BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f); +BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc); +BUILTIN (Sc); #endif diff --git a/gcc/invoke.texi b/gcc/invoke.texi index 82720d395db..39989b6010a 100644 --- a/gcc/invoke.texi +++ b/gcc/invoke.texi @@ -111,7 +111,7 @@ in the following sections. -fhuge-objects -fno-implicit-templates -finit-priority -fno-implement-inlines -fname-mangling-version-@var{n} -fno-default-inline -fno-operator-names -fno-optional-diags -fpermissive --frepo -fstrict-prototype -ftemplate-depth-@var{n} +-frepo -fstrict-prototype -fsquangle -ftemplate-depth-@var{n} -fuse-cxa-atexit -fvtable-thunks -nostdinc++ -Wctor-dtor-privacy -Wno-deprecated -Weffc++ -Wno-non-template-friend -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wreorder @@ -1155,6 +1155,20 @@ errors if these functions are not inlined everywhere they are called. Disable pedwarns about constructs used in MFC, such as implicit int and getting a pointer to member function via non-standard syntax. +@item -fname-mangling-version-@var{n} +Control the way in which names are mangled. Version 0 is compatible +with versions of g++ before 2.8. Version 1 is the default. Version 1 +will allow correct mangling of function templates. For example, +version 0 mangling does not mangle foo<int, double> and foo<int, char> +given this declaration: + +@example +template <class T, class U> void foo(T t); +@end example + +Like all options that change the ABI, all C++ code, @emph{including +libgcc} must be built with the same setting of this option. + @item -fno-operator-names Do not treat the operator name keywords @code{and}, @code{bitand}, @code{bitor}, @code{compl}, @code{not}, @code{or} and @code{xor} as @@ -1197,6 +1211,18 @@ functions. This flag no longer affects declarations with C++ linkage. +@item -fsquangle +@itemx -fno-squangle +@samp{-fsquangle} will enable a compressed form of name mangling for +identifiers. In particular, it helps to shorten very long names by recognizing +types and class names which occur more than once, replacing them with special +short ID codes. This option also requires any C++ libraries being used to +be compiled with this option as well. The compiler has this disabled (the +equivalent of @samp{-fno-squangle}) by default. + +Like all options that change the ABI, all C++ code, @emph{including +libgcc.a} must be built with the same setting of this option. + @item -ftemplate-depth-@var{n} Set the maximum instantiation depth for template classes to @var{n}. A limit on the template instantiation depth is needed to detect |