diff options
Diffstat (limited to 'gcc/cp/mangle.c')
-rw-r--r-- | gcc/cp/mangle.c | 205 |
1 files changed, 122 insertions, 83 deletions
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 15334f321e3..b34c309c827 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -158,7 +158,7 @@ static void mangle_call_offset (const tree, const tree); /* Functions for emitting mangled representations of things. */ -static void write_mangled_name (const 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); @@ -602,27 +602,66 @@ find_substitution (tree 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 (const tree decl) +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* "); } } @@ -991,6 +1030,8 @@ write_unqualified_name (const tree 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. @@ -1804,37 +1845,25 @@ write_class_enum_type (const tree type) static void 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'); } @@ -1893,7 +1922,7 @@ write_expression (tree 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 @@ -2112,7 +2141,7 @@ write_template_arg (tree 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) { @@ -2124,6 +2153,20 @@ write_template_arg (tree 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); @@ -2199,7 +2242,20 @@ write_array_type (const tree 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)); @@ -2363,29 +2419,9 @@ mangle_decl_string (const tree 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); @@ -2600,8 +2636,8 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_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; @@ -2610,7 +2646,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). */ @@ -2618,7 +2654,7 @@ 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 @@ -2630,29 +2666,32 @@ 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; } |