From 1f6e1acc0f2017e81282604bda62db1b2b865075 Mon Sep 17 00:00:00 2001 From: Alex Samuel Date: Sun, 4 Jun 2000 21:12:27 +0000 Subject: [PATCH] Make-lang.in (CXX_SRCS): Add mangle.c. * Make-lang.in (CXX_SRCS): Add mangle.c. * Makefile.in (CXX_OBJS): Add mangle.o. (mangle.o): New rule. Co-Authored-By: Mark Mitchell From-SVN: r34394 --- gcc/cp/ChangeLog | 134 +- gcc/cp/Make-lang.in | 10 +- gcc/cp/Makefile.in | 3 +- gcc/cp/class.c | 25 +- gcc/cp/cp-tree.h | 41 +- gcc/cp/decl.c | 77 +- gcc/cp/decl2.c | 58 +- gcc/cp/expr.c | 79 - gcc/cp/mangle.c | 2128 +++++++++++++++++ gcc/cp/method.c | 78 +- gcc/cp/operators.def | 7 +- gcc/cp/pt.c | 175 +- gcc/cp/rtti.c | 35 +- gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C | 10 +- gcc/testsuite/g++.old-deja/g++.abi/vtable2.C | 8 +- .../g++.old-deja/g++.other/mangle1.C | 35 +- .../g++.old-deja/g++.other/mangle2.C | 42 - .../g++.old-deja/g++.other/static8.C | 8 +- 18 files changed, 2616 insertions(+), 337 deletions(-) create mode 100644 gcc/cp/mangle.c delete mode 100644 gcc/testsuite/g++.old-deja/g++.other/mangle2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9930544eed1..ce7b48e6d43 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,66 +1,78 @@ -2000-06-03 Mark Mitchell +2000-06-03 Alex Samuel + Mark Mitchell - * cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment. - (INNERMOST_TEMPLATE_ARGS): New macro. - (innermost_args): Remove. - (get_innermost_template_args): New function. - * decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS. - * error.c (dump_function_decl): Be caution when using - most_general_template. - * method.c (build_template_parm_names): Use - INNERMOST_TEMPLATE_ARGS. - * pt.c (add_to_template_args): Tidy comment - (get_innermost_template_args): New function. - (check_explicit_specialization): Clear DECL_INITIAL for a new - specialization. - (process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS. - Tidy. - (push_template_decl): Always register specializations of the most - general template. - (convert_template_argument): Use INNERMOST_TEMPLATE_ARGS. - (coerce_template_parms): Likewise. - (lookup_template_class): Likewise. - (innermost_args): Remove. - (tsubst_decl): Use INNERMOST_TEMPLATE_ARGS. - (tsubst_decl): Handle tricky specializations. Use - get_innermost_template_args. - (instantiate_template): Simplify handling of partial - instantiations. - (get_class_bindings): Use INNERMOST_TEMPLATE_ARGS. - (most_general_template): Reimplement, in a more straightforward - manner. - (regenerate_decl_from_template): Tweak formatting. Use - TMPL_ARGS_DEPTH for clarity. - (set_mangled_name_for_template_decl): Use INNERMOST_ARGS. + * Make-lang.in (CXX_SRCS): Add mangle.c. + * Makefile.in (CXX_OBJS): Add mangle.o. + (mangle.o): New rule. + + * class.c (local_classes): New variable. + * class.c (get_vtable_name): Use mangle_vtable_for_type for new ABI. + (get_vtt_name): Use mangle_vtt_name for new ABI. + (init_class_processing): Initialize local_classes. + (build_ctor_vtbl_group): Use mangle_ctor_vtbl_for_type for new ABI. + * cp-tree.h (cp_tree_index): Add CPTI_STD_IDENTIFIER. + (std_identifier): New macro. + (DECL_VOLATILE_MEMFUNC_P): New macro. + (DECL_NAMESPACE_STD_P): Likewise. + (local_classes): Declare. + (get_mostly_instantiated_function_type): Declare. + (init_mangle): Declare. + (mangle_decl): Likewise. + (mangle_type_string): Likewise. + (mangle_type): Likewise. + (mangle_typeinfo_for_type): Likewise. + (mangle_typeinfo_string_for_type): Likewise. + (mangle_vtbl_for_type): Likewise. + (mangle_vtt_for_type): Likewise. + (mangle_ctor_vtbl_for_type): Likewise. + (mangle_thunk): Likewise. + (mangle_conv_op_name_for_type): Likewise. + (mangle_guard_variable): Likewise. + * decl.c (pushtag): Keep track of local classes. + (initialize_predefined_identifiers): Initialize std_identifier. + (init_decl_processing): Use std_identifier. + (start_decl): Don't treat instantiations as specializations. + (grokdeclarator): Likewise. + (grokvardecl): Call mangle_decl for new ABI. Only set mangled + name for fully-instantiated templates. + * decl2.c (grokclassfn): Use set_mangled_name_for_decl for + destructors with the new ABI. + (finish_static_data_member_decl): Use mangle_decl under the new ABI. + (grokfield): Use mangle_type for new ABI. + (grokoptypename): Use mangle_conv_op_for_type for new ABI. + (get_sentry): Use mangle_guard_variable for new ABI. + (start_static_initialization_or_destruction): Likewise. + * expr.c (extract_aggr_init): Remove. + (extract_scalar_init): Likewise. + (extract_init): Remove #if 0'd code. + * mangle.c: New function. + * method.c (build_mangled_name): Assert not flag_new_abi. + (build_static_name): Likewise. + (build_decl_overload_real): Likewise. + (build_typename_overload): Likewise. + (build_overload_with_type): Likewise. + (build_overload_name): Likewise. + (get_ctor_vtbl_name): Likewise. + (start_squangling): Likewise. + (get_id_2): Likewise. + (set_mangled_name_for_decl): Call mangle_decl for new ABI. + (init_method): Call init_mangle for new ABI. + (make_thunk): Call mangle_thunk for new ABI. + * operators.def: Correct new ABI manglings for the `%' operator. + Add `::' operator. + * pt.c (build_template_decl): Copy DECL_OVERLOADED_OPERATOR_P and + DECL_ASSIGNMENT_OPERATOR_P to the TEMPLATE_DECL. + (lookup_template_class): Call mangle_decl for new ABI. + (get_mostly_instantiated_function_type): New function. + (set_mangled_name_for_template_decl): Use it. + (tsubst_decl): Use set_mangled_name_for_decl for destructors with + the new ABI. Use mangle_conv_op_name_for_type for instantiated + conversion op names. + * rtti.c (tinfo_name): Call mangle_type_string for new ABI. + (get_tinfo_decl): Call mangle_typeinfo_for_type for new ABI. + (tinfo_base_init): Likewise. Mangle typeinfo string name with + mangle_typeinfo_string_for_type. - * dump.c (dequeue_and_dump): Dump information about thunks. - -2000-06-02 Jason Merrill - - * exception.cc (__cp_pop_exception): If we aren't popping or - rethrowing, push down past any uncaught exceptions. - (__uncatch_exception): Rethrow the currently handled exception. - Move it to the top of the exception stack. - -Fri Jun 2 19:38:57 2000 Richard Kenner - - * cp-tree.h: Use struct tree_common instead of a char array. - * decl.c (grokdeclarator): Set DECL_NONADDRESSABLE_P instead - of TREE_ADDRESSABLE. - -2000-06-02 Richard Henderson - - * decl.c (init_decl_processing): Don't set lang_get_alias_set. - -2000-06-02 Jason Merrill - - * decl.c (store_return_init): Call put_var_into_stack. - -2000-06-01 Mark Mitchell - - * cp-tree.h (lang_decl_flags): Add anticipated_p. - (DECL_ANTICIPATED): Use it. - 2000-06-01 Richard Henderson * decl.c (init_decl_processing): Set lang_get_alias_set first thing. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 0d6fae85cea..92ade94309c 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -115,11 +115,11 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/class.c $(srcdir)/cp/cp-tree.def \ $(srcdir)/cp/errfn.c $(srcdir)/cp/error.c $(srcdir)/cp/except.c \ $(srcdir)/cp/expr.c $(srcdir)/cp/friend.c $(srcdir)/cp/init.c \ $(srcdir)/cp/input.c $(srcdir)/cp/lex.c $(srcdir)/cp/lex.h \ - $(srcdir)/cp/method.c $(srcdir)/cp/optimize.c $(srcdir)/cp/parse.y \ - $(srcdir)/cp/pt.c $(srcdir)/cp/ptree.c $(srcdir)/cp/repo.c \ - $(srcdir)/cp/rtti.c $(srcdir)/cp/search.c $(srcdir)/cp/semantics.c \ - $(srcdir)/cp/spew.c $(srcdir)/cp/tree.c $(srcdir)/cp/typeck.c \ - $(srcdir)/cp/typeck2.c $(srcdir)/cp/xref.c + $(srcdir)/cp/mangle.c $(srcdir)/cp/method.c $(srcdir)/cp/optimize.c \ + $(srcdir)/cp/parse.y $(srcdir)/cp/pt.c $(srcdir)/cp/ptree.c \ + $(srcdir)/cp/repo.c $(srcdir)/cp/rtti.c $(srcdir)/cp/search.c \ + $(srcdir)/cp/semantics.c $(srcdir)/cp/spew.c $(srcdir)/cp/tree.c \ + $(srcdir)/cp/typeck.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/xref.c cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o \ c-pragma.o $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def \ diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index e162294c1a6..6d9a6a97f8b 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -176,7 +176,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config -I$(srcdir) CXX_OBJS = call.o decl.o errfn.o expr.o pt.o typeck2.o \ class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \ except.o friend.o init.o method.o search.o semantics.o tree.o xref.o \ - repo.o dump.o optimize.o @extra_cxx_objs@ + repo.o dump.o optimize.o mangle.o @extra_cxx_objs@ # Language-independent object files. OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o @@ -311,6 +311,7 @@ dump.o: dump.c $(CXX_TREE_H) optimize.o: optimize.c $(CXX_TREE_H) \ $(srcdir)/../rtl.h $(srcdir)/../integrate.h ../insn-config.h \ $(srcdir)/../input.h +mangle.o: mangle.c $(CXX_TREE_H) $(srcdir)/../toplev.h # # These exist for maintenance purposes. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index be0a84a340b..8d74b4426d5 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -83,6 +83,10 @@ typedef struct vcall_offset_data_s static int current_class_stack_size; static class_stack_node_t current_class_stack; +/* An array of all local classes present in this translation unit, in + declaration order. */ +varray_type local_classes; + static tree get_vfield_name PARAMS ((tree)); static void finish_struct_anon PARAMS ((tree)); static tree build_vbase_pointer PARAMS ((tree, tree)); @@ -630,8 +634,11 @@ static tree get_vtable_name (type) tree type; { - return build_overload_with_type (get_identifier (VTABLE_NAME_PREFIX), - 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 @@ -641,8 +648,11 @@ tree get_vtt_name (type) tree type; { - return build_overload_with_type (get_identifier (VTT_NAME_PREFIX), - 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. */ @@ -5296,6 +5306,8 @@ init_class_processing () current_class_stack = (class_stack_node_t) xmalloc (current_class_stack_size * sizeof (struct class_stack_node)); + VARRAY_TREE_INIT (local_classes, 8, "local_classes"); + ggc_add_tree_varray_root (&local_classes, 1); access_default_node = build_int_2 (0, 0); access_public_node = build_int_2 (ak_public, 0); @@ -6698,7 +6710,10 @@ build_ctor_vtbl_group (binfo, t) tree id; /* See if we've already create this construction vtable group. */ - id = get_ctor_vtbl_name (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 b9a9eb6e94b..fa03358cf4a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -588,6 +588,7 @@ enum cp_tree_index CPTI_PFN_OR_DELTA2_IDENTIFIER, CPTI_VPTR_IDENTIFIER, CPTI_PUSH_EXCEPTION_IDENTIFIER, + CPTI_STD_IDENTIFIER, CPTI_LANG_NAME_C, CPTI_LANG_NAME_CPLUSPLUS, @@ -707,6 +708,8 @@ extern tree cp_global_trees[CPTI_MAX]; /* The name of the function to call to push an exception onto the exception stack. */ #define cp_push_exception_identifier cp_global_trees[CPTI_PUSH_EXCEPTION_IDENTIFIER] +/* The name of the std namespace. */ +#define std_identifier cp_global_trees[CPTI_STD_IDENTIFIER] #define lang_name_c cp_global_trees[CPTI_LANG_NAME_C] #define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS] @@ -1968,8 +1971,7 @@ struct lang_decl #define DECL_COPY_CONSTRUCTOR_P(NODE) \ (DECL_CONSTRUCTOR_P (NODE) && copy_args_p (NODE)) -/* There ought to be a better way to find out whether or not something is - a destructor. */ +/* Nonzero if NODE is a destructor. */ #define DECL_DESTRUCTOR_P(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.destructor_attr) @@ -2118,6 +2120,13 @@ struct lang_decl && CP_TYPE_CONST_P (TREE_TYPE (TREE_VALUE \ (TYPE_ARG_TYPES (TREE_TYPE (NODE)))))) +/* Nonzero for FUNCTION_DECL means that this member function + has `this' as volatile X *const. */ +#define DECL_VOLATILE_MEMFUNC_P(NODE) \ + (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) \ + && CP_TYPE_VOLATILE_P (TREE_TYPE (TREE_VALUE \ + (TYPE_ARG_TYPES (TREE_TYPE (NODE)))))) + /* Nonzero for a DECL means that this member is a non-static member. */ #define DECL_NONSTATIC_MEMBER_P(NODE) \ ((TREE_CODE (NODE) == FUNCTION_DECL \ @@ -2209,7 +2218,7 @@ struct lang_decl #define DECL_FUNCTION_SCOPE_P(NODE) \ (DECL_CONTEXT (NODE) \ && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL) - + /* For a NAMESPACE_DECL: the list of using namespace directives The PURPOSE is the used namespace, the value is the namespace that is the common ancestor. */ @@ -2226,6 +2235,12 @@ struct lang_decl #define ORIGINAL_NAMESPACE(NODE) \ (DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE)) +/* Non-zero if NODE is the std namespace. */ +#define DECL_NAMESPACE_STD_P(NODE) \ + (TREE_CODE (NODE) == NAMESPACE_DECL \ + && CP_DECL_CONTEXT (NODE) == global_namespace \ + && DECL_NAME (NODE) == std_identifier) + /* In a non-local VAR_DECL with static storage duration, this is the initialization priority. If this value is zero, the NODE will be initialized at the DEFAULT_INIT_PRIORITY. */ @@ -3396,6 +3411,10 @@ extern int current_class_depth; /* Points to the name of that function. May not be the DECL_NAME of CURRENT_FUNCTION_DECL due to overloading */ extern tree original_function_name; + +/* An array of all local classes present in this translation unit, in + declaration order. */ +extern varray_type local_classes; /* Here's where we control how name mangling takes place. */ @@ -4355,7 +4374,7 @@ extern void print_candidates PARAMS ((tree)); extern int instantiate_pending_templates PARAMS ((void)); extern tree tsubst_default_argument PARAMS ((tree, tree, tree)); extern tree most_general_template PARAMS ((tree)); - +extern tree get_mostly_instantiated_function_type PARAMS ((tree, tree *, tree *)); extern int processing_template_parmlist; /* in repo.c */ @@ -4718,6 +4737,20 @@ extern void GNU_xref_member PARAMS ((tree, tree)); /* in dump.c */ extern void dump_node_to_file PARAMS ((tree, const char *)); +/* in mangle.c */ +extern void init_mangle PARAMS ((void)); +extern tree mangle_decl PARAMS ((tree)); +extern const char *mangle_type_string PARAMS ((tree)); +extern tree mangle_type PARAMS ((tree)); +extern tree mangle_typeinfo_for_type PARAMS ((tree)); +extern tree mangle_typeinfo_string_for_type PARAMS ((tree)); +extern tree mangle_vtbl_for_type PARAMS ((tree)); +extern tree mangle_vtt_for_type PARAMS ((tree)); +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)); + /* -- end of C++ */ #endif /* not _CP_TREE_H */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2c83225d7a8..5aff843f539 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2881,9 +2881,24 @@ pushtag (name, type, globalize) TYPE_CONTEXT (type) = DECL_CONTEXT (d); DECL_ASSEMBLER_NAME (d) = DECL_NAME (d); - if (!uses_template_parms (type)) - DECL_ASSEMBLER_NAME (d) - = get_identifier (build_overload_name (type, 1, 1)); + + /* If this is a local class, keep track of it. We need this + information for name-mangling, and so that it is possible to find + all function definitions in a translation unit in a convenient + way. (It's otherwise tricky to find a member function definition + it's only pointed to from within a local class.) */ + if (TYPE_CONTEXT (type) + && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL) + VARRAY_PUSH_TREE (local_classes, type); + + if (!uses_template_parms (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) { @@ -6229,6 +6244,7 @@ initialize_predefined_identifiers () { "_vptr", &vptr_identifier, 0 }, { "__cp_push_exception", &cp_push_exception_identifier, 0 }, { "__vtt_parm", &vtt_parm_identifier, 0 }, + { "std", &std_identifier, 0 }, { NULL, NULL, 0 } }; @@ -6577,7 +6593,8 @@ init_decl_processing () record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node); std_node = build_decl (NAMESPACE_DECL, - get_identifier (flag_honor_std ? "fake std":"std"), + flag_honor_std + ? get_identifier ("fake std") : std_identifier, void_type_node); pushdecl (std_node); @@ -7246,7 +7263,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */ DECL_IN_AGGR_P (decl) = 0; if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) - || CLASSTYPE_USE_TEMPLATE (context)) + || CLASSTYPE_TEMPLATE_INSTANTIATION (context)) { SET_DECL_TEMPLATE_SPECIALIZATION (decl); /* [temp.expl.spec] An explicit specialization of a static data @@ -9086,7 +9103,16 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) type = TREE_TYPE (type); decl = build_lang_decl (VAR_DECL, declarator, type); DECL_CONTEXT (decl) = basetype; - DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator); + /* DECL_ASSEMBLER_NAME is needed only for full-instantiated + templates. */ + if (!uses_template_parms (decl)) + { + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + else + DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, + declarator); + } } else { @@ -9110,8 +9136,14 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) set_decl_namespace (decl, context, 0); context = DECL_CONTEXT (decl); - if (declarator && context && current_lang_name != lang_name_c) - DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator); + if (declarator && context && current_lang_name != lang_name_c) + { + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl); + else + DECL_ASSEMBLER_NAME (decl) + = build_static_name (context, declarator); + } } if (in_namespace) @@ -11146,19 +11178,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)) = TYPE_IDENTIFIER (type); - /* 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; + if (flag_new_abi) + DECL_ASSEMBLER_NAME (decl) = mangle_type (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; + { + /* 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. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a942bd79596..95702d60d6f 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1116,7 +1116,12 @@ grokclassfn (ctype, function, flags, quals) if (flags == DTOR_FLAG) { DECL_DESTRUCTOR_P (function) = 1; - DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype); + + if (flag_new_abi) + set_mangled_name_for_decl (function); + else + DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype); + TYPE_HAS_DESTRUCTOR (ctype) = 1; } else @@ -1578,6 +1583,8 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags) my_friendly_assert (TREE_PUBLIC (decl), 0); + DECL_CONTEXT (decl) = current_class_type; + /* We cannot call pushdecl here, because that would fill in the decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do the right thing, namely, to put this decl out straight away. */ @@ -1585,8 +1592,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) - = build_static_name (current_class_type, DECL_NAME (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) { @@ -1611,7 +1621,6 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags) TREE_USED (decl) = 1; DECL_INITIAL (decl) = init; DECL_IN_AGGR_P (decl) = 1; - DECL_CONTEXT (decl) = current_class_type; cp_finish_decl (decl, init, asmspec_tree, flags); } @@ -1717,9 +1726,14 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) /* Now that we've updated the context, we need to remangle the name for this TYPE_DECL. */ DECL_ASSEMBLER_NAME (value) = DECL_NAME (value); - if (!uses_template_parms (value)) - DECL_ASSEMBLER_NAME (value) = - get_identifier (build_overload_name (TREE_TYPE (value), 1, 1)); + if (!uses_template_parms (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); @@ -1905,7 +1919,10 @@ grokoptypename (declspecs, declarator) tree declspecs, declarator; { tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); - return build_typename_overload (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, @@ -2856,16 +2873,25 @@ build_cleanup (decl) return temp; } +/* Returns the initialization guard variable for the non-local + variable DECL. */ + static tree -get_sentry (base) - tree base; +get_sentry (decl) + tree decl; { - tree sname = get_id_2 ("__sn", base); + tree sname; + tree sentry; + + 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 be globally unique */ - tree sentry = IDENTIFIER_GLOBAL_VALUE (sname); - + sentry = IDENTIFIER_GLOBAL_VALUE (sname); if (! sentry) { sentry = build_decl (VAR_DECL, sname, integer_type_node); @@ -3239,7 +3265,9 @@ start_static_initialization_or_destruction (decl, initp) cond = build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond); /* We need a sentry if this is an object with external linkage that - might be initialized in more than one place. */ + might be initialized in more than one place. (For example, a + static data member of a template, when the data member requires + construction.) */ if (TREE_PUBLIC (decl) && (DECL_COMMON (decl) || DECL_ONE_ONLY (decl) || DECL_WEAK (decl))) @@ -3247,7 +3275,7 @@ start_static_initialization_or_destruction (decl, initp) tree sentry; tree sentry_cond; - sentry = get_sentry (DECL_ASSEMBLER_NAME (decl)); + sentry = get_sentry (decl); /* We do initializations only if the SENTRY is zero, i.e., if we are the first to initialize the variable. We do destructions diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 7573a79404c..42a53903ee3 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -32,10 +32,6 @@ Boston, MA 02111-1307, USA. */ #include "except.h" #include "tm_p.h" -#if 0 -static tree extract_aggr_init PARAMS ((tree, tree)); -static tree extract_scalar_init PARAMS ((tree, tree)); -#endif static rtx cplus_expand_expr PARAMS ((tree, rtx, enum machine_mode, enum expand_modifier)); @@ -202,86 +198,11 @@ fixup_result_decl (decl, result) } } -#if 0 -/* Expand this initialization inline and see if it's simple enough that - it can be done at compile-time. */ - -static tree -extract_aggr_init (decl, init) - tree decl, init; -{ - return 0; -} - -static tree -extract_scalar_init (decl, init) - tree decl, init; -{ - rtx value, insns, insn; - extern struct obstack temporary_obstack; - tree t = NULL_TREE; - - start_sequence (); - value = expand_expr (init, NULL_RTX, VOIDmode, 0); - insns = get_insns (); - end_sequence (); - reg_scan (insns, max_reg_num (), 0); - jump_optimize (insns, 0, 0, 1); - - for (insn = insns; insn; insn = NEXT_INSN (insn)) - { - rtx r, to; - - if (GET_CODE (insn) == NOTE) - continue; - else if (GET_CODE (insn) != INSN) - return 0; - - r = PATTERN (insn); - if (GET_CODE (r) != SET) - return 0; - - to = XEXP (r, 0); - - if (! (to == value - || (GET_CODE (to) == SUBREG && XEXP (to, 0) == value))) - return 0; - - r = XEXP (r, 1); - - switch (GET_CODE (r)) - { - case CONST_INT: - t = build_int_2 (XEXP (r, 0), 0); - break; - default: - return 0; - } - } - - return t; -} -#endif - int extract_init (decl, init) tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED; { return 0; - -#if 0 - if (IS_AGGR_TYPE (TREE_TYPE (decl)) - || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) - init = extract_aggr_init (decl, init); - else - init = extract_scalar_init (decl, init); - - if (init == NULL_TREE) - return 0; - - DECL_INITIAL (decl) = init; - return 1; -#endif } void diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c new file mode 100644 index 00000000000..d4bd066cd09 --- /dev/null +++ b/gcc/cp/mangle.c @@ -0,0 +1,2128 @@ +/* Name mangling for the new standard C++ ABI. + Copyright (C) 2000 Free Software Foundation, Inc. + Written by Alex Samuel + + This file is part of GNU CC. + + GNU CC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU CC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file implements mangling of C++ names according to the IA64 + C++ ABI specification. A mangled name encodes a function or + variable's name, scope, type, and/or template arguments into a text + identifier. This identifier is used as the function's or + variable's linkage name, to preserve compatibility between C++'s + language features (templates, scoping, and overloading) and C + linkers. + + Additionally, g++ uses mangled names internally. To support this, + mangling of types is allowed, even though the mangled name of a + type should not appear by itself as an exported name. Ditto for + uninstantiated templates. + + The primary entry point for this module is mangle_decl, which + returns an identifier containing the mangled name for a decl. + Additional entry points are provided to build mangled names of + particular constructs when the appropriate decl for that construct + is not available. These are: + + mangle_typeinfo_for_type: typeinfo data + mangle_typeinfo_string_for_type: typeinfo type name + mangle_vtbl_for_type: virtual table data + mangle_vtt_for_type: VTT data + mangle_ctor_vtbl_for_type: `C-in-B' constructor virtual table data + mangle_thunk: thunk function or entry + +*/ + +#include "config.h" +#include "system.h" +#include "tree.h" +#include "cp-tree.h" +#include "obstack.h" +#include "toplev.h" +#include "varray.h" + +/* Debugging support. */ + +/* Define DEBUG_MANGLE to enable very verbose trace messages. */ +#ifndef DEBUG_MANGLE +#define DEBUG_MANGLE 0 +#endif + +/* Macros for tracing the write_* functions. */ +#if DEBUG_MANGLE +# define MANGLE_TRACE(FN, INPUT) \ + fprintf (stderr, " %-24s: %-24s\n", FN, INPUT) +# define MANGLE_TRACE_TREE(FN, NODE) \ + fprintf (stderr, " %-24s: %-24s (%p)\n", \ + FN, tree_code_name[TREE_CODE (NODE)], (void *) NODE) +#else +# define MANGLE_TRACE(FN, INPUT) +# define MANGLE_TRACE_TREE(FN, NODE) +#endif + +/* Non-zero if NODE is a template-id. */ +#define DECL_TEMPLATE_ID_P(NODE) \ + (DECL_LANG_SPECIFIC (NODE) != NULL \ + && DECL_USE_TEMPLATE (NODE) \ + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (NODE))) + +/* Non-zero if NODE is a class template-id. */ +#define CLASSTYPE_TEMPLATE_ID_P(NODE) \ + (TYPE_LANG_SPECIFIC (NODE) != NULL \ + && CLASSTYPE_USE_TEMPLATE (NODE) \ + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))) + +/* Things we only need one of. This module is not reentrant. */ +static struct globals +{ + /* The name in which we're building the mangled name. */ + struct obstack name_obstack; + + /* The current innermost template args. */ + tree template_args; + + /* An array of the current substitution candidates, in the order + we've seen them. */ + varray_type substitutions; +} G; + +/* Indices into subst_identifiers. These are identifiers used in + special substitution rules. */ +typedef enum +{ + SUBID_ALLOCATOR, + SUBID_BASIC_STRING, + SUBID_CHAR_TRAITS, + SUBID_BASIC_ISTREAM, + SUBID_BASIC_OSTREAM, + SUBID_BASIC_IOSTREAM, + SUBID_MAX +} +substitution_identifier_index_t; + +/* For quick substitution checks, look up these common identifiers + once only. */ +static tree subst_identifiers[SUBID_MAX]; + +/* Single-letter codes for builtin integer types, defined in + . These are indexed by integer_type_kind values. */ +static char +integer_type_codes[itk_none] = +{ + 'c', /* itk_char */ + 'a', /* itk_signed_char */ + 'h', /* itk_unsigned_char */ + 's', /* itk_short */ + 't', /* itk_unsigned_short */ + 'i', /* itk_int */ + 'j', /* itk_unsigned_int */ + 'l', /* itk_long */ + 'm', /* itk_unsigned_long */ + 'x', /* itk_long_long */ + 'y' /* itk_unsigned_long_long */ +}; + +/* Functions for handling substitutions. */ + +static inline tree canonicalize_for_substitution PARAMS ((tree)); +static void add_substitution PARAMS ((tree)); +static inline int is_std_substitution PARAMS ((tree, substitution_identifier_index_t)); +static inline int is_std_substitution_char PARAMS ((tree, substitution_identifier_index_t)); +static int find_substitution PARAMS ((tree)); + +/* Functions for emitting mangled representations of things. */ + +static void write_mangled_name PARAMS ((tree)); +static void write_encoding PARAMS ((tree)); +static void write_name PARAMS ((tree)); +static void write_unscoped_name PARAMS ((tree)); +static void write_unscoped_template_name PARAMS ((tree)); +static void write_nested_name PARAMS ((tree)); +static void write_prefix PARAMS ((tree)); +static void write_template_prefix PARAMS ((tree)); +static void write_component PARAMS ((tree)); +static void write_unqualified_name PARAMS ((tree)); +static void write_source_name PARAMS ((tree)); +static void write_number PARAMS ((int, int)); +static void write_integer_cst PARAMS ((tree)); +static void write_identifier PARAMS ((char *)); +static void write_special_name_constructor PARAMS ((tree)); +static void write_special_name_destructor PARAMS ((tree)); +static void write_type PARAMS ((tree)); +static int write_CV_qualifiers_for_type PARAMS ((tree)); +static void write_builtin_type PARAMS ((tree)); +static void write_function_type PARAMS ((tree, int)); +static void write_bare_function_type PARAMS ((tree, int)); +static void write_method_parms PARAMS ((tree, int)); +static void write_class_enum_type PARAMS ((tree)); +static void write_template_args PARAMS ((tree)); +static void write_expression PARAMS ((tree)); +static void write_template_arg_literal PARAMS ((tree)); +static void write_template_arg PARAMS ((tree)); +static void write_template_template_arg PARAMS ((tree)); +static void write_array_type PARAMS ((tree)); +static void write_pointer_to_member_type PARAMS ((tree)); +static void write_template_param PARAMS ((tree)); +static void write_template_template_param PARAMS ((tree)); +static void write_substitution PARAMS ((int)); +static int discriminator_for_local_entity PARAMS ((tree)); +static int discriminator_for_string_literal PARAMS ((tree, tree)); +static void write_discriminator PARAMS ((int)); +static void write_local_name PARAMS ((tree, tree)); +static void dump_substitution_candidates PARAMS ((void)); +static const char *mangle_decl_string PARAMS ((tree)); + +/* Control functions. */ + +static inline void start_mangling PARAMS ((void)); +static inline const char *finish_mangling PARAMS ((void)); +static tree mangle_special_for_type PARAMS ((tree, const char *)); + +/* Append a single character to the end of the mangled + representation. */ +#define write_char(CHAR) \ + obstack_1grow (&G.name_obstack, (CHAR)) + +/* Append a NUL-terminated string to the end of the mangled + representation. */ +#define write_string(STRING) \ + obstack_grow (&G.name_obstack, (STRING), strlen (STRING)) + +/* Return the position at which the next character will be appended to + the mangled representation. */ +#define mangled_position() \ + obstack_object_size (&G.name_obstack) + +/* Non-zero if NODE1__ and NODE2__ are both TREE_LIST nodes and have + the same purpose (context, which may be a type) and value (template + decl). See write_template_prefix for more information on what this + is used for. */ +#define NESTED_TEMPLATE_MATCH(NODE1, NODE2) \ + (TREE_CODE (NODE1) == TREE_LIST \ + && TREE_CODE (NODE2) == TREE_LIST \ + && ((TYPE_P (TREE_PURPOSE (NODE1)) \ + && same_type_p (TREE_PURPOSE (NODE1), TREE_PURPOSE (NODE2)))\ + || TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2)) \ + && TREE_VALUE (NODE1) == TREE_VALUE (NODE2)) + +/* Produce debugging output of current substitution candidates. */ + +static void +dump_substitution_candidates () +{ + unsigned i; + + fprintf (stderr, " ++ substitutions "); + for (i = 0; i < VARRAY_ACTIVE_SIZE (G.substitutions); ++i) + { + tree el = VARRAY_TREE (G.substitutions, i); + const char *name = "???"; + + if (i > 0) + fprintf (stderr, " "); + if (DECL_P (el)) + name = IDENTIFIER_POINTER (DECL_NAME (el)); + else if (TREE_CODE (el) == TREE_LIST) + name = IDENTIFIER_POINTER (DECL_NAME (TREE_VALUE (el))); + else if (TYPE_NAME (el)) + name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (el))); + fprintf (stderr, " S%d_ = ", i - 1); + if (TYPE_P (el) && + (CP_TYPE_RESTRICT_P (el) + || CP_TYPE_VOLATILE_P (el) + || CP_TYPE_CONST_P (el))) + fprintf (stderr, "CV-"); + fprintf (stderr, "%s (%s at %p)\n", + name, tree_code_name[TREE_CODE (el)], (void *) el); + } +} + +/* Both decls and types can be substitution candidates, but sometimes + they refer to the same thing. For instance, a TYPE_DECL and + RECORD_TYPE for the same class refer to the same thing, and should + be treated accordinginly in substitutions. This function returns a + canonicalized tree node representing NODE that is used when adding + and substitution candidates and finding matches. */ + +static inline tree +canonicalize_for_substitution (node) + tree node; +{ + /* For a TYPE_DECL, use the type instead. */ + if (TREE_CODE (node) == TYPE_DECL) + node = TREE_TYPE (node); + + return node; +} + +/* Add NODE as a substitution candidate. NODE must not already be on + the list of candidates. */ + +static void +add_substitution (node) + tree node; +{ + tree c; + + if (DEBUG_MANGLE) + fprintf (stderr, " ++ add_substitution (%s at %10p)\n", + tree_code_name[TREE_CODE (node)], (void *) node); + + /* Get the canonicalized substitution candidate for NODE. */ + c = canonicalize_for_substitution (node); + if (DEBUG_MANGLE && c != node) + fprintf (stderr, " ++ using candidate (%s at %10p)\n", + tree_code_name[TREE_CODE (node)], (void *) node); + node = c; + +#if ENABLE_CHECKING + /* Make sure NODE isn't already a candidate. */ + { + int i; + for (i = VARRAY_ACTIVE_SIZE (G.substitutions); --i >= 0; ) + { + tree candidate = VARRAY_TREE (G.substitutions, i); + if ((DECL_P (node) + && node == candidate) + || (TYPE_P (node) + && TYPE_P (candidate) + && same_type_p (node, candidate))) + my_friendly_abort (20000524); + } + } +#endif /* ENABLE_CHECKING */ + + /* Put the decl onto the varray of substitution candidates. */ + VARRAY_PUSH_TREE (G.substitutions, node); + + if (DEBUG_MANGLE) + dump_substitution_candidates (); +} + +/* Helper function for find_substitution. Returns non-zero if NODE, + which may be a decl or a CLASS_TYPE, is a template-id with template + name of substitution_index[INDEX] in the ::std namespace. */ + +static inline int +is_std_substitution (node, index) + tree node; + substitution_identifier_index_t index; +{ + tree type = NULL; + tree decl = NULL; + + if (DECL_P (node)) + { + type = TREE_TYPE (node); + decl = node; + } + else if (CLASS_TYPE_P (node)) + { + type = node; + decl = TYPE_NAME (node); + } + else + /* These are not the droids you're looking for. */ + return 0; + + return + DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl)) + && TYPE_LANG_SPECIFIC (type) + && CLASSTYPE_USE_TEMPLATE (type) + && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)) + == subst_identifiers[index]); +} + +/* Helper function for find_substitution. Returns non-zero if NODE, + which may be a decl or a CLASS_TYPE, is the template-id + ::std::identifier, where identifier is + substitution_index[INDEX]. */ + +static inline int +is_std_substitution_char (node, index) + tree node; + substitution_identifier_index_t index; +{ + tree args; + /* Check NODE's name is ::std::identifier. */ + if (!is_std_substitution (node, index)) + return 0; + /* Figure out its template args. */ + if (DECL_P (node)) + args = DECL_TI_ARGS (node); + else if (CLASS_TYPE_P (node)) + args = CLASSTYPE_TI_ARGS (node); + else + /* Oops, not a template. */ + return 0; + /* NODE's template arg list should be . */ + return + TREE_VEC_LENGTH (args) == 1 + && TREE_VEC_ELT (args, 0) == char_type_node; +} + +/* Check whether a substitution should be used to represent NODE in + the mangling. + + First, check standard special-case substitutions. + + ::= St + # ::std + + ::= Sa + # ::std::allocator + + ::= Sb + # ::std::basic_string + + ::= Ss + # ::std::basic_string, + ::std::allocator > + + ::= Si + # ::std::basic_istream > + + ::= So + # ::std::basic_ostream > + + ::= Sd + # ::std::basic_iostream > + + Then examine the stack of currently available substitution + candidates for entities appearing earlier in the same mangling + + If a substitution is found, write its mangled representation and + return non-zero. If none is found, just return zero. */ + +static int +find_substitution (node) + tree node; +{ + int i; + int size = VARRAY_ACTIVE_SIZE (G.substitutions); + tree decl; + tree type; + + if (DEBUG_MANGLE) + fprintf (stderr, " ++ find_substitution (%s at %p)\n", + tree_code_name[TREE_CODE (node)], (void *) node); + + /* Obtain the canonicalized substitution representation for NODE. + This is what we'll compare against. */ + node = canonicalize_for_substitution (node); + + /* Check for builtin substitutions. */ + + decl = TYPE_P (node) ? TYPE_NAME (node) : node; + type = TYPE_P (node) ? node : TREE_TYPE (node); + + /* Check for std::allocator. */ + if (decl && is_std_substitution (decl, SUBID_ALLOCATOR)) + { + write_string ("Sa"); + return 1; + } + + /* Check for std::basic_string. */ + if (decl && is_std_substitution (decl, SUBID_BASIC_STRING)) + { + if (type) + { + /* If this is a type (i.e. a fully-qualified template-id), + check for + std::basic_string , + std::allocator > . */ + if (CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED + && CLASSTYPE_USE_TEMPLATE (type)) + { + tree args = CLASSTYPE_TI_ARGS (type); + if (TREE_VEC_LENGTH (args) == 3 + && TREE_VEC_ELT (args, 0) == char_type_node + && is_std_substitution_char (TREE_VEC_ELT (args, 1), + SUBID_CHAR_TRAITS) + && is_std_substitution_char (TREE_VEC_ELT (args, 2), + SUBID_ALLOCATOR)) + { + write_string ("Ss"); + return 1; + } + } + } + else + /* Substitute for the template name only if this isn't a type. */ + { + write_string ("Sb"); + return 1; + } + } + + /* Check for basic_{i,o,io}stream. */ + if (type + && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED + && CLASS_TYPE_P (type) + && CLASSTYPE_USE_TEMPLATE (type) + && CLASSTYPE_TEMPLATE_INFO (type) != NULL) + { + /* First, check for the template + args > . */ + tree args = CLASSTYPE_TI_ARGS (type); + if (TREE_VEC_LENGTH (args) == 2 + && TREE_VEC_ELT (args, 0) == char_type_node + && is_std_substitution_char (TREE_VEC_ELT (args, 1), + SUBID_CHAR_TRAITS)) + { + /* Got them. Is this basic_istream? */ + tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)); + if (name == subst_identifiers[SUBID_BASIC_ISTREAM]) + { + write_string ("Si"); + return 1; + } + /* Or basic_ostream? */ + else if (name == subst_identifiers[SUBID_BASIC_OSTREAM]) + { + write_string ("So"); + return 1; + } + /* Or basic_iostream? */ + else if (name == subst_identifiers[SUBID_BASIC_IOSTREAM]) + { + write_string ("Sd"); + return 1; + } + } + } + + /* Check for namespace std. */ + if (decl&& DECL_NAMESPACE_STD_P (decl)) + { + write_string ("St"); + return 1; + } + + /* Now check the list of available substitutions for this mangling + operation. */ + + for (i = 0; i < size; ++i) + { + tree candidate = VARRAY_TREE (G.substitutions, i); + /* NODE is a matched to a candidate if it's the same decl node or + if it's the same type. */ + if (decl == candidate + || (TYPE_P (candidate) && type && TYPE_P (type) + && same_type_p (type, candidate)) + || NESTED_TEMPLATE_MATCH (node, candidate)) + { + write_substitution (i); + return 1; + } + } + + /* No substitution found. */ + return 0; +} + + +/* ::= _Z */ + +static inline void +write_mangled_name (decl) + tree decl; +{ + MANGLE_TRACE_TREE ("mangled-name", decl); + + if (DECL_LANG_SPECIFIC (decl) && DECL_EXTERN_C_FUNCTION_P (decl)) + /* The standard notes: + "The of an extern "C" function is treated like + global-scope data, i.e. as its without a type." */ + write_source_name (DECL_NAME (decl)); + else + /* C++ name; needs to be mangled. */ + { + write_string ("_Z"); + write_encoding (decl); + } +} + +/* ::= + ::= + ::= */ + +static void +write_encoding (decl) + tree decl; +{ + MANGLE_TRACE_TREE ("encoding", decl); + + if (find_substitution (decl)) + return; + + if (DECL_LANG_SPECIFIC (decl) && DECL_EXTERN_C_FUNCTION_P (decl)) + { + write_source_name (DECL_NAME (decl)); + return; + } + + write_name (decl); + if (TREE_CODE (decl) == FUNCTION_DECL) + { + tree fn_type; + + if (DECL_TEMPLATE_ID_P (decl)) + fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL); + else + fn_type = TREE_TYPE (decl); + + write_bare_function_type (fn_type, DECL_TEMPLATE_ID_P (decl)); + } + + add_substitution (decl); +} + +/* ::= + ::= + ::= + ::= */ + +static void +write_name (decl) + tree decl; +{ + tree context = CP_DECL_CONTEXT (decl); + + MANGLE_TRACE_TREE ("name", decl); + + /* Decls in :: or ::std scope are treated specially. */ + if (context == global_namespace || DECL_NAMESPACE_STD_P (context)) + { + if (decl && DECL_TEMPLATE_ID_P (decl)) + { + /* Templated decls get an . */ + write_unscoped_template_name (DECL_TI_TEMPLATE (decl)); + write_template_args (DECL_TI_ARGS (decl)); + } + else if (TREE_CODE (decl) == TYPE_DECL + && CLASSTYPE_TEMPLATE_ID_P (TREE_TYPE (decl))) + { + tree type; + + /* Templated decls get an . */ + type = TREE_TYPE (decl); + write_unscoped_template_name (TYPE_TI_TEMPLATE (type)); + write_template_args (TYPE_TI_ARGS (type)); + } + else + /* Everything else gets an . */ + write_unscoped_name (decl); + } + /* Handle local names. */ + else if (TREE_CODE (context) == FUNCTION_DECL) + write_local_name (context, decl); + /* Other decls get a to encode their scope. */ + else + write_nested_name (decl); +} + +/* ::= + ::= St # ::std:: */ + +static void +write_unscoped_name (decl) + tree decl; +{ + tree context = CP_DECL_CONTEXT (decl); + + MANGLE_TRACE_TREE ("unscoped-name", decl); + + /* Is DECL in ::std? */ + if (DECL_NAMESPACE_STD_P (context)) + { + write_string ("St"); + write_unqualified_name (decl); + } + /* If not, it should be in the global namespace. */ + else if (context == global_namespace || context == NULL) + write_unqualified_name (decl); + else + my_friendly_abort (20000521); +} + +/* ::= + ::= */ + +static void +write_unscoped_template_name (decl) + tree decl; +{ + MANGLE_TRACE_TREE ("unscoped-template-name", decl); + + if (find_substitution (decl)) + return; + write_unscoped_name (decl); + add_substitution (decl); +} + +/* Write the nested name, including CV-qualifiers, of DECL. + + ::= N [] E + ::= N [] E + + ::= [r] [V] [K] */ + +static void +write_nested_name (decl) + tree decl; +{ + MANGLE_TRACE_TREE ("nested-name", decl); + + write_char ('N'); + + /* Write CV-qualifiers, if this is a member function. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + { + if (DECL_VOLATILE_MEMFUNC_P (decl)) + write_char ('V'); + if (DECL_CONST_MEMFUNC_P (decl)) + write_char ('K'); + } + + if (DECL_TEMPLATE_ID_P (decl)) + { + write_template_prefix (decl); + write_template_args (DECL_TI_ARGS (decl)); + } + else if (CLASSTYPE_TEMPLATE_ID_P (TREE_TYPE (decl))) + { + write_template_prefix (decl); + write_template_args (CLASSTYPE_TI_ARGS (TREE_TYPE (decl))); + } + else + { + write_prefix (DECL_CONTEXT (decl)); + write_component (decl); + } + write_char ('E'); +} + +/* ::= + ::= + ::= # empty + ::= */ + +static void +write_prefix (node) + tree node; +{ + tree decl; + tree type; + tree context; + + if (node == NULL + || node == global_namespace) + return; + + MANGLE_TRACE_TREE ("prefix", node); + + decl = DECL_P (node) ? node : TYPE_NAME (node); + type = DECL_P (node) ? TREE_TYPE (node) : node; + context = CP_DECL_CONTEXT (decl); + + if (find_substitution (node)) + return; + + /* Check if this is a template-id. For a template member, the + template info will be hanging off the decl. */ + if (DECL_TEMPLATE_ID_P (decl)) + { + write_template_prefix (decl); + write_template_args (DECL_TI_ARGS (decl)); + } + /* For a template class, the template info will be hanging off the + type. */ + else if (type && CLASSTYPE_TEMPLATE_ID_P (type)) + { + write_template_prefix (type); + write_template_args (CLASSTYPE_TI_ARGS (type)); + } + else + /* Not templated. */ + { + write_prefix (context); + write_component (decl); + } + + add_substitution (node); +} + +/* ::=