-/* Name mangling for the new standard C++ ABI.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Name mangling for the 3.0 C++ ABI.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Alex Samuel <sameul@codesourcery.com>
This file is part of GNU CC.
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
+#include "real.h"
#include "obstack.h"
#include "toplev.h"
#include "varray.h"
/* Macros for tracing the write_* functions. */
#if DEBUG_MANGLE
# define MANGLE_TRACE(FN, INPUT) \
- fprintf (stderr, " %-24s: %-24s\n", FN, INPUT)
+ fprintf (stderr, " %-24s: %-24s\n", (FN), (INPUT))
# define MANGLE_TRACE_TREE(FN, NODE) \
fprintf (stderr, " %-24s: %-24s (%p)\n", \
- FN, tree_code_name[TREE_CODE (NODE)], (void *) NODE)
+ (FN), tree_code_name[TREE_CODE (NODE)], (void *) (NODE))
#else
# define MANGLE_TRACE(FN, INPUT)
# define MANGLE_TRACE_TREE(FN, NODE)
#endif
-/* Non-zero if NODE is a class template-id. We can't rely on
+/* Nonzero if NODE is a class template-id. We can't rely on
CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
that hard to distinguish A<T> from A, where A<T> is the type as
instantiated outside of the template, and A is the type used
/* An array of the current substitution candidates, in the order
we've seen them. */
varray_type substitutions;
+
+ /* We are mangling an internal symbol. It is important to keep those
+ involving template parmeters distinct by distinguishing their level
+ and, for non-type parms, their type. */
+ bool internal_mangling_p;
} G;
/* Indices into subst_identifiers. These are identifiers used in
/* Single-letter codes for builtin integer types, defined in
<builtin-type>. These are indexed by integer_type_kind values. */
-static char
+static const char
integer_type_codes[itk_none] =
{
'c', /* itk_char */
static void write_template_prefix PARAMS ((tree));
static void write_unqualified_name PARAMS ((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 inline const char *finish_mangling PARAMS ((void));
static tree mangle_special_for_type PARAMS ((tree, const char *));
-/* Foreign language functions. */
+/* Foreign language functions. */
static void write_java_integer_type_codes PARAMS ((tree));
#define write_char(CHAR) \
obstack_1grow (&G.name_obstack, (CHAR))
+/* Append a sized buffer to the end of the mangled representation. */
+#define write_chars(CHAR, LEN) \
+ obstack_grow (&G.name_obstack, (CHAR), (LEN))
+
/* Append a NUL-terminated string to the end of the mangled
representation. */
#define write_string(STRING) \
obstack_grow (&G.name_obstack, (STRING), strlen (STRING))
-/* Return the position at which the next character will be appended to
- the mangled representation. */
-#define mangled_position() \
- obstack_object_size (&G.name_obstack)
-
-/* Non-zero if NODE1 and NODE2 are both TREE_LIST nodes and have the
+/* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the
same purpose (context, which may be a type) and value (template
decl). See write_template_prefix for more information on what this
is used for. */
|| TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2)) \
&& TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
-/* Write out a signed quantity in base 10. */
-#define write_signed_number(NUMBER) \
- write_number (NUMBER, /*unsigned_p=*/0, 10)
-
/* Write out an unsigned quantity in base 10. */
#define write_unsigned_number(NUMBER) \
- write_number (NUMBER, /*unsigned_p=*/1, 10)
+ write_number ((NUMBER), /*unsigned_p=*/1, 10)
-/* If DECL is a template instance, return non-zero and, if
+/* If DECL is a template instance, return nonzero and, if
TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
Otherwise return zero. */
|| (TYPE_P (node)
&& TYPE_P (candidate)
&& same_type_p (node, candidate)))
- my_friendly_abort (20000524);
+ abort ();
}
}
#endif /* ENABLE_CHECKING */
dump_substitution_candidates ();
}
-/* Helper function for find_substitution. Returns non-zero if NODE,
+/* Helper function for find_substitution. Returns nonzero if NODE,
which may be a decl or a CLASS_TYPE, is a template-id with template
name of substitution_index[INDEX] in the ::std namespace. */
== subst_identifiers[index]));
}
-/* Helper function for find_substitution. Returns non-zero if NODE,
+/* Helper function for find_substitution. Returns nonzero if NODE,
which may be a decl or a CLASS_TYPE, is the template-id
::std::identifier<char>, where identifier is
substitution_index[INDEX]. */
candidates for entities appearing earlier in the same mangling
If a substitution is found, write its mangled representation and
- return non-zero. If none is found, just return zero. */
+ return nonzero. If none is found, just return zero. */
static int
find_substitution (node)
std::basic_string <char,
std::char_traits<char>,
std::allocator<char> > . */
- if (CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED
+ if (cp_type_quals (type) == TYPE_UNQUALIFIED
&& CLASSTYPE_USE_TEMPLATE (type))
{
tree args = CLASSTYPE_TI_ARGS (type);
/* Check for basic_{i,o,io}stream. */
if (TYPE_P (node)
- && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED
+ && cp_type_quals (type) == TYPE_UNQUALIFIED
&& CLASS_TYPE_P (type)
&& CLASSTYPE_USE_TEMPLATE (type)
&& CLASSTYPE_TEMPLATE_INFO (type) != NULL)
}
/* Now check the list of available substitutions for this mangling
- operation. */
+ operation. */
for (i = 0; i < size; ++i)
{
tree candidate = VARRAY_TREE (G.substitutions, i);
::= <nested-name>
::= <local-name>
- If IGNORE_LOCAL_SCOPE is non-zero, this production of <name> is
+ If IGNORE_LOCAL_SCOPE is nonzero, this production of <name> is
called from <local-name>, which mangles the enclosing scope
elsewhere and then uses this function to mangle just the part
underneath the function scope. So don't use the <local-name>
|| TREE_CODE (context) == FUNCTION_DECL)
write_unqualified_name (decl);
else
- my_friendly_abort (20000521);
+ abort ();
}
/* <unscoped-template-name> ::= <unscoped-name>
template = CLASSTYPE_TI_TEMPLATE (type);
else
/* Oops, not a template. */
- my_friendly_abort (20000524);
+ abort ();
/* For a member template, though, the template name for the
innermost name must have all the outer template levels
{
/* Conversion operator. Handle it right here.
<operator> ::= cv <type> */
+ tree type;
+ if (decl_is_template_id (decl, NULL))
+ {
+ tree fn_type = get_mostly_instantiated_function_type (decl, NULL,
+ NULL);
+ type = TREE_TYPE (fn_type);
+ }
+ else
+ type = TREE_TYPE (DECL_NAME (decl));
write_string ("cv");
- write_type (TREE_TYPE (DECL_NAME (decl)));
+ write_type (type);
}
else if (DECL_OVERLOADED_OPERATOR_P (decl))
{
write_identifier (IDENTIFIER_POINTER (identifier));
}
+/* 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
+ characters generated (these will be layed out in advance of where
+ 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;
+{
+ static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ unsigned digits = 0;
+
+ while (number)
+ {
+ unsigned HOST_WIDE_INT d = number / base;
+
+ *--buffer = base_digits[number - d * base];
+ digits++;
+ number = d;
+ }
+ while (digits < min_digits)
+ {
+ *--buffer = base_digits[0];
+ digits++;
+ }
+ return digits;
+}
+
/* Non-terminal <number>.
<number> ::= [n] </decimal integer/> */
int unsigned_p;
unsigned int base;
{
- static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- unsigned HOST_WIDE_INT n;
- unsigned HOST_WIDE_INT m = 1;
+ char buffer[sizeof (HOST_WIDE_INT) * 8];
+ unsigned count = 0;
if (!unsigned_p && (HOST_WIDE_INT) number < 0)
{
write_char ('n');
number = -((HOST_WIDE_INT) number);
}
-
- /* Figure out how many digits there are. */
- n = number;
- while (n >= base)
- {
- n /= base;
- m *= base;
- }
-
- /* Write them out. */
- while (m > 0)
- {
- int digit = number / m;
- write_char (digits[digit]);
- number -= digit * m;
- m /= base;
- }
-
- my_friendly_assert (number == 0, 20000407);
+ count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
+ write_chars (buffer + sizeof (buffer) - count, count);
}
-/* Write out an integeral CST in decimal. */
+/* Write out an integral CST in decimal. Most numbers are small, and
+ representable in a HOST_WIDE_INT. Occasionally we'll have numbers
+ bigger than that, which we must deal with. */
static inline void
write_integer_cst (cst)
tree cst;
{
- if (tree_int_cst_sgn (cst) >= 0)
+ int sign = tree_int_cst_sgn (cst);
+
+ if (TREE_INT_CST_HIGH (cst) + (sign < 0))
{
- if (TREE_INT_CST_HIGH (cst) != 0)
- sorry ("mangling very large integers");
- write_unsigned_number (TREE_INT_CST_LOW (cst));
+ /* A bignum. We do this in chunks, each of which fits in a
+ HOST_WIDE_INT. */
+ char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
+ unsigned HOST_WIDE_INT chunk;
+ unsigned chunk_digits;
+ char *ptr = buffer + sizeof (buffer);
+ unsigned count = 0;
+ tree n, base, type;
+ int done;
+
+ /* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
+ representable. */
+ chunk = 1000000000;
+ chunk_digits = 9;
+
+ if (sizeof (HOST_WIDE_INT) >= 8)
+ {
+ /* It is at least 64 bits, so 10^18 is representable. */
+ chunk_digits = 18;
+ chunk *= chunk;
+ }
+
+ type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst));
+ base = build_int_2 (chunk, 0);
+ n = build_int_2 (TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
+ TREE_TYPE (n) = TREE_TYPE (base) = type;
+
+ if (sign < 0)
+ {
+ write_char ('n');
+ n = fold (build1 (NEGATE_EXPR, type, n));
+ }
+ do
+ {
+ 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,
+ done ? 1 : chunk_digits);
+ ptr -= c;
+ count += c;
+ n = d;
+ }
+ while (!done);
+ write_chars (ptr, count);
+ }
+ else
+ {
+ /* A small num. */
+ unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
+
+ if (sign < 0)
+ {
+ write_char ('n');
+ low = -low;
+ }
+ write_unsigned_number (low);
}
- else
- write_signed_number (tree_low_cst (cst, 0));
}
/* Non-terminal <identifier>.
Currently, allocating constructors are never used.
- We also need to provide unique mangled names (which should never be
- exported) for the constructor that takes an in-charge parameter,
- and for a constructor whose name is the same as its class's name.
- We use "C*INTERNAL*" for these. */
+ We also need to provide mangled names for the maybe-in-charge
+ constructor, so we treat it here too. mangle_decl_string will
+ append *INTERNAL* to that, to make sure we never emit it. */
static void
write_special_name_constructor (ctor)
else if (DECL_BASE_CONSTRUCTOR_P (ctor))
write_string ("C2");
else
- my_friendly_abort (20001115);
+ abort ();
}
/* Handle destructor productions of non-terminal <special-name>.
- DTOR is a denstructor FUNCTION_DECL.
+ DTOR is a destructor FUNCTION_DECL.
<special-name> ::= D0 # deleting (in-charge) destructor
::= D1 # complete object (in-charge) destructor
- ::= D2 # base object (not-in-charge) destructor
+ ::= D2 # base object (not-in-charge) destructor
- We also need to provide unique mngled names for old-ABI
- destructors, sometimes. These should only be used internally. We
- use "D*INTERNAL*" for these. */
+ We also need to provide mangled names for the maybe-incharge
+ destructor, so we treat it here too. mangle_decl_string will
+ append *INTERNAL* to that, to make sure we never emit it. */
static void
write_special_name_destructor (dtor)
else if (DECL_BASE_DESTRUCTOR_P (dtor))
write_string ("D2");
else
- my_friendly_abort (20001115);
+ abort ();
}
/* Return the discriminator for ENTITY appearing inside
/* Assume this is the only local entity with this name. */
discriminator = 0;
- /* For now, we don't discriminate amongst local variables. */
- if (TREE_CODE (entity) != TYPE_DECL)
- return 0;
-
- /* Scan the list of local classes. */
- entity = TREE_TYPE (entity);
- for (type = &VARRAY_TREE (local_classes, 0); *type != entity; ++type)
- if (TYPE_IDENTIFIER (*type) == TYPE_IDENTIFIER (entity)
- && TYPE_CONTEXT (*type) == TYPE_CONTEXT (entity))
- ++discriminator;
+ if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity))
+ discriminator = DECL_DISCRIMINATOR (entity);
+ else if (TREE_CODE (entity) == TYPE_DECL)
+ {
+ /* Scan the list of local classes. */
+ entity = TREE_TYPE (entity);
+ for (type = &VARRAY_TREE (local_classes, 0); *type != entity; ++type)
+ if (TYPE_IDENTIFIER (*type) == TYPE_IDENTIFIER (entity)
+ && TYPE_CONTEXT (*type) == TYPE_CONTEXT (entity))
+ ++discriminator;
+ }
return discriminator;
}
write_discriminator (discriminator)
int discriminator;
{
- /* If discriminator is zero, don't write anything. Otherwise... */
+ /* If discriminator is zero, don't write anything. Otherwise... */
if (discriminator > 0)
{
write_char ('_');
- /* The number is omitted for discriminator == 1. Beyond 1, the
- numbering starts at 0. */
- if (discriminator > 1)
- write_unsigned_number (discriminator - 2);
+ write_unsigned_number (discriminator - 1);
}
}
write_type (type)
tree type;
{
- /* This gets set to non-zero if TYPE turns out to be a (possibly
+ /* This gets set to nonzero if TYPE turns out to be a (possibly
CV-qualified) builtin type. */
int is_builtin_type = 0;
since both the qualified and uqualified types are substitution
candidates. */
write_type (TYPE_MAIN_VARIANT (type));
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ /* It is important not to use the TYPE_MAIN_VARIANT of TYPE here
+ so that the cv-qualification of the element type is available
+ in write_array_type. */
+ write_array_type (type);
else
{
/* See through any typedefs. */
break;
case TYPENAME_TYPE:
- /* We handle TYPENAME_TYPEs like ordinary nested names. */
+ case UNBOUND_CLASS_TEMPLATE:
+ /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
+ ordinary nested names. */
write_nested_name (TYPE_STUB_DECL (type));
break;
- case ARRAY_TYPE:
- write_array_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. */
break;
default:
- my_friendly_abort (20000409);
+ abort ();
}
}
"In cases where multiple order-insensitive qualifiers are
present, they should be ordered 'K' (closest to the base type),
- 'V', 'r', and 'U' (farthest from the base type) ..." */
+ 'V', 'r', and 'U' (farthest from the base type) ..."
+
+ Note that we do not use cp_type_quals below; given "const
+ int[3]", the "const" is emitted with the "int", not with the
+ array. */
- if (CP_TYPE_RESTRICT_P (type))
+ if (TYPE_QUALS (type) & TYPE_QUAL_RESTRICT)
{
write_char ('r');
++num_qualifiers;
}
- if (CP_TYPE_VOLATILE_P (type))
+ if (TYPE_QUALS (type) & TYPE_QUAL_VOLATILE)
{
write_char ('V');
++num_qualifiers;
}
- if (CP_TYPE_CONST_P (type))
+ if (TYPE_QUALS (type) & TYPE_QUAL_CONST)
{
write_char ('K');
++num_qualifiers;
::= m # unsigned long
::= x # long long, __int64
::= y # unsigned long long, __int64
- ::= n # __int128 [not supported]
- ::= o # unsigned __int128 [not supported]
+ ::= n # __int128
+ ::= o # unsigned __int128
::= f # float
::= d # double
::= e # long double, __float80
write_char (integer_type_codes[itk]);
break;
}
-
+
if (itk == itk_none)
{
- tree t = type_for_mode (TYPE_MODE (type), TREE_UNSIGNED (type));
+ tree t = c_common_type_for_mode (TYPE_MODE (type),
+ TREE_UNSIGNED (type));
if (type == t)
- /* Couldn't find this type. */
- my_friendly_abort (20000408);
- type = t;
- goto iagain;
+ {
+ if (TYPE_PRECISION (type) == 128)
+ write_char (TREE_UNSIGNED (type) ? 'o' : 'n');
+ else
+ /* Couldn't find this type. */
+ abort ();
+ }
+ else
+ {
+ type = t;
+ goto iagain;
+ }
}
}
break;
else if (type == long_double_type_node)
write_char ('e');
else
- my_friendly_abort (20000409);
+ abort ();
break;
default:
- my_friendly_abort (20000509);
+ abort ();
}
}
{
MANGLE_TRACE_TREE ("function-type", type);
+ /* For a pointer to member function, the function type may have
+ cv-qualifiers, indicating the quals for the artificial 'this'
+ parameter. */
+ if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* The first parameter must be a POINTER_TYPE pointing to the
+ `this' parameter. */
+ tree this_type = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
+ write_CV_qualifiers_for_type (this_type);
+ }
+
write_char ('F');
/* We don't track whether or not a type is `extern "C"'. Note that
you can have an `extern "C"' function that does not have
}
/* Non-terminal <bare-function-type>. TYPE is a FUNCTION_TYPE or
- METHOD_TYPE. If INCLUDE_RETURN_TYPE is non-zero, the return value
+ METHOD_TYPE. If INCLUDE_RETURN_TYPE is nonzero, the return value
is mangled before the parameter types. If non-NULL, DECL is
FUNCTION_DECL for the function whose type is being emitted.
}
/* Write the mangled representation of a method parameter list of
- types given in PARM_TYPES. If METHOD_P is non-zero, the function is
+ types given in PARM_TYPES. If METHOD_P is nonzero, the function is
considered a non-static method, and the this parameter is omitted.
If non-NULL, DECL is the FUNCTION_DECL for the function whose
parameters are being emitted. */
code = TREE_CODE (expr);
}
- /* Handle template parameters. */
+ /* Skip NOP_EXPRs. They can occur when (say) a pointer argument
+ is converted (via qualification conversions) to another
+ type. */
+ while (TREE_CODE (expr) == NOP_EXPR
+ || TREE_CODE (expr) == NON_LVALUE_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ code = TREE_CODE (expr);
+ }
+
+ /* Handle template parameters. */
if (code == TEMPLATE_TYPE_PARM
|| code == TEMPLATE_TEMPLATE_PARM
|| code == BOUND_TEMPLATE_TEMPLATE_PARM
write_mangled_name (expr);
write_char ('E');
}
+ else if (TREE_CODE (expr) == SIZEOF_EXPR
+ && TYPE_P (TREE_OPERAND (expr, 0)))
+ {
+ write_string ("st");
+ write_type (TREE_OPERAND (expr, 0));
+ }
else
{
int i;
- /* Skip NOP_EXPRs. They can occur when (say) a pointer argument
- is converted (via qualification conversions) to another
- type. */
- while (TREE_CODE (expr) == NOP_EXPR)
- {
- expr = TREE_OPERAND (expr, 0);
- code = TREE_CODE (expr);
- }
-
/* When we bind a variable or function to a non-type template
argument with reference type, we create an ADDR_EXPR to show
the fact that the entity's address has been taken. But, we
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
- /* Handle pointers-to-members specially. */
- if (code == SCOPE_REF)
+ switch (code)
{
+ case CAST_EXPR:
+ write_type (TREE_TYPE (expr));
+ write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
+ break;
+
+ case STATIC_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ write_type (TREE_TYPE (expr));
+ write_expression (TREE_OPERAND (expr, 0));
+ break;
+
+
+ /* Handle pointers-to-members specially. */
+ case SCOPE_REF:
write_type (TREE_OPERAND (expr, 0));
if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
write_source_name (TREE_OPERAND (expr, 1));
else
write_encoding (TREE_OPERAND (expr, 1));
+ break;
+
+ default:
+ for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
+ write_expression (TREE_OPERAND (expr, i));
}
- else
- for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
- write_expression (TREE_OPERAND (expr, i));
}
}
else if (value == boolean_true_node)
write_unsigned_number (1);
else
- my_friendly_abort (20000412);
+ abort ();
}
else
write_integer_cst (value);
#endif
}
else
- my_friendly_abort (20000412);
+ abort ();
write_char ('E');
}
TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
TEMPLATE_PARM_INDEX.
- <template-param> ::= T </parameter/ number> _ */
+ <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. */
static void
write_template_param (parm)
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:
- my_friendly_abort (20000523);
+ abort ();
}
write_char ('T');
if (parm_index > 0)
write_unsigned_number (parm_index - 1);
write_char ('_');
+ if (G.internal_mangling_p)
+ {
+ if (parm_level > 0)
+ write_unsigned_number (parm_level - 1);
+ write_char ('_');
+ if (parm_type)
+ write_type (parm_type);
+ write_char ('_');
+ }
}
/* <template-template-param>
static inline void
start_mangling ()
{
+ VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
obstack_free (&G.name_obstack, obstack_base (&G.name_obstack));
}
finish_mangling ()
{
/* Clear all the substitutions. */
- VARRAY_POP_ALL (G.substitutions);
+ G.substitutions = 0;
/* Null-terminate the string. */
write_char ('\0');
init_mangle ()
{
gcc_obstack_init (&G.name_obstack);
- VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
/* Cache these identifiers for quick comparison when checking for
standard substitutions. */
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);
/* Create an identifier for the external mangled name of DECL. */
-tree
+void
mangle_decl (decl)
tree decl;
{
- return get_identifier (mangle_decl_string (decl));
+ tree id = get_identifier (mangle_decl_string (decl));
+
+ SET_DECL_ASSEMBLER_NAME (decl, id);
}
/* Generate the mangled representation of TYPE. */
tree type;
{
tree identifier;
+ const char *mangled_type;
+ char *op_name;
- /* Build the mangling for TYPE. */
- const char *mangled_type = mangle_type_string (type);
+ /* Build the internal mangling for TYPE. */
+ G.internal_mangling_p = true;
+ mangled_type = mangle_type_string (type);
+ G.internal_mangling_p = false;
+
/* Allocate a temporary buffer for the complete name. */
- char *op_name = (char *) xmalloc (strlen ("operator ")
- + strlen (mangled_type) + 1);
- /* Assemble the mangling. */
- strcpy (op_name, "operator ");
- strcat (op_name, mangled_type);
+ op_name = concat ("operator ", mangled_type, NULL);
/* Find or create an identifier. */
identifier = get_identifier (op_name);
/* Done with the temporary buffer. */
free (op_name);
+
+ /* It had better be a unique mangling for the type. */
+ my_friendly_assert (!IDENTIFIER_TYPENAME_P (identifier)
+ || same_type_p (type, TREE_TYPE (identifier)),
+ 20011230);
+
/* Set bits on the identifier so we know later it's a conversion. */
IDENTIFIER_OPNAME_P (identifier) = 1;
IDENTIFIER_TYPENAME_P (identifier) = 1;
{
start_mangling ();
write_string ("_ZGV");
- write_name (variable, /*ignore_local_scope=*/0);
+ if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
+ /* The name of a guard variable for a reference temporary should refer
+ to the reference, not the temporary. */
+ write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
+ else
+ write_name (variable, /*ignore_local_scope=*/0);
return get_identifier (finish_mangling ());
}
+/* Return an identifier for the name of a temporary variable used to
+ initialize a static reference. This isn't part of the ABI, but we might
+ as well call them something readable. */
+
+tree
+mangle_ref_init_variable (variable)
+ tree variable;
+{
+ start_mangling ();
+ write_string ("_ZGR");
+ write_name (variable, /*ignore_local_scope=*/0);
+ return get_identifier (finish_mangling ());
+}
\f
/* Foreign language type mangling section. */
else if (type == java_boolean_type_node)
write_char ('b');
else
- my_friendly_abort (20001207);
+ abort ();
}