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;
}
}
-/* 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. */
-
-static bool
-needs_fake_anon (const_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);
-}
-
/* Lambdas can have a bit more context for mangling, specifically VAR_DECL
or PARM_DECL context, which doesn't belong in DECL_CONTEXT. */
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);
}
context = decl_mangling_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;
-
/* A decl in :: or ::std scope is treated specially. The former is
mangled using <unscoped-name> or <unscoped-template-name>, the
latter with a special substitution. Also, a name that is
directly in a local function scope is also mangled with
<unscoped-name> rather than a full <nested-name>. */
- if (context == global_namespace
+ if (context == NULL
+ || context == global_namespace
|| DECL_NAMESPACE_STD_P (context)
|| (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
{
}
else
{
- if (context == error_mark_node)
- context = global_namespace;
-
/* Handle local names, unless we asked not to (that is, invoked
under <local-name>, to handle only the part of the name under
the 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 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);
{
/* No, just use <prefix> */
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');
<local-source-name> ::= L <source-name> <discriminator> */
static void
+write_unqualified_id (tree identifier)
+{
+ if (IDENTIFIER_TYPENAME_P (identifier))
+ write_conversion_operator_name (TREE_TYPE (identifier));
+ else if (IDENTIFIER_OPNAME_P (identifier))
+ {
+ int i;
+ const char *mangled_name = NULL;
+
+ /* Unfortunately, there is no easy way to go from the
+ name of the operator back to the corresponding tree
+ code. */
+ for (i = 0; i < MAX_TREE_CODES; ++i)
+ if (operator_name_info[i].identifier == identifier)
+ {
+ /* The ABI says that we prefer binary operator
+ names to unary operator names. */
+ if (operator_name_info[i].arity == 2)
+ {
+ mangled_name = operator_name_info[i].mangled_name;
+ break;
+ }
+ else if (!mangled_name)
+ mangled_name = operator_name_info[i].mangled_name;
+ }
+ else if (assignment_operator_name_info[i].identifier
+ == identifier)
+ {
+ mangled_name
+ = assignment_operator_name_info[i].mangled_name;
+ break;
+ }
+ write_string (mangled_name);
+ }
+ else
+ write_source_name (identifier);
+}
+
+static void
write_unqualified_name (const tree decl)
{
MANGLE_TRACE_TREE ("unqualified-name", decl);
+ if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ {
+ write_unqualified_id (decl);
+ return;
+ }
+
if (DECL_NAME (decl) == NULL_TREE)
{
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
MANGLE_TRACE_TREE ("closure-type-name", type);
write_string ("Ul");
- write_method_parms (parms, /*method_p=*/1, fn);
+ write_method_parms (parms, DECL_NONSTATIC_MEMBER_FUNCTION_P (fn), fn);
write_char ('E');
write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
}
{
if (DECL_DISCRIMINATOR_P (entity))
{
- if (DECL_LANG_SPECIFIC (entity))
+ if (DECL_DISCRIMINATOR_SET_P (entity))
return DECL_DISCRIMINATOR (entity);
else
/* The first entity with a particular name doesn't get
- DECL_LANG_SPECIFIC/DECL_DISCRIMINATOR. */
+ DECL_DISCRIMINATOR set up. */
return 0;
}
else if (TREE_CODE (entity) == TYPE_DECL)
if (find_substitution (type))
return;
+ /* According to the C++ ABI, some library classes are passed the
+ same as the scalar type of their single member and use the same
+ mangling. */
+ if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
+ type = TREE_TYPE (first_field (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
break;
case VECTOR_TYPE:
- write_string ("U8__vector");
+ if (abi_version_at_least (4))
+ {
+ write_string ("Dv");
+ /* Non-constant vector size would be encoded with
+ _ expression, but we don't support that yet. */
+ write_unsigned_number (TYPE_VECTOR_SUBPARTS (type));
+ write_char ('_');
+ }
+ else
+ write_string ("U8__vector");
write_type (TREE_TYPE (type));
break;
/* Non-terminal <template-args>. ARGS is a TREE_VEC of template
arguments.
- <template-args> ::= I <template-arg>+ E */
+ <template-args> ::= I <template-arg>* 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. */
write_member_name (tree member)
{
if (TREE_CODE (member) == IDENTIFIER_NODE)
- write_source_name (member);
+ write_unqualified_id (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);
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
{
- tree template_args;
-
write_string ("sr");
write_type (scope);
- /* If MEMBER is a template-id, separate the template
- from the arguments. */
- if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
- {
- template_args = TREE_OPERAND (member, 1);
- member = TREE_OPERAND (member, 0);
- }
- else
- template_args = NULL_TREE;
- /* Write out the name of the MEMBER. */
- if (IDENTIFIER_TYPENAME_P (member))
- write_conversion_operator_name (TREE_TYPE (member));
- else if (IDENTIFIER_OPNAME_P (member))
- {
- int i;
- const char *mangled_name = NULL;
-
- /* Unfortunately, there is no easy way to go from the
- name of the operator back to the corresponding tree
- code. */
- for (i = 0; i < MAX_TREE_CODES; ++i)
- if (operator_name_info[i].identifier == member)
- {
- /* The ABI says that we prefer binary operator
- names to unary operator names. */
- if (operator_name_info[i].arity == 2)
- {
- mangled_name = operator_name_info[i].mangled_name;
- break;
- }
- else if (!mangled_name)
- mangled_name = operator_name_info[i].mangled_name;
- }
- else if (assignment_operator_name_info[i].identifier
- == member)
- {
- mangled_name
- = assignment_operator_name_info[i].mangled_name;
- break;
- }
- write_string (mangled_name);
- }
- else
- write_source_name (member);
- /* Write out the template arguments. */
- if (template_args)
- write_template_args (template_args);
+ write_member_name (member);
}
}
else if (TREE_CODE (expr) == INDIRECT_REF
{
write_expression (TREE_OPERAND (expr, 0));
}
+ else if (TREE_CODE (expr) == IDENTIFIER_NODE)
+ {
+ /* An operator name appearing as a dependent name needs to be
+ specially marked to disambiguate between a use of the operator
+ name and a use of the operator in an expression. */
+ if (IDENTIFIER_OPNAME_P (expr))
+ write_string ("on");
+ write_unqualified_id (expr);
+ }
+ else if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+ {
+ tree fn = TREE_OPERAND (expr, 0);
+ if (is_overloaded_fn (fn))
+ fn = DECL_NAME (get_first_fn (fn));
+ if (IDENTIFIER_OPNAME_P (fn))
+ write_string ("on");
+ write_unqualified_id (fn);
+ write_template_args (TREE_OPERAND (expr, 1));
+ }
else
{
- int i;
+ int i, len;
const char *name;
/* When we bind a variable or function to a non-type template
&& type_dependent_expression_p_push (expr))
fn = DECL_NAME (get_first_fn (fn));
- if (TREE_CODE (fn) == IDENTIFIER_NODE)
- write_source_name (fn);
- else
- write_expression (fn);
+ write_expression (fn);
}
for (i = 0; i < call_expr_nargs (expr); ++i)
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
write_template_param (const tree parm)
{
int parm_index;
- int parm_level;
- tree parm_type = NULL_TREE;
MANGLE_TRACE_TREE ("template-parm", 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:
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. */
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);