diff options
Diffstat (limited to 'contrib/gcc/cp/mangle.c')
-rw-r--r-- | contrib/gcc/cp/mangle.c | 717 |
1 files changed, 370 insertions, 347 deletions
diff --git a/contrib/gcc/cp/mangle.c b/contrib/gcc/cp/mangle.c index 7180648..760d8b3 100644 --- a/contrib/gcc/cp/mangle.c +++ b/contrib/gcc/cp/mangle.c @@ -1,21 +1,21 @@ /* Name mangling for the 3.0 C++ ABI. - Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by Alex Samuel <sameul@codesourcery.com> - This file is part of GNU CC. + This file is part of GCC. - GNU CC is free software; you can redistribute it and/or modify it + GCC 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 + GCC 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 + along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -49,6 +49,8 @@ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "tm_p.h" #include "cp-tree.h" @@ -56,7 +58,7 @@ #include "obstack.h" #include "toplev.h" #include "varray.h" -#include "ggc.h" +#include "flags.h" /* Debugging support. */ @@ -122,7 +124,7 @@ substitution_identifier_index_t; /* For quick substitution checks, look up these common identifiers once only. */ -static tree subst_identifiers[SUBID_MAX]; +static GTY(()) tree subst_identifiers[SUBID_MAX]; /* Single-letter codes for builtin integer types, defined in <builtin-type>. These are indexed by integer_type_kind values. */ @@ -142,70 +144,74 @@ integer_type_codes[itk_none] = 'y' /* itk_unsigned_long_long */ }; -static int decl_is_template_id PARAMS ((tree, tree*)); +static int decl_is_template_id (const tree, tree* const); /* 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)); +static inline tree canonicalize_for_substitution (tree); +static void add_substitution (tree); +static inline int is_std_substitution (const tree, + const substitution_identifier_index_t); +static inline int is_std_substitution_char (const tree, + const substitution_identifier_index_t); +static int find_substitution (tree); +static void mangle_call_offset (const tree, const 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, int)); -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_unqualified_name PARAMS ((tree)); -static void write_conversion_operator_name (tree); -static void write_source_name PARAMS ((tree)); -static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned)); -static void write_number PARAMS ((unsigned HOST_WIDE_INT, int, - unsigned int)); -static void write_integer_cst PARAMS ((tree)); -static void write_real_cst PARAMS ((tree)); -static void write_identifier PARAMS ((const 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)); -static void write_bare_function_type PARAMS ((tree, int, tree)); -static void write_method_parms PARAMS ((tree, int, tree)); -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, tree)); -static void dump_substitution_candidates PARAMS ((void)); -static const char *mangle_decl_string PARAMS ((tree)); +static void write_mangled_name (const tree, bool); +static void write_encoding (const tree); +static void write_name (tree, const int); +static void write_unscoped_name (const tree); +static void write_unscoped_template_name (const tree); +static void write_nested_name (const tree); +static void write_prefix (const tree); +static void write_template_prefix (const tree); +static void write_unqualified_name (const tree); +static void write_conversion_operator_name (const tree); +static void write_source_name (tree); +static int hwint_to_ascii (unsigned HOST_WIDE_INT, const unsigned int, char *, + const unsigned int); +static void write_number (unsigned HOST_WIDE_INT, const int, + const unsigned int); +static void write_integer_cst (const tree); +static void write_real_cst (const tree); +static void write_identifier (const char *); +static void write_special_name_constructor (const tree); +static void write_special_name_destructor (const tree); +static void write_type (tree); +static int write_CV_qualifiers_for_type (const tree); +static void write_builtin_type (tree); +static void write_function_type (const tree); +static void write_bare_function_type (const tree, const int, const tree); +static void write_method_parms (tree, const int, const tree); +static void write_class_enum_type (const tree); +static void write_template_args (tree); +static void write_expression (tree); +static void write_template_arg_literal (const tree); +static void write_template_arg (tree); +static void write_template_template_arg (const tree); +static void write_array_type (const tree); +static void write_pointer_to_member_type (const tree); +static void write_template_param (const tree); +static void write_template_template_param (const tree); +static void write_substitution (const int); +static int discriminator_for_local_entity (tree); +static int discriminator_for_string_literal (tree, tree); +static void write_discriminator (const int); +static void write_local_name (const tree, const tree, const tree); +static void dump_substitution_candidates (void); +static const char *mangle_decl_string (const tree); /* Control functions. */ -static inline void start_mangling (tree); -static inline const char *finish_mangling (bool); -static tree mangle_special_for_type PARAMS ((tree, const char *)); +static inline void start_mangling (const tree); +static inline const char *finish_mangling (const bool); +static tree mangle_special_for_type (const tree, const char *); /* Foreign language functions. */ -static void write_java_integer_type_codes PARAMS ((tree)); +static void write_java_integer_type_codes (const tree); /* Append a single character to the end of the mangled representation. */ @@ -242,15 +248,13 @@ static void write_java_integer_type_codes PARAMS ((tree)); Otherwise return zero. */ static int -decl_is_template_id (decl, template_info) - tree decl; - tree* template_info; +decl_is_template_id (const tree decl, tree* const template_info) { if (TREE_CODE (decl) == TYPE_DECL) { /* TYPE_DECLs are handled specially. Look at its type to decide if this is a template instantiation. */ - tree type = TREE_TYPE (decl); + const tree type = TREE_TYPE (decl); if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type)) { @@ -284,7 +288,7 @@ decl_is_template_id (decl, template_info) /* Produce debugging output of current substitution candidates. */ static void -dump_substitution_candidates () +dump_substitution_candidates (void) { unsigned i; @@ -316,13 +320,12 @@ dump_substitution_candidates () /* 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 + be treated accordingly 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; +canonicalize_for_substitution (tree node) { /* For a TYPE_DECL, use the type instead. */ if (TREE_CODE (node) == TYPE_DECL) @@ -337,8 +340,7 @@ canonicalize_for_substitution (node) the list of candidates. */ static void -add_substitution (node) - tree node; +add_substitution (tree node) { tree c; @@ -359,7 +361,7 @@ add_substitution (node) int i; for (i = VARRAY_ACTIVE_SIZE (G.substitutions); --i >= 0; ) { - tree candidate = VARRAY_TREE (G.substitutions, i); + const tree candidate = VARRAY_TREE (G.substitutions, i); if ((DECL_P (node) && node == candidate) || (TYPE_P (node) @@ -382,9 +384,8 @@ add_substitution (node) name of substitution_index[INDEX] in the ::std namespace. */ static inline int -is_std_substitution (node, index) - tree node; - substitution_identifier_index_t index; +is_std_substitution (const tree node, + const substitution_identifier_index_t index) { tree type = NULL; tree decl = NULL; @@ -416,9 +417,8 @@ is_std_substitution (node, index) substitution_index[INDEX]. */ static inline int -is_std_substitution_char (node, index) - tree node; - substitution_identifier_index_t index; +is_std_substitution_char (const tree node, + const substitution_identifier_index_t index) { tree args; /* Check NODE's name is ::std::identifier. */ @@ -473,11 +473,10 @@ is_std_substitution_char (node, index) return nonzero. If none is found, just return zero. */ static int -find_substitution (node) - tree node; +find_substitution (tree node) { int i; - int size = VARRAY_ACTIVE_SIZE (G.substitutions); + const int size = VARRAY_ACTIVE_SIZE (G.substitutions); tree decl; tree type; @@ -548,6 +547,7 @@ find_substitution (node) args <char, std::char_traits<char> > . */ tree args = CLASSTYPE_TI_ARGS (type); if (TREE_VEC_LENGTH (args) == 2 + && TYPE_P (TREE_VEC_ELT (args, 0)) && same_type_p (TREE_VEC_ELT (args, 0), char_type_node) && is_std_substitution_char (TREE_VEC_ELT (args, 1), SUBID_CHAR_TRAITS)) @@ -603,28 +603,66 @@ find_substitution (node) } -/* <mangled-name> ::= _Z <encoding> */ +/* TOP_LEVEL is true, if this is being called at outermost level of + mangling. It should be false when mangling a decl appearing in an + expression within some other mangling. + + <mangled-name> ::= _Z <encoding> */ -static inline void -write_mangled_name (decl) - tree decl; +static void +write_mangled_name (const tree decl, bool top_level) { MANGLE_TRACE_TREE ("mangled-name", decl); - if (DECL_LANG_SPECIFIC (decl) - && DECL_EXTERN_C_FUNCTION_P (decl) - && ! DECL_OVERLOADED_OPERATOR_P (decl)) - /* The standard notes: - "The <encoding> of an extern "C" function is treated like - global-scope data, i.e. as its <source-name> without a type." - We cannot write overloaded operators that way though, - because it contains characters invalid in assembler. */ - write_source_name (DECL_NAME (decl)); + if (/* The names of `extern "C"' functions are not mangled. */ + DECL_EXTERN_C_FUNCTION_P (decl) + /* But overloaded operator names *are* mangled. */ + && !DECL_OVERLOADED_OPERATOR_P (decl)) + { + unmangled_name:; + + if (top_level) + write_string (IDENTIFIER_POINTER (DECL_NAME (decl))); + else + { + /* The standard notes: "The <encoding> of an extern "C" + function is treated like global-scope data, i.e. as its + <source-name> without a type." We cannot write + overloaded operators that way though, because it contains + characters invalid in assembler. */ + if (abi_version_at_least (2)) + write_string ("_Z"); + else + G.need_abi_warning = true; + write_source_name (DECL_NAME (decl)); + } + } + else if (TREE_CODE (decl) == VAR_DECL + /* The names of global variables aren't mangled. */ + && (CP_DECL_CONTEXT (decl) == global_namespace + /* And neither are `extern "C"' variables. */ + || DECL_EXTERN_C_P (decl))) + { + if (top_level || abi_version_at_least (2)) + goto unmangled_name; + else + { + G.need_abi_warning = true; + goto mangled_name; + } + } else - /* C++ name; needs to be mangled. */ { + mangled_name:; write_string ("_Z"); write_encoding (decl); + if (DECL_LANG_SPECIFIC (decl) + && (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl) + || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl))) + /* We need a distinct mangled name for these entities, but + we should never actually output it. So, we append some + characters the assembler won't like. */ + write_string (" *INTERNAL* "); } } @@ -632,8 +670,7 @@ write_mangled_name (decl) ::= <data name> */ static void -write_encoding (decl) - tree decl; +write_encoding (const tree decl) { MANGLE_TRACE_TREE ("encoding", decl); @@ -652,18 +689,25 @@ write_encoding (decl) if (TREE_CODE (decl) == FUNCTION_DECL) { tree fn_type; + tree d; if (decl_is_template_id (decl, NULL)) - fn_type = get_mostly_instantiated_function_type (decl); + { + fn_type = get_mostly_instantiated_function_type (decl); + d = NULL_TREE; + } else - fn_type = TREE_TYPE (decl); + { + fn_type = TREE_TYPE (decl); + d = decl; + } write_bare_function_type (fn_type, (!DECL_CONSTRUCTOR_P (decl) && !DECL_DESTRUCTOR_P (decl) && !DECL_CONV_FN_P (decl) && decl_is_template_id (decl, NULL)), - decl); + d); } } @@ -679,9 +723,7 @@ write_encoding (decl) production, to avoid an infinite recursion. */ static void -write_name (decl, ignore_local_scope) - tree decl; - int ignore_local_scope; +write_name (tree decl, const int ignore_local_scope) { tree context; @@ -763,8 +805,7 @@ write_name (decl, ignore_local_scope) ::= St <unqualified-name> # ::std:: */ static void -write_unscoped_name (decl) - tree decl; +write_unscoped_name (const tree decl) { tree context = CP_DECL_CONTEXT (decl); @@ -790,8 +831,7 @@ write_unscoped_name (decl) ::= <substitution> */ static void -write_unscoped_template_name (decl) - tree decl; +write_unscoped_template_name (const tree decl) { MANGLE_TRACE_TREE ("unscoped-template-name", decl); @@ -809,8 +849,7 @@ write_unscoped_template_name (decl) <CV-qualifiers> ::= [r] [V] [K] */ static void -write_nested_name (decl) - tree decl; +write_nested_name (const tree decl) { tree template_info; @@ -851,8 +890,7 @@ write_nested_name (decl) ::= <substitution> */ static void -write_prefix (node) - tree node; +write_prefix (const tree node) { tree decl; /* Non-NULL if NODE represents a template-id. */ @@ -917,8 +955,7 @@ write_prefix (node) ::= <substitution> */ static void -write_template_prefix (node) - tree node; +write_template_prefix (const tree node) { tree decl = DECL_P (node) ? node : TYPE_NAME (node); tree type = DECL_P (node) ? TREE_TYPE (node) : node; @@ -993,8 +1030,7 @@ write_template_prefix (node) ::= <source-name> */ static void -write_unqualified_name (decl) - tree decl; +write_unqualified_name (const tree decl) { MANGLE_TRACE_TREE ("unqualified-name", decl); @@ -1002,6 +1038,8 @@ write_unqualified_name (decl) write_special_name_constructor (decl); else if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_DESTRUCTOR_P (decl)) write_special_name_destructor (decl); + else if (DECL_NAME (decl) == NULL_TREE) + write_source_name (DECL_ASSEMBLER_NAME (decl)); else if (DECL_CONV_FN_P (decl)) { /* Conversion operator. Handle it right here. @@ -1033,19 +1071,18 @@ write_unqualified_name (decl) /* Write the unqualified-name for a conversion operator to TYPE. */ static void -write_conversion_operator_name (tree type) +write_conversion_operator_name (const tree type) { write_string ("cv"); write_type (type); } -/* Non-termial <source-name>. IDENTIFIER is an IDENTIFIER_NODE. +/* Non-terminal <source-name>. IDENTIFIER is an IDENTIFIER_NODE. <source-name> ::= </length/ number> <identifier> */ static void -write_source_name (identifier) - tree identifier; +write_source_name (tree identifier) { MANGLE_TRACE_TREE ("source-name", identifier); @@ -1065,11 +1102,8 @@ write_source_name (identifier) BUFFER points). */ static int -hwint_to_ascii (number, base, buffer, min_digits) - unsigned HOST_WIDE_INT number; - unsigned int base; - char *buffer; - unsigned min_digits; +hwint_to_ascii (unsigned HOST_WIDE_INT number, const unsigned int base, + char *buffer, const unsigned int min_digits) { static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; unsigned digits = 0; @@ -1095,10 +1129,8 @@ hwint_to_ascii (number, base, buffer, min_digits) <number> ::= [n] </decimal integer/> */ static void -write_number (number, unsigned_p, base) - unsigned HOST_WIDE_INT number; - int unsigned_p; - unsigned int base; +write_number (unsigned HOST_WIDE_INT number, const int unsigned_p, + const unsigned int base) { char buffer[sizeof (HOST_WIDE_INT) * 8]; unsigned count = 0; @@ -1117,8 +1149,7 @@ write_number (number, unsigned_p, base) bigger than that, which we must deal with. */ static inline void -write_integer_cst (cst) - tree cst; +write_integer_cst (const tree cst) { int sign = tree_int_cst_sgn (cst); @@ -1161,7 +1192,7 @@ write_integer_cst (cst) tree d = fold (build (FLOOR_DIV_EXPR, type, n, base)); tree tmp = fold (build (MULT_EXPR, type, d, base)); unsigned c; - + done = integer_zerop (d); tmp = fold (build (MINUS_EXPR, type, n, tmp)); c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr, @@ -1208,8 +1239,7 @@ write_integer_cst (cst) Caller is responsible for the Lx and the E. */ static void -write_real_cst (value) - tree value; +write_real_cst (const tree value) { if (abi_version_at_least (2)) { @@ -1258,8 +1288,7 @@ write_real_cst (value) <identifier> ::= </unqualified source code identifier> */ static void -write_identifier (identifier) - const char *identifier; +write_identifier (const char *identifier) { MANGLE_TRACE ("identifier", identifier); write_string (identifier); @@ -1279,8 +1308,7 @@ write_identifier (identifier) append *INTERNAL* to that, to make sure we never emit it. */ static void -write_special_name_constructor (ctor) - tree ctor; +write_special_name_constructor (const tree ctor) { if (DECL_COMPLETE_CONSTRUCTOR_P (ctor) /* Even though we don't ever emit a definition of the @@ -1306,8 +1334,7 @@ write_special_name_constructor (ctor) append *INTERNAL* to that, to make sure we never emit it. */ static void -write_special_name_destructor (dtor) - tree dtor; +write_special_name_destructor (const tree dtor) { if (DECL_DELETING_DESTRUCTOR_P (dtor)) write_string ("D0"); @@ -1328,14 +1355,12 @@ write_special_name_destructor (dtor) entities with the same name in the same FUNCTION. */ static int -discriminator_for_local_entity (entity) - tree entity; +discriminator_for_local_entity (tree entity) { tree *type; - int discriminator; /* Assume this is the only local entity with this name. */ - discriminator = 0; + int discriminator = 0; if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity)) discriminator = DECL_DISCRIMINATOR (entity); @@ -1353,13 +1378,12 @@ discriminator_for_local_entity (entity) } /* Return the discriminator for STRING, a string literal used inside - FUNCTION. The disciminator is the lexical ordinal of STRING among + FUNCTION. The discriminator is the lexical ordinal of STRING among string literals used in FUNCTION. */ static int -discriminator_for_string_literal (function, string) - tree function ATTRIBUTE_UNUSED; - tree string ATTRIBUTE_UNUSED; +discriminator_for_string_literal (tree function ATTRIBUTE_UNUSED, + tree string ATTRIBUTE_UNUSED) { /* For now, we don't discriminate amongst string literals. */ return 0; @@ -1372,8 +1396,7 @@ discriminator_for_string_literal (function, string) n - 2, if this is the nth occurrence, in lexical order. */ static void -write_discriminator (discriminator) - int discriminator; +write_discriminator (const int discriminator) { /* If discriminator is zero, don't write anything. Otherwise... */ if (discriminator > 0) @@ -1393,10 +1416,8 @@ write_discriminator (discriminator) := Z <function encoding> E s [<discriminator>] */ static void -write_local_name (function, local_entity, entity) - tree function; - tree local_entity; - tree entity; +write_local_name (const tree function, const tree local_entity, + const tree entity) { MANGLE_TRACE_TREE ("local-name", entity); @@ -1438,8 +1459,7 @@ write_local_name (function, local_entity, entity) TYPE is a type node. */ static void -write_type (type) - tree type; +write_type (tree type) { /* This gets set to nonzero if TYPE turns out to be a (possibly CV-qualified) builtin type. */ @@ -1456,7 +1476,7 @@ write_type (type) if (write_CV_qualifiers_for_type (type) > 0) /* If TYPE was CV-qualified, we just wrote the qualifiers; now mangle the unqualified type. The recursive call is needed here - since both the qualified and uqualified types are substitution + since both the qualified and unqualified types are substitution candidates. */ write_type (TYPE_MAIN_VARIANT (type)); else if (TREE_CODE (type) == ARRAY_TYPE) @@ -1469,7 +1489,9 @@ write_type (type) /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); - switch (TREE_CODE (type)) + if (TYPE_PTRMEM_P (type)) + write_pointer_to_member_type (type); + else switch (TREE_CODE (type)) { case VOID_TYPE: case BOOLEAN_TYPE: @@ -1511,15 +1533,8 @@ write_type (type) break; case POINTER_TYPE: - /* A pointer-to-member variable is represented by a POINTER_TYPE - to an OFFSET_TYPE, so check for this first. */ - if (TYPE_PTRMEM_P (type)) - write_pointer_to_member_type (type); - else - { - write_char ('P'); - write_type (TREE_TYPE (type)); - } + write_char ('P'); + write_type (TREE_TYPE (type)); break; case REFERENCE_TYPE: @@ -1542,10 +1557,6 @@ write_type (type) (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type))); break; - case OFFSET_TYPE: - write_pointer_to_member_type (build_pointer_type (type)); - break; - case VECTOR_TYPE: write_string ("U8__vector"); write_type (TREE_TYPE (type)); @@ -1567,8 +1578,7 @@ write_type (type) <CV-qualifiers> ::= [r] [V] [K] */ static int -write_CV_qualifiers_for_type (type) - tree type; +write_CV_qualifiers_for_type (const tree type) { int num_qualifiers = 0; @@ -1626,8 +1636,7 @@ write_CV_qualifiers_for_type (type) ::= u <source-name> # vendor extended type */ static void -write_builtin_type (type) - tree type; +write_builtin_type (tree type) { switch (TREE_CODE (type)) { @@ -1710,8 +1719,7 @@ write_builtin_type (type) <function-type> ::= F [Y] <bare-function-type> E */ static void -write_function_type (type) - tree type; +write_function_type (const tree type) { MANGLE_TRACE_TREE ("function-type", type); @@ -1752,10 +1760,8 @@ write_function_type (type) <bare-function-type> ::= </signature/ type>+ */ static void -write_bare_function_type (type, include_return_type_p, decl) - tree type; - int include_return_type_p; - tree decl; +write_bare_function_type (const tree type, const int include_return_type_p, + const tree decl) { MANGLE_TRACE_TREE ("bare-function-type", type); @@ -1776,10 +1782,7 @@ write_bare_function_type (type, include_return_type_p, decl) parameters are being emitted. */ static void -write_method_parms (parm_types, method_p, decl) - tree decl; - tree parm_types; - int method_p; +write_method_parms (tree parm_types, const int method_p, const tree decl) { tree first_parm_type; tree parm_decl = decl ? DECL_ARGUMENTS (decl) : NULL_TREE; @@ -1837,8 +1840,7 @@ write_method_parms (parm_types, method_p, decl) /* <class-enum-type> ::= <name> */ static void -write_class_enum_type (type) - tree type; +write_class_enum_type (const tree type) { write_name (TYPE_NAME (type), /*ignore_local_scope=*/0); } @@ -1849,40 +1851,27 @@ write_class_enum_type (type) <template-args> ::= I <template-arg>+ E */ static void -write_template_args (args) - tree args; +write_template_args (tree args) { + int i; + int length = TREE_VEC_LENGTH (args); + MANGLE_TRACE_TREE ("template-args", args); write_char ('I'); - if (TREE_CODE (args) == TREE_VEC) - { - int i; - int length = TREE_VEC_LENGTH (args); - my_friendly_assert (length > 0, 20000422); + my_friendly_assert (length > 0, 20000422); - if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) - { - /* We have nested template args. We want the innermost template - argument list. */ - args = TREE_VEC_ELT (args, length - 1); - length = TREE_VEC_LENGTH (args); - } - for (i = 0; i < length; ++i) - write_template_arg (TREE_VEC_ELT (args, i)); - } - else + if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) { - my_friendly_assert (TREE_CODE (args) == TREE_LIST, 20021014); - - while (args) - { - write_template_arg (TREE_VALUE (args)); - args = TREE_CHAIN (args); - } + /* We have nested template args. We want the innermost template + argument list. */ + args = TREE_VEC_ELT (args, length - 1); + length = TREE_VEC_LENGTH (args); } - + for (i = 0; i < length; ++i) + write_template_arg (TREE_VEC_ELT (args, i)); + write_char ('E'); } @@ -1897,8 +1886,7 @@ write_template_args (args) ::= sr <type> <unqualified-name> <template-args> */ static void -write_expression (expr) - tree expr; +write_expression (tree expr) { enum tree_code code; @@ -1942,7 +1930,7 @@ write_expression (expr) if (code == CONST_DECL) G.need_abi_warning = 1; write_char ('L'); - write_mangled_name (expr); + write_mangled_name (expr, false); write_char ('E'); } else if (TREE_CODE (expr) == SIZEOF_EXPR @@ -1975,8 +1963,6 @@ write_expression (expr) { template_args = TREE_OPERAND (member, 1); member = TREE_OPERAND (member, 0); - if (TREE_CODE (member) == LOOKUP_EXPR) - member = TREE_OPERAND (member, 0); } else template_args = NULL_TREE; @@ -2068,6 +2054,19 @@ write_expression (expr) write_type (TREE_OPERAND (expr, 0)); if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE) write_source_name (TREE_OPERAND (expr, 1)); + else if (TREE_CODE (TREE_OPERAND (expr, 1)) == TEMPLATE_ID_EXPR) + { + tree template_id; + tree name; + + template_id = TREE_OPERAND (expr, 1); + name = TREE_OPERAND (template_id, 0); + /* FIXME: What about operators? */ + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, + 20030707); + write_source_name (TREE_OPERAND (template_id, 0)); + write_template_args (TREE_OPERAND (template_id, 1)); + } else { /* G++ 3.2 incorrectly put out both the "sr" code and @@ -2079,7 +2078,21 @@ write_expression (expr) default: for (i = 0; i < TREE_CODE_LENGTH (code); ++i) - write_expression (TREE_OPERAND (expr, i)); + { + tree operand = TREE_OPERAND (expr, i); + /* As a GNU expression, the middle operand of a + conditional may be omitted. Since expression + manglings are supposed to represent the input token + stream, there's no good way to mangle such an + expression without extending the C++ ABI. */ + if (code == COND_EXPR && i == 1 && !operand) + { + error ("omitted middle operand to `?:' operand " + "cannot be mangled"); + continue; + } + write_expression (operand); + } } } } @@ -2092,8 +2105,7 @@ write_expression (expr) encoded as 0, true as 1." */ static void -write_template_arg_literal (value) - tree value; +write_template_arg_literal (const tree value) { tree type = TREE_TYPE (value); write_char ('L'); @@ -2105,9 +2117,9 @@ write_template_arg_literal (value) { if (same_type_p (type, boolean_type_node)) { - if (value == boolean_false_node || integer_zerop (value)) + if (integer_zerop (value)) write_unsigned_number (0); - else if (value == boolean_true_node) + else if (integer_onep (value)) write_unsigned_number (1); else abort (); @@ -2131,14 +2143,13 @@ write_template_arg_literal (value) ::= X <expression> E # expression */ static void -write_template_arg (node) - tree node; +write_template_arg (tree node) { enum tree_code code = TREE_CODE (node); MANGLE_TRACE_TREE ("template-arg", node); - /* A template template paramter's argument list contains TREE_LIST + /* A template template parameter's argument list contains TREE_LIST nodes of which the value field is the the actual argument. */ if (code == TREE_LIST) { @@ -2150,6 +2161,20 @@ write_template_arg (node) code = TREE_CODE (node); } } + + if (TREE_CODE (node) == NOP_EXPR + && TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE) + { + /* Template parameters can be of reference type. To maintain + internal consistency, such arguments use a conversion from + address of object to reference type. */ + my_friendly_assert (TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR, + 20031215); + if (abi_version_at_least (2)) + node = TREE_OPERAND (TREE_OPERAND (node, 0), 0); + else + G.need_abi_warning = 1; + } if (TYPE_P (node)) write_type (node); @@ -2183,8 +2208,8 @@ write_template_arg (node) ::= <name> ::= <substitution> */ -void -write_template_template_arg (tree decl) +static void +write_template_template_arg (const tree decl) { MANGLE_TRACE_TREE ("template-template-arg", decl); @@ -2204,9 +2229,8 @@ write_template_template_arg (tree decl) element type. For variable length arrays, the dimension (but not the '_' separator) is omitted." */ -static void -write_array_type (type) - tree type; +static void +write_array_type (const tree type) { write_char ('A'); if (TYPE_DOMAIN (type)) @@ -2226,7 +2250,20 @@ write_array_type (type) write_unsigned_number (tree_low_cst (max, 1)); } else - write_expression (TREE_OPERAND (max, 0)); + { + max = TREE_OPERAND (max, 0); + if (!abi_version_at_least (2)) + { + /* value_dependent_expression_p presumes nothing is + dependent when PROCESSING_TEMPLATE_DECL is zero. */ + ++processing_template_decl; + if (!value_dependent_expression_p (max)) + G.need_abi_warning = 1; + --processing_template_decl; + } + write_expression (max); + } + } write_char ('_'); write_type (TREE_TYPE (type)); @@ -2238,8 +2275,7 @@ write_array_type (type) <pointer-to-member-type> ::= M </class/ type> </member/ type> */ static void -write_pointer_to_member_type (type) - tree type; +write_pointer_to_member_type (const tree type) { write_char ('M'); write_type (TYPE_PTRMEM_CLASS_TYPE (type)); @@ -2250,18 +2286,10 @@ write_pointer_to_member_type (type) TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a TEMPLATE_PARM_INDEX. - <template-param> ::= T </parameter/ number> _ - - If we are internally mangling then we distinguish level and, for - non-type parms, type too. The mangling appends - - </level/ number> _ </non-type type/ type> _ - - This is used by mangle_conv_op_name_for_type. */ + <template-param> ::= T </parameter/ number> _ */ static void -write_template_param (parm) - tree parm; +write_template_param (const tree parm) { int parm_index; int parm_level; @@ -2301,8 +2329,7 @@ write_template_param (parm) ::= <substitution> */ static void -write_template_template_param (parm) - tree parm; +write_template_template_param (const tree parm) { tree template = NULL_TREE; @@ -2330,8 +2357,7 @@ write_template_template_param (parm) ::= S_ */ static void -write_substitution (seq_id) - int seq_id; +write_substitution (const int seq_id) { MANGLE_TRACE ("substitution", ""); @@ -2344,7 +2370,7 @@ write_substitution (seq_id) /* Start mangling ENTITY. */ static inline void -start_mangling (tree entity) +start_mangling (const tree entity) { G.entity = entity; G.need_abi_warning = false; @@ -2357,7 +2383,7 @@ start_mangling (tree entity) future version of the ABI, issue a warning. */ static inline const char * -finish_mangling (bool warn) +finish_mangling (const bool warn) { if (warn_abi && warn && G.need_abi_warning) warning ("the mangled name of `%D' will change in a future " @@ -2376,7 +2402,7 @@ finish_mangling (bool warn) /* Initialize data structures for mangling. */ void -init_mangle () +init_mangle (void) { gcc_obstack_init (&G.name_obstack); @@ -2393,8 +2419,7 @@ init_mangle () /* Generate the mangled name of DECL. */ static const char * -mangle_decl_string (decl) - tree decl; +mangle_decl_string (const tree decl) { const char *result; @@ -2402,29 +2427,9 @@ mangle_decl_string (decl) if (TREE_CODE (decl) == TYPE_DECL) write_type (TREE_TYPE (decl)); - else if (/* The names of `extern "C"' functions are not mangled. */ - (DECL_EXTERN_C_FUNCTION_P (decl) - /* But overloaded operator names *are* mangled. */ - && !DECL_OVERLOADED_OPERATOR_P (decl)) - /* The names of global variables aren't mangled either. */ - || (TREE_CODE (decl) == VAR_DECL - && CP_DECL_CONTEXT (decl) == global_namespace) - /* And neither are `extern "C"' variables. */ - || (TREE_CODE (decl) == VAR_DECL - && DECL_EXTERN_C_P (decl))) - write_string (IDENTIFIER_POINTER (DECL_NAME (decl))); else - { - write_mangled_name (decl); - if (DECL_LANG_SPECIFIC (decl) - && (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl) - || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl))) - /* We need a distinct mangled name for these entities, but - we should never actually output it. So, we append some - characters the assembler won't like. */ - write_string (" *INTERNAL* "); - } - + write_mangled_name (decl, true); + result = finish_mangling (/*warn=*/true); if (DEBUG_MANGLE) fprintf (stderr, "mangle_decl_string = '%s'\n\n", result); @@ -2434,8 +2439,7 @@ mangle_decl_string (decl) /* Create an identifier for the external mangled name of DECL. */ void -mangle_decl (decl) - tree decl; +mangle_decl (const tree decl) { tree id = get_identifier (mangle_decl_string (decl)); @@ -2445,8 +2449,7 @@ mangle_decl (decl) /* Generate the mangled representation of TYPE. */ const char * -mangle_type_string (type) - tree type; +mangle_type_string (const tree type) { const char *result; @@ -2461,8 +2464,7 @@ mangle_type_string (type) /* Create an identifier for the mangled representation of TYPE. */ tree -mangle_type (type) - tree type; +mangle_type (const tree type) { return get_identifier (mangle_type_string (type)); } @@ -2472,9 +2474,7 @@ mangle_type (type) component. */ static tree -mangle_special_for_type (type, code) - tree type; - const char *code; +mangle_special_for_type (const tree type, const char *code) { const char *result; @@ -2500,8 +2500,7 @@ mangle_special_for_type (type, code) structure for TYPE. */ tree -mangle_typeinfo_for_type (type) - tree type; +mangle_typeinfo_for_type (const tree type) { return mangle_special_for_type (type, "TI"); } @@ -2510,8 +2509,7 @@ mangle_typeinfo_for_type (type) the mangled name of TYPE. */ tree -mangle_typeinfo_string_for_type (type) - tree type; +mangle_typeinfo_string_for_type (const tree type) { return mangle_special_for_type (type, "TS"); } @@ -2519,8 +2517,7 @@ mangle_typeinfo_string_for_type (type) /* Create an identifier for the mangled name of the vtable for TYPE. */ tree -mangle_vtbl_for_type (type) - tree type; +mangle_vtbl_for_type (const tree type) { return mangle_special_for_type (type, "TV"); } @@ -2528,8 +2525,7 @@ mangle_vtbl_for_type (type) /* Returns an identifier for the mangled name of the VTT for TYPE. */ tree -mangle_vtt_for_type (type) - tree type; +mangle_vtt_for_type (const tree type) { return mangle_special_for_type (type, "TT"); } @@ -2549,9 +2545,7 @@ mangle_vtt_for_type (type) <special-name> ::= CT <type> <offset number> _ <base type> */ tree -mangle_ctor_vtbl_for_type (type, binfo) - tree type; - tree binfo; +mangle_ctor_vtbl_for_type (const tree type, const tree binfo) { const char *result; @@ -2570,45 +2564,74 @@ mangle_ctor_vtbl_for_type (type, binfo) return get_identifier (result); } -/* Return an identifier for the mangled name of a thunk to FN_DECL. - OFFSET is the initial adjustment to this used to find the vptr. If - VCALL_OFFSET is non-NULL, this is a virtual thunk, and it is the - vtbl offset in bytes. +/* Mangle a this pointer or result pointer adjustment. + + <call-offset> ::= h <fixed offset number> _ + ::= v <fixed offset number> _ <virtual offset number> _ */ + +static void +mangle_call_offset (const tree fixed_offset, const tree virtual_offset) +{ + write_char (virtual_offset ? 'v' : 'h'); + + /* For either flavor, write the fixed offset. */ + write_integer_cst (fixed_offset); + write_char ('_'); + + /* For a virtual thunk, add the virtual offset. */ + if (virtual_offset) + { + write_integer_cst (virtual_offset); + write_char ('_'); + } +} - <special-name> ::= Th <offset number> _ <base encoding> - ::= Tv <offset number> _ <vcall offset number> _ - <base encoding> +/* Return an identifier for the mangled name of a this-adjusting or + covariant thunk to FN_DECL. FIXED_OFFSET is the initial adjustment + to this used to find the vptr. If VIRTUAL_OFFSET is non-NULL, this + is a virtual thunk, and it is the vtbl offset in + bytes. THIS_ADJUSTING is nonzero for a this adjusting thunk and + zero for a covariant thunk. Note, that FN_DECL might be a covariant + thunk itself. A covariant thunk name always includes the adjustment + for the this pointer, even if there is none. + + <special-name> ::= T <call-offset> <base encoding> + ::= Tc <this_adjust call-offset> <result_adjust call-offset> + <base encoding> */ tree -mangle_thunk (fn_decl, offset, vcall_offset) - tree fn_decl; - tree offset; - tree vcall_offset; +mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset, + tree virtual_offset) { const char *result; start_mangling (fn_decl); write_string ("_Z"); - /* The <special-name> for virtual thunks is Tv, for non-virtual - thunks Th. */ write_char ('T'); - if (vcall_offset != 0) - write_char ('v'); + + if (!this_adjusting) + { + /* Covariant thunk with no this adjustment */ + write_char ('c'); + mangle_call_offset (integer_zero_node, NULL_TREE); + mangle_call_offset (fixed_offset, virtual_offset); + } + else if (!DECL_THUNK_P (fn_decl)) + /* Plain this adjusting thunk. */ + mangle_call_offset (fixed_offset, virtual_offset); else - write_char ('h'); - - /* For either flavor, write the offset to this. */ - write_integer_cst (offset); - write_char ('_'); - - /* For a virtual thunk, add the vcall offset. */ - if (vcall_offset) { - /* Virtual thunk. Write the vcall offset and base type name. */ - write_integer_cst (vcall_offset); - write_char ('_'); + /* This adjusting thunk to covariant thunk. */ + write_char ('c'); + mangle_call_offset (fixed_offset, virtual_offset); + fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn_decl)); + virtual_offset = THUNK_VIRTUAL_OFFSET (fn_decl); + if (virtual_offset) + virtual_offset = BINFO_VPTR_FIELD (virtual_offset); + mangle_call_offset (fixed_offset, virtual_offset); + fn_decl = THUNK_TARGET (fn_decl); } /* Scoped name. */ @@ -2621,8 +2644,8 @@ mangle_thunk (fn_decl, offset, vcall_offset) } /* This hash table maps TYPEs to the IDENTIFIER for a conversion - operator to TYPE. The nodes are TREE_LISTs whose TREE_PURPOSE is - the TYPE and whose TREE_VALUE is the IDENTIFIER. */ + operator to TYPE. The nodes are IDENTIFIERs whose TREE_TYPE is the + TYPE. */ static GTY ((param_is (union tree_node))) htab_t conv_type_names; @@ -2631,7 +2654,7 @@ static GTY ((param_is (union tree_node))) htab_t conv_type_names; static hashval_t hash_type (const void *val) { - return htab_hash_pointer (TREE_PURPOSE ((tree) val)); + return (hashval_t) TYPE_UID (TREE_TYPE ((tree) val)); } /* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */ @@ -2639,41 +2662,44 @@ hash_type (const void *val) static int compare_type (const void *val1, const void *val2) { - return TREE_PURPOSE ((tree) val1) == (tree) val2; + return TREE_TYPE ((tree) val1) == (tree) val2; } /* 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. */ - + tree mangle_conv_op_name_for_type (const tree type) { void **slot; tree identifier; - char buffer[64]; - + if (conv_type_names == NULL) conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL); slot = htab_find_slot_with_hash (conv_type_names, type, - htab_hash_pointer (type), INSERT); - if (*slot) - return TREE_VALUE ((tree) *slot); - - /* Create a unique name corresponding to TYPE. */ - sprintf (buffer, "operator %lu", - (unsigned long) htab_elements (conv_type_names)); - identifier = get_identifier (buffer); - *slot = build_tree_list (type, identifier); + (hashval_t) TYPE_UID (type), INSERT); + identifier = (tree)*slot; + if (!identifier) + { + char buffer[64]; + + /* Create a unique name corresponding to TYPE. */ + sprintf (buffer, "operator %lu", + (unsigned long) htab_elements (conv_type_names)); + identifier = get_identifier (buffer); + *slot = identifier; + + /* Hang TYPE off the identifier so it can be found easily later + when performing conversions. */ + TREE_TYPE (identifier) = type; + + /* Set bits on the identifier so we know later it's a conversion. */ + IDENTIFIER_OPNAME_P (identifier) = 1; + IDENTIFIER_TYPENAME_P (identifier) = 1; + } - /* Set bits on the identifier so we know later it's a conversion. */ - IDENTIFIER_OPNAME_P (identifier) = 1; - IDENTIFIER_TYPENAME_P (identifier) = 1; - /* Hang TYPE off the identifier so it can be found easily later when - performing conversions. */ - TREE_TYPE (identifier) = type; - return identifier; } @@ -2681,8 +2707,7 @@ mangle_conv_op_name_for_type (const tree type) variable for indicated VARIABLE. */ tree -mangle_guard_variable (variable) - tree variable; +mangle_guard_variable (const tree variable) { start_mangling (variable); write_string ("_ZGV"); @@ -2700,8 +2725,7 @@ mangle_guard_variable (variable) as well call them something readable. */ tree -mangle_ref_init_variable (variable) - tree variable; +mangle_ref_init_variable (const tree variable) { start_mangling (variable); write_string ("_ZGR"); @@ -2715,8 +2739,7 @@ mangle_ref_init_variable (variable) /* How to write the type codes for the integer Java type. */ static void -write_java_integer_type_codes (type) - tree type; +write_java_integer_type_codes (const tree type) { if (type == java_int_type_node) write_char ('i'); |