X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Fmangle.c;h=7e4cf668e9c48ec831d1c1cbbbbc93ca2fe7f24d;hp=bb046d23d5a4c946d332cdd2e50cc09170db8f25;hb=e9b1be72e8c51f2f935e82733151993527722cad;hpb=62164d4c3690257a01326783bed77c15831d52b9 diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index bb046d23d5a..7e4cf668e9c 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -105,10 +105,6 @@ typedef struct GTY(()) globals { static GTY (()) globals G; -/* Whether or not to pretend that a static function is in an anonymous - namespace. */ -static bool fake_anon_scope; - /* The obstack on which we build mangled names. */ static struct obstack *mangle_obstack; @@ -182,10 +178,13 @@ 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 void write_unnamed_type_name (const tree); +static void write_closure_type_name (const 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_compact_number (int num); static void write_integer_cst (const tree); static void write_real_cst (const tree); static void write_identifier (const char *); @@ -211,9 +210,10 @@ 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 write_local_name (tree, const tree, const tree); static void dump_substitution_candidates (void); static tree mangle_decl_string (const tree); +static int local_class_index (tree); /* Control functions. */ @@ -730,18 +730,24 @@ write_encoding (const tree decl) } } -/* Since we now use strcmp to compare typeinfos on all targets because of - the RTLD_LOCAL problem, we need to munge the typeinfo name used for - local classes of static functions to fix g++.dg/abi/local1.C. We do - that by pretending that the function is in an anonymous namespace. */ +/* Lambdas can have a bit more context for mangling, specifically VAR_DECL + or PARM_DECL context, which doesn't belong in DECL_CONTEXT. */ -static bool -needs_fake_anon (const_tree decl) +static tree +decl_mangling_context (tree decl) { - /* Pretend there's an anonymous namespace right around a static - function if we're mangling for RTTI. */ - return (fake_anon_scope && !TREE_PUBLIC (decl) - && TREE_CODE (decl) == FUNCTION_DECL); + if (TREE_CODE (decl) == TYPE_DECL + && LAMBDA_TYPE_P (TREE_TYPE (decl))) + { + tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl)); + if (extra) + return extra; + } + else if (TREE_CODE (decl) == TYPE_DECL + && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM) + /* template type parms have no mangling context. */ + return NULL_TREE; + return CP_DECL_CONTEXT (decl); } /* ::= @@ -767,23 +773,17 @@ write_name (tree decl, const int ignore_local_scope) /* In case this is a typedef, fish out the corresponding TYPE_DECL for the main variant. */ decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); - context = CP_TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); } - else - context = CP_DECL_CONTEXT (decl); - - gcc_assert (context != NULL_TREE); - /* If we need a fake anonymous namespace, force the nested name path. */ - if (needs_fake_anon (decl) && context == global_namespace) - context = error_mark_node; + context = decl_mangling_context (decl); /* A decl in :: or ::std scope is treated specially. The former is mangled using or , the latter with a special substitution. Also, a name that is directly in a local function scope is also mangled with rather than a full . */ - if (context == global_namespace + if (context == NULL + || context == global_namespace || DECL_NAMESPACE_STD_P (context) || (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL)) { @@ -801,9 +801,6 @@ write_name (tree decl, const int ignore_local_scope) } else { - if (context == error_mark_node) - context = global_namespace; - /* Handle local names, unless we asked not to (that is, invoked under , to handle only the part of the name under the local scope). */ @@ -816,13 +813,14 @@ write_name (tree decl, const int ignore_local_scope) directly in that function's scope, either decl or one of its enclosing scopes. */ tree local_entity = decl; - while (context != global_namespace) + while (context != NULL && context != global_namespace) { /* Make sure we're always dealing with decls. */ - if (TYPE_P (context)) + if (context != NULL && TYPE_P (context)) context = TYPE_NAME (context); /* Is this a function? */ - if (TREE_CODE (context) == FUNCTION_DECL) + if (TREE_CODE (context) == FUNCTION_DECL + || TREE_CODE (context) == PARM_DECL) { /* Yes, we have local scope. Use the production for the innermost function scope. */ @@ -831,7 +829,7 @@ write_name (tree decl, const int ignore_local_scope) } /* Up one scope level. */ local_entity = context; - context = CP_DECL_CONTEXT (context); + context = decl_mangling_context (context); } /* No local scope found? Fall through to . */ @@ -863,6 +861,7 @@ write_unscoped_name (const tree decl) /* If not, it should be either in the global namespace, or directly in a local function scope. */ gcc_assert (context == global_namespace + || context != NULL || TREE_CODE (context) == FUNCTION_DECL); write_unqualified_name (decl); @@ -934,9 +933,6 @@ write_nested_name (const tree decl) { /* No, just use */ write_prefix (DECL_CONTEXT (decl)); - if (needs_fake_anon (decl)) - /* Pretend this static function is in an anonymous namespace. */ - write_source_name (get_anonymous_namespace_name ()); write_unqualified_name (decl); } write_char ('E'); @@ -955,23 +951,24 @@ write_prefix (const tree node) /* Non-NULL if NODE represents a template-id. */ tree template_info = NULL; - MANGLE_TRACE_TREE ("prefix", node); - if (node == NULL || node == global_namespace) return; + MANGLE_TRACE_TREE ("prefix", node); + if (find_substitution (node)) return; if (DECL_P (node)) { - /* If this is a function decl, that means we've hit function + /* If this is a function or parm decl, that means we've hit function scope, so this prefix must be for a local name. In this case, we're under the production, which encodes the enclosing function scope elsewhere. So don't continue here. */ - if (TREE_CODE (node) == FUNCTION_DECL) + if (TREE_CODE (node) == FUNCTION_DECL + || TREE_CODE (node) == PARM_DECL) return; decl = node; @@ -1016,8 +1013,15 @@ write_prefix (const tree node) else /* Not templated. */ { - write_prefix (CP_DECL_CONTEXT (decl)); + write_prefix (decl_mangling_context (decl)); write_unqualified_name (decl); + if (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FIELD_DECL) + { + /* := M */ + write_char ('M'); + return; + } } add_substitution (node); @@ -1107,6 +1111,7 @@ write_template_prefix (const tree node) ::= ::= ::= + ::= ::= ::= L */ @@ -1172,7 +1177,18 @@ write_unqualified_name (const tree decl) so there's no code to output one here. */ } else - write_source_name (DECL_NAME (decl)); + { + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == TYPE_DECL + && TYPE_ANONYMOUS_P (type)) + write_unnamed_type_name (type); + else if (TREE_CODE (decl) == TYPE_DECL + && LAMBDA_TYPE_P (type)) + write_closure_type_name (type); + else + write_source_name (DECL_NAME (decl)); + } } /* Write the unqualified-name for a conversion operator to TYPE. */ @@ -1202,6 +1218,78 @@ write_source_name (tree identifier) write_identifier (IDENTIFIER_POINTER (identifier)); } +/* Encode 0 as _, and 1+ as n-1_. */ + +static void +write_compact_number (int num) +{ + if (num > 0) + write_unsigned_number (num - 1); + write_char ('_'); +} + +/* Return how many unnamed types precede TYPE in its enclosing class. */ + +static int +nested_anon_class_index (tree type) +{ + int index = 0; + tree member = TYPE_FIELDS (TYPE_CONTEXT (type)); + for (; member; member = TREE_CHAIN (member)) + if (DECL_IMPLICIT_TYPEDEF_P (member)) + { + tree memtype = TREE_TYPE (member); + if (memtype == type) + return index; + else if (TYPE_ANONYMOUS_P (memtype)) + ++index; + } + + gcc_unreachable (); +} + +/* ::= Ut [ ] _ */ + +static void +write_unnamed_type_name (const tree type __attribute__ ((__unused__))) +{ + int discriminator; + MANGLE_TRACE_TREE ("unnamed-type-name", type); + + if (TYPE_FUNCTION_SCOPE_P (type)) + discriminator = local_class_index (type); + else if (TYPE_CLASS_SCOPE_P (type)) + discriminator = nested_anon_class_index (type); + else + { + gcc_assert (no_linkage_check (type, /*relaxed_p=*/true)); + /* Just use the old mangling at namespace scope. */ + write_source_name (TYPE_IDENTIFIER (type)); + return; + } + + write_string ("Ut"); + write_compact_number (discriminator); +} + +/* ::= Ul E [ ] _ + ::= + # Parameter types or "v" if the lambda has no parameters */ + +static void +write_closure_type_name (const tree type) +{ + tree fn = lambda_function (type); + tree lambda = CLASSTYPE_LAMBDA_EXPR (type); + tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); + + MANGLE_TRACE_TREE ("closure-type-name", type); + + write_string ("Ul"); + write_method_parms (parms, DECL_NONSTATIC_MEMBER_FUNCTION_P (fn), fn); + write_char ('E'); + write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda)); +} + /* Convert NUMBER to ascii using base BASE and generating at least MIN_DIGITS characters. BUFFER points to the _end_ of the buffer into which to store the characters. Returns the number of @@ -1461,6 +1549,29 @@ write_special_name_destructor (const tree dtor) } } +/* Scan the vector of local classes and return how many others with the + same name (or same no name) and context precede ENTITY. */ + +static int +local_class_index (tree entity) +{ + int ix, discriminator = 0; + tree name = (TYPE_ANONYMOUS_P (entity) ? NULL_TREE + : TYPE_IDENTIFIER (entity)); + tree ctx = TYPE_CONTEXT (entity); + for (ix = 0; ; ix++) + { + tree type = VEC_index (tree, local_classes, ix); + if (type == entity) + return discriminator; + if (TYPE_CONTEXT (type) == ctx + && (name ? TYPE_IDENTIFIER (type) == name + : TYPE_ANONYMOUS_P (type))) + ++discriminator; + } + gcc_unreachable (); +} + /* Return the discriminator for ENTITY appearing inside FUNCTION. The discriminator is the lexical ordinal of VAR among entities with the same name in the same FUNCTION. */ @@ -1468,29 +1579,28 @@ write_special_name_destructor (const tree dtor) static int discriminator_for_local_entity (tree entity) { - /* Assume this is the only local entity with this name. */ - int discriminator = 0; - - if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity)) - discriminator = DECL_DISCRIMINATOR (entity); + if (DECL_DISCRIMINATOR_P (entity)) + { + if (DECL_DISCRIMINATOR_SET_P (entity)) + return DECL_DISCRIMINATOR (entity); + else + /* The first entity with a particular name doesn't get + DECL_DISCRIMINATOR set up. */ + return 0; + } else if (TREE_CODE (entity) == TYPE_DECL) { - int ix; - /* Scan the list of local classes. */ entity = TREE_TYPE (entity); - for (ix = 0; ; ix++) - { - tree type = VEC_index (tree, local_classes, ix); - if (type == entity) - break; - if (TYPE_IDENTIFIER (type) == TYPE_IDENTIFIER (entity) - && TYPE_CONTEXT (type) == TYPE_CONTEXT (entity)) - ++discriminator; - } - } - return discriminator; + /* Lambdas and unnamed types have their own discriminators. */ + if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity)) + return 0; + + return local_class_index (entity); + } + else + gcc_unreachable (); } /* Return the discriminator for STRING, a string literal used inside @@ -1523,23 +1633,49 @@ write_discriminator (const int discriminator) } /* Mangle the name of a function-scope entity. FUNCTION is the - FUNCTION_DECL for the enclosing function. ENTITY is the decl for - the entity itself. LOCAL_ENTITY is the entity that's directly - scoped in FUNCTION_DECL, either ENTITY itself or an enclosing scope - of ENTITY. + FUNCTION_DECL for the enclosing function, or a PARM_DECL for lambdas in + default argument scope. ENTITY is the decl for the entity itself. + LOCAL_ENTITY is the entity that's directly scoped in FUNCTION_DECL, + either ENTITY itself or an enclosing scope of ENTITY. := Z E [] - := Z E s [] */ + := Z E s [] + := Z Ed [ ] _ */ static void -write_local_name (const tree function, const tree local_entity, +write_local_name (tree function, const tree local_entity, const tree entity) { + tree parm = NULL_TREE; + MANGLE_TRACE_TREE ("local-name", entity); + if (TREE_CODE (function) == PARM_DECL) + { + parm = function; + function = DECL_CONTEXT (parm); + } + write_char ('Z'); write_encoding (function); write_char ('E'); + + /* For this purpose, parameters are numbered from right-to-left. */ + if (parm) + { + tree t; + int i = 0; + for (t = DECL_ARGUMENTS (function); t; t = TREE_CHAIN (t)) + { + if (t == parm) + i = 1; + else if (i) + ++i; + } + write_char ('d'); + write_compact_number (i - 1); + } + if (TREE_CODE (entity) == STRING_CST) { write_char ('s'); @@ -1718,6 +1854,10 @@ write_type (tree type) break; case DECLTYPE_TYPE: + /* These shouldn't make it into mangling. */ + gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type) + && !DECLTYPE_FOR_LAMBDA_RETURN (type)); + write_char ('D'); if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)) write_char ('t'); @@ -1894,6 +2034,12 @@ write_builtin_type (tree type) write_char ('d'); else if (type == long_double_type_node) write_char ('e'); + else if (type == dfloat32_type_node) + write_string ("Df"); + else if (type == dfloat64_type_node) + write_string ("Dd"); + else if (type == dfloat128_type_node) + write_string ("De"); else gcc_unreachable (); break; @@ -2114,21 +2260,22 @@ write_class_enum_type (const tree type) /* Non-terminal . ARGS is a TREE_VEC of template arguments. - ::= I + E */ + ::= I * E */ static void write_template_args (tree args) { int i; - int length = TREE_VEC_LENGTH (args); + int length = 0; MANGLE_TRACE_TREE ("template-args", args); write_char ('I'); - gcc_assert (length > 0); + if (args) + length = TREE_VEC_LENGTH (args); - if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) + if (args && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) { /* We have nested template args. We want the innermost template argument list. */ @@ -2152,12 +2299,7 @@ write_member_name (tree member) if (TREE_CODE (member) == IDENTIFIER_NODE) write_source_name (member); else if (DECL_P (member)) - { - /* G++ 3.2 incorrectly put out both the "sr" code and - the nested name of the qualified name. */ - G.need_abi_warning = 1; - write_unqualified_name (member); - } + write_unqualified_name (member); else if (TREE_CODE (member) == TEMPLATE_ID_EXPR) { tree name = TREE_OPERAND (member, 0); @@ -2230,9 +2372,7 @@ write_expression (tree expr) int index = DECL_PARM_INDEX (expr); gcc_assert (index >= 1); write_string ("fp"); - if (index > 1) - write_unsigned_number (index - 2); - write_char ('_'); + write_compact_number (index - 1); } else if (DECL_P (expr)) { @@ -2256,17 +2396,27 @@ write_expression (tree expr) write_string ("at"); write_type (TREE_OPERAND (expr, 0)); } - else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF) + else if (TREE_CODE (expr) == SCOPE_REF) { tree scope = TREE_OPERAND (expr, 0); tree member = TREE_OPERAND (expr, 1); + if (!abi_version_at_least (2)) + { + write_string ("sr"); + write_type (scope); + /* G++ 3.2 incorrectly put out both the "sr" code and + the nested name of the qualified name. */ + G.need_abi_warning = 1; + write_encoding (member); + } + /* If the MEMBER is a real declaration, then the qualifying scope was not dependent. Ideally, we would not have a SCOPE_REF in those cases, but sometimes we do. If the second argument is a DECL, then the name must not have been dependent. */ - if (DECL_P (member)) + else if (DECL_P (member)) write_expression (member); else { @@ -2331,7 +2481,7 @@ write_expression (tree expr) } else { - int i; + int i, len; const char *name; /* When we bind a variable or function to a non-type template @@ -2431,14 +2581,28 @@ write_expression (tree expr) sorry ("mangling new-expression"); break; - /* Handle pointers-to-members specially. */ - case SCOPE_REF: - write_type (TREE_OPERAND (expr, 0)); - write_member_name (TREE_OPERAND (expr, 1)); - break; - default: - for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i) + /* In the middle-end, some expressions have more operands than + they do in templates (and mangling). */ + switch (code) + { + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + len = 1; + break; + + case ARRAY_REF: + len = 2; + break; + + default: + len = TREE_OPERAND_LENGTH (expr); + break; + } + + for (i = 0; i < len; ++i) { tree operand = TREE_OPERAND (expr, i); /* As a GNU extension, the middle operand of a @@ -2668,8 +2832,6 @@ static void write_template_param (const tree parm) { int parm_index; - int parm_level; - tree parm_type = NULL_TREE; MANGLE_TRACE_TREE ("template-parm", parm); @@ -2679,13 +2841,10 @@ write_template_param (const tree parm) case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: parm_index = TEMPLATE_TYPE_IDX (parm); - parm_level = TEMPLATE_TYPE_LEVEL (parm); break; case TEMPLATE_PARM_INDEX: parm_index = TEMPLATE_PARM_IDX (parm); - parm_level = TEMPLATE_PARM_LEVEL (parm); - parm_type = TREE_TYPE (TEMPLATE_PARM_DECL (parm)); break; default: @@ -2695,9 +2854,7 @@ write_template_param (const tree parm) write_char ('T'); /* NUMBER as it appears in the mangling is (-1)-indexed, with the earliest template param denoted by `_'. */ - if (parm_index > 0) - write_unsigned_number (parm_index - 1); - write_char ('_'); + write_compact_number (parm_index); } /* @@ -2792,7 +2949,7 @@ finish_mangling_get_identifier (const bool warn) finish_mangling_internal (warn); /* Don't obstack_finish here, and the next start_mangling will remove the identifier. */ - return get_identifier ((const char *) name_base); + return get_identifier ((const char *) obstack_base (mangle_obstack)); } /* Initialize data structures for mangling. */ @@ -2845,18 +3002,15 @@ mangle_decl (const tree decl) SET_DECL_ASSEMBLER_NAME (decl, id); } -/* Generate the mangled representation of TYPE for the typeinfo name. */ +/* Generate the mangled representation of TYPE. */ const char * -mangle_type_string_for_rtti (const tree type) +mangle_type_string (const tree type) { const char *result; start_mangling (type); - /* Mangle in a fake anonymous namespace if necessary. */ - fake_anon_scope = true; write_type (type); - fake_anon_scope = false; result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) fprintf (stderr, "mangle_type_string = '%s'\n\n", result);