This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] C++: Fix three mangling bugs
- To: chip at valinux dot com
- Subject: Re: [PATCH] C++: Fix three mangling bugs
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sat, 10 Jun 2000 20:57:35 -0700
- Cc: gcc-patches at gcc dot gnu dot org
- Organization: CodeSourcery, LLC
- References: <20000609153840.A443@perlsupport.com>
Chip --
I committed this patch. It's a synthesis of your work and mine, and
I think it fixes the bugs you reported.
Thanks,
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-06-09 Chip Salzenberg <chip@valinux.com>
Mark Mitchell <mark@codesourcery.com>
* mangle.c (write_number): Take an unsigned HOST_WIDE_INT as an
argument.
(write_signed_number): New macro.
(write_unsigned_number): Likewise.
(write_source_name): Use them.
(write_number): Handle signed and unsigned values.
(write_integer_cst): Use tree_int_cst_sgn, and use
write_unsigned_number or write_signed_number as appropriate.
(write_discriminator): Use write_unsigned_number or
write_signed_number as appropriate.
(write_template_arg_literal): Likewise.
(write_array_type): Use tree_low_cst.
(write_template_parm): Use write_unsigned_number or
write_signed_number as appropriate.
(write_substitution): Adjust call to write_number.
(write_type): Get the TYPE_MAIN_VARIANT before mangling it.
(write_expression): Handle non-type template arguments of
reference type correctly.
(mangle_thunk): Use write_signed_number.
2000-06-09 Chip Salzenberg <chip@valinux.com>
* mangle.c (find_substition): Don't mangle objects with typename
substitutions (e.g. "cin" as "Si").
Index: cp/mangle.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/mangle.c,v
retrieving revision 1.6
diff -c -p -r1.6 mangle.c
*** mangle.c 2000/06/09 16:45:22 1.6
--- mangle.c 2000/06/11 03:50:40
*************** static void write_template_prefix PARAMS
*** 157,163 ****
static void write_component PARAMS ((tree));
static void write_unqualified_name PARAMS ((tree));
static void write_source_name PARAMS ((tree));
! static void write_number PARAMS ((int, int));
static void write_integer_cst PARAMS ((tree));
static void write_identifier PARAMS ((char *));
static void write_special_name_constructor PARAMS ((tree));
--- 157,164 ----
static void write_component PARAMS ((tree));
static void write_unqualified_name PARAMS ((tree));
static void write_source_name PARAMS ((tree));
! static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
! unsigned int));
static void write_integer_cst PARAMS ((tree));
static void write_identifier PARAMS ((char *));
static void write_special_name_constructor PARAMS ((tree));
*************** static tree mangle_special_for_type PARA
*** 219,224 ****
--- 220,233 ----
|| 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)
+
/* Produce debugging output of current substitution candidates. */
static void
*************** find_substitution (node)
*** 441,447 ****
/* Check for std::basic_string. */
if (decl && is_std_substitution (decl, SUBID_BASIC_STRING))
{
! if (type)
{
/* If this is a type (i.e. a fully-qualified template-id),
check for
--- 450,456 ----
/* Check for std::basic_string. */
if (decl && is_std_substitution (decl, SUBID_BASIC_STRING))
{
! if (TYPE_P (node))
{
/* If this is a type (i.e. a fully-qualified template-id),
check for
*************** find_substitution (node)
*** 473,479 ****
}
/* Check for basic_{i,o,io}stream. */
! if (type
&& CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED
&& CLASS_TYPE_P (type)
&& CLASSTYPE_USE_TEMPLATE (type)
--- 482,488 ----
}
/* Check for basic_{i,o,io}stream. */
! if (TYPE_P (node)
&& CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED
&& CLASS_TYPE_P (type)
&& CLASSTYPE_USE_TEMPLATE (type)
*************** find_substitution (node)
*** 510,516 ****
}
/* Check for namespace std. */
! if (decl&& DECL_NAMESPACE_STD_P (decl))
{
write_string ("St");
return 1;
--- 519,525 ----
}
/* Check for namespace std. */
! if (decl && DECL_NAMESPACE_STD_P (decl))
{
write_string ("St");
return 1;
*************** find_substitution (node)
*** 518,524 ****
/* Now check the list of available substitutions for this mangling
operation. */
-
for (i = 0; i < size; ++i)
{
tree candidate = VARRAY_TREE (G.substitutions, i);
--- 527,532 ----
*************** static void
*** 604,611 ****
write_name (decl)
tree decl;
{
! tree context = CP_DECL_CONTEXT (decl);
MANGLE_TRACE_TREE ("name", decl);
/* Decls in :: or ::std scope are treated specially. */
--- 612,621 ----
write_name (decl)
tree decl;
{
! tree context;
+ context = CP_DECL_CONTEXT (decl);
+
MANGLE_TRACE_TREE ("name", decl);
/* Decls in :: or ::std scope are treated specially. */
*************** write_source_name (identifier)
*** 913,919 ****
if (IDENTIFIER_TEMPLATE (identifier))
identifier = IDENTIFIER_TEMPLATE (identifier);
! write_number (IDENTIFIER_LENGTH (identifier), 10);
write_identifier (IDENTIFIER_POINTER (identifier));
}
--- 923,929 ----
if (IDENTIFIER_TEMPLATE (identifier))
identifier = IDENTIFIER_TEMPLATE (identifier);
! write_unsigned_number (IDENTIFIER_LENGTH (identifier));
write_identifier (IDENTIFIER_POINTER (identifier));
}
*************** write_source_name (identifier)
*** 922,941 ****
<number> ::= [n] </decimal integer/> */
static void
! write_number (number, base)
! int number;
! int base;
{
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
! int n;
! int m = 1;
! if (number < 0)
{
write_char ('n');
! number = -number;
}
n = number;
while (n >= base)
{
--- 932,953 ----
<number> ::= [n] </decimal integer/> */
static void
! write_number (number, unsigned_p, base)
! unsigned HOST_WIDE_INT number;
! int unsigned_p;
! unsigned int base;
{
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
! unsigned HOST_WIDE_INT n;
! unsigned HOST_WIDE_INT m = 1;
! 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)
{
*************** write_number (number, base)
*** 943,948 ****
--- 955,961 ----
m *= base;
}
+ /* Write them out. */
while (m > 0)
{
int digit = number / m;
*************** static inline void
*** 960,966 ****
write_integer_cst (cst)
tree cst;
{
! write_number (tree_low_cst (cst, TREE_UNSIGNED (TREE_TYPE (cst))), 10);
}
/* Non-terminal <identifier>.
--- 973,986 ----
write_integer_cst (cst)
tree cst;
{
! if (tree_int_cst_sgn (cst) >= 0)
! {
! if (TREE_INT_CST_HIGH (cst) != 0)
! sorry ("mangling very large integers");
! write_unsigned_number (TREE_INT_CST_LOW (cst));
! }
! else
! write_signed_number (tree_low_cst (cst, 0));
}
/* Non-terminal <identifier>.
*************** write_discriminator (discriminator)
*** 1086,1092 ****
/* The number is omitted for discriminator == 1. Beyond 1, the
numbering starts at 0. */
if (discriminator > 1)
! write_number (discriminator - 2, 10);
}
}
--- 1106,1112 ----
/* The number is omitted for discriminator == 1. Beyond 1, the
numbering starts at 0. */
if (discriminator > 1)
! write_unsigned_number (discriminator - 2);
}
}
*************** write_type (type)
*** 1151,1157 ****
if (find_substitution (type))
return;
!
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
--- 1171,1177 ----
if (find_substitution (type))
return;
!
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
*************** write_type (type)
*** 1159,1243 ****
candidates. */
write_type (TYPE_MAIN_VARIANT (type));
else
! switch (TREE_CODE (type))
! {
! case VOID_TYPE:
! case BOOLEAN_TYPE:
! case INTEGER_TYPE: /* Includes wchar_t. */
! case REAL_TYPE:
! /* If this is a typedef, TYPE may not be one of
! the standard builtin type nodes, but an alias of one. Use
! TYPE_MAIN_VARIANT to get to the underlying builtin type. */
! write_builtin_type (TYPE_MAIN_VARIANT (type));
! ++is_builtin_type;
! break;
!
! case COMPLEX_TYPE:
! write_char ('C');
! write_type (TREE_TYPE (type));
! break;
!
! case FUNCTION_TYPE:
! case METHOD_TYPE:
! write_function_type (type, 1);
! break;
!
! case UNION_TYPE:
! case RECORD_TYPE:
! case ENUMERAL_TYPE:
! /* A pointer-to-member function is represented as a special
! RECORD_TYPE, so check for this first. */
! if (TYPE_PTRMEMFUNC_P (type))
! write_pointer_to_member_type (type);
! else
! write_class_enum_type (type);
! break;
!
! case TYPENAME_TYPE:
! /* We handle TYPENAME_TYPEs 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. */
! if (TYPE_PTRMEM_P (type))
! write_pointer_to_member_type (type);
! else
! {
! write_char ('P');
! write_type (TREE_TYPE (type));
! }
! break;
!
! case REFERENCE_TYPE:
! write_char ('R');
! write_type (TREE_TYPE (type));
! break;
!
! case TEMPLATE_TYPE_PARM:
! case TEMPLATE_PARM_INDEX:
! write_template_param (type);
! break;
!
! case TEMPLATE_TEMPLATE_PARM:
! write_template_template_param (type);
! if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type))
! write_template_args
! (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
! break;
!
! case OFFSET_TYPE:
! write_pointer_to_member_type (build_pointer_type (type));
! break;
! default:
! my_friendly_abort (20000409);
! }
/* Types other than builtin types are substitution candidates. */
if (!is_builtin_type)
--- 1179,1268 ----
candidates. */
write_type (TYPE_MAIN_VARIANT (type));
else
! {
! /* See through any typedefs. */
! type = TYPE_MAIN_VARIANT (type);
! switch (TREE_CODE (type))
! {
! case VOID_TYPE:
! case BOOLEAN_TYPE:
! case INTEGER_TYPE: /* Includes wchar_t. */
! case REAL_TYPE:
! /* If this is a typedef, TYPE may not be one of
! the standard builtin type nodes, but an alias of one. Use
! TYPE_MAIN_VARIANT to get to the underlying builtin type. */
! write_builtin_type (TYPE_MAIN_VARIANT (type));
! ++is_builtin_type;
! break;
!
! case COMPLEX_TYPE:
! write_char ('C');
! write_type (TREE_TYPE (type));
! break;
!
! case FUNCTION_TYPE:
! case METHOD_TYPE:
! write_function_type (type, 1);
! break;
!
! case UNION_TYPE:
! case RECORD_TYPE:
! case ENUMERAL_TYPE:
! /* A pointer-to-member function is represented as a special
! RECORD_TYPE, so check for this first. */
! if (TYPE_PTRMEMFUNC_P (type))
! write_pointer_to_member_type (type);
! else
! write_class_enum_type (type);
! break;
!
! case TYPENAME_TYPE:
! /* We handle TYPENAME_TYPEs 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. */
! if (TYPE_PTRMEM_P (type))
! write_pointer_to_member_type (type);
! else
! {
! write_char ('P');
! write_type (TREE_TYPE (type));
! }
! break;
!
! case REFERENCE_TYPE:
! write_char ('R');
! write_type (TREE_TYPE (type));
! break;
!
! case TEMPLATE_TYPE_PARM:
! case TEMPLATE_PARM_INDEX:
! write_template_param (type);
! break;
!
! case TEMPLATE_TEMPLATE_PARM:
! write_template_template_param (type);
! if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type))
! write_template_args
! (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
! break;
!
! case OFFSET_TYPE:
! write_pointer_to_member_type (build_pointer_type (type));
! break;
!
! default:
! my_friendly_abort (20000409);
! }
! }
/* Types other than builtin types are substitution candidates. */
if (!is_builtin_type)
*************** write_expression (expr)
*** 1564,1571 ****
if (TREE_CODE (expr) == ADDR_EXPR
&& TREE_TYPE (expr)
&& TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
! expr = TREE_OPERAND (expr, 0);
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
--- 1589,1605 ----
if (TREE_CODE (expr) == ADDR_EXPR
&& TREE_TYPE (expr)
&& TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
! {
! expr = TREE_OPERAND (expr, 0);
! if (DECL_P (expr))
! {
! write_expression (expr);
! return;
! }
+ code = TREE_CODE (expr);
+ }
+
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
*************** write_template_arg_literal (value)
*** 1610,1618 ****
if (same_type_p (type, boolean_type_node))
{
if (value == boolean_false_node || integer_zerop (value))
! write_number (0, 10);
else if (value == boolean_true_node)
! write_number (1, 10);
else
my_friendly_abort (20000412);
}
--- 1644,1652 ----
if (same_type_p (type, boolean_type_node))
{
if (value == boolean_false_node || integer_zerop (value))
! write_unsigned_number (0);
else if (value == boolean_true_node)
! write_unsigned_number (1);
else
my_friendly_abort (20000412);
}
*************** write_template_arg_literal (value)
*** 1633,1639 ****
size_t i;
for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
write_number (((unsigned char *)
! &TREE_REAL_CST (value))[i], 16);
#endif
}
else
--- 1667,1675 ----
size_t i;
for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
write_number (((unsigned char *)
! &TREE_REAL_CST (value))[i],
! /*unsigned_p=*/1,
! 16);
#endif
}
else
*************** write_array_type (type)
*** 1732,1738 ****
array. */
max = TYPE_MAX_VALUE (index_type);
if (TREE_CODE (max) == INTEGER_CST)
! write_number (TREE_INT_CST_LOW (max) + 1, 10);
else
write_expression (TREE_OPERAND (max, 0));
}
--- 1768,1774 ----
array. */
max = TYPE_MAX_VALUE (index_type);
if (TREE_CODE (max) == INTEGER_CST)
! write_unsigned_number (tree_low_cst (max, 1));
else
write_expression (TREE_OPERAND (max, 0));
}
*************** write_template_param (parm)
*** 1786,1792 ****
/* NUMBER as it appears in the mangling is (-1)-indexed, with the
earliest template param denoted by `_'. */
if (parm_index > 0)
! write_number (parm_index - 1, 10);
write_char ('_');
}
--- 1822,1828 ----
/* 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_substitution (seq_id)
*** 1831,1837 ****
write_char ('S');
if (seq_id > 0)
! write_number (seq_id - 1, 36);
write_char ('_');
}
--- 1867,1873 ----
write_char ('S');
if (seq_id > 0)
! write_number (seq_id - 1, /*unsigned=*/1, 36);
write_char ('_');
}
*************** mangle_thunk (fn_decl, offset, vcall_off
*** 2063,2076 ****
write_char ('h');
/* For either flavor, write the offset to this. */
! write_number (offset, 10);
write_char ('_');
/* For a virtual thunk, add the vcall offset. */
if (vcall_offset != 0)
{
/* Virtual thunk. Write the vcall offset and base type name. */
! write_number (vcall_offset, 10);
write_char ('_');
}
--- 2099,2112 ----
write_char ('h');
/* For either flavor, write the offset to this. */
! write_signed_number (offset);
write_char ('_');
/* For a virtual thunk, add the vcall offset. */
if (vcall_offset != 0)
{
/* Virtual thunk. Write the vcall offset and base type name. */
! write_signed_number (vcall_offset);
write_char ('_');
}
Index: testsuite/g++.old-deja/g++.other/crash19.C
===================================================================
RCS file: crash19.C
diff -N crash19.C
*** /dev/null Tue May 5 13:32:27 1998
--- crash19.C Sat Jun 10 20:50:59 2000
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+
+ template <class T>
+ struct S {};
+
+ struct X {};
+
+ void f () {
+ typedef X Y;
+ S<Y> s;
+ }