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;
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 *);
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. */
}
}
-/* 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);
}
/* <name> ::= <unscoped-name>
/* 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 <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 (TREE_CODE (context) == FUNCTION_DECL
+ || TREE_CODE (context) == PARM_DECL)
{
/* Yes, we have local scope. Use the <local-name>
production for the innermost function 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 <nested-name>. */
/* 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');
/* 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 <local-name> 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;
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)
+ {
+ /* <data-member-prefix> := <member source-name> M */
+ write_char ('M');
+ return;
+ }
}
add_substitution (node);
<unqualified-name> ::= <operator-name>
::= <special-name>
::= <source-name>
+ ::= <unnamed-type-name>
::= <local-source-name>
<local-source-name> ::= L <source-name> <discriminator> */
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. */
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 ();
+}
+
+/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
+
+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);
+}
+
+/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
+ <lambda-sig> ::= <parameter type>+ # 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
}
}
+/* 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. */
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
}
/* 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.
<local-name> := Z <function encoding> E <entity name> [<discriminator>]
- := Z <function encoding> E s [<discriminator>] */
+ := Z <function encoding> E s [<discriminator>]
+ := Z <function encoding> Ed [ <parameter number> ] _ <entity name> */
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');
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');
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;
/* 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. */
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);
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))
{
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
{
}
else
{
- int i;
+ int i, len;
const char *name;
/* When we bind a variable or function to a non-type template
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:
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);
}
/* <template-template-param>
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);