(C++) mangling fixes
Jason Merrill
jason@cygnus.com
Sun Mar 14 01:29:00 GMT 1999
We were failing to see through typedefs when checking for repeated types in
some cases; see g++.other/mangle1.C. Also see that testcase for how to
write mangling tests; everyone should feel free to write others so that we
can finally nail down the mangling code.
The problem was that canonical_type_variant only works on one-level types;
a pointer to a typedef type, for instance, is unaffected. So I've torn out
the code that set and checked TREE_USED, and changed pointer equality tests
to use same_type_p.
1999-03-13 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (duplicate_decls): Use same_type_p.
* method.c (try_old_backref): Renamed from flush_repeats. Use
same_type_p. Don't try to handle repeats. Return success.
(is_back_referenceable_type): Return 0 if TYPE_FOR_JAVA. Support
calls from old-style code, too.
(check_ktype): Use same_type_p.
(check_btype): Use same_type_p. Don't pull out TYPE_MAIN_VARIANT.
(build_qualified_name): Simplify logic.
(build_mangled_name_for_type_with_Gcode): Remove call to
type_canonical_variant.
(process_overload_item): Strip typedefs and quals at the top.
(build_mangled_name): Likewise. Remove support for old-style
repeats, which have been disabled since 2.7.2. Don't mess with
TREE_USED.
(build_decl_overload_real): Don't mess with TREE_USED.
Index: method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.92
diff -c -p -r1.92 method.c
*** method.c 1999/03/09 23:02:37 1.92
--- method.c 1999/03/14 09:28:41
*************** static char *scratch_firstobj;
*** 57,63 ****
static void icat PROTO((HOST_WIDE_INT));
static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
! static void flush_repeats PROTO((int, tree));
static void build_overload_identifier PROTO((tree));
static void build_overload_nested_name PROTO((tree));
static void build_overload_int PROTO((tree, int));
--- 57,63 ----
static void icat PROTO((HOST_WIDE_INT));
static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
! static int try_old_backref PROTO((tree));
static void build_overload_identifier PROTO((tree));
static void build_overload_nested_name PROTO((tree));
static void build_overload_int PROTO((tree, int));
*************** dicat (lo, hi)
*** 299,326 ****
OB_PUTC ('0' + ulo);
}
! static __inline void
! flush_repeats (nrepeats, type)
! int nrepeats;
tree type;
{
int tindex = 0;
! while (typevec[tindex] != type)
! tindex++;
! if (nrepeats > 1)
! {
! OB_PUTC ('N');
! icat (nrepeats);
! if (nrepeats > 9)
! OB_PUTC ('_');
! }
! else
! OB_PUTC ('T');
icat (tindex);
if (tindex > 9)
OB_PUTC ('_');
}
/* Returns nonzero iff this is a type to which we will want to make
--- 299,331 ----
OB_PUTC ('0' + ulo);
}
! /* Old mangling style: If TYPE has already been used in the parameter list,
! emit a backward reference and return non-zero; otherwise, return 0. */
!
! static __inline int
! try_old_backref (type)
tree type;
{
int tindex = 0;
! if (! is_back_referenceable_type (type))
! return 0;
! /* The entry for this parm is at maxtype-1, so don't look there for
! something to repeat. */
! for (tindex = 0; tindex < maxtype - 1; ++tindex)
! if (same_type_p (typevec[tindex], type))
! break;
!
! if (tindex == maxtype - 1)
! return 0;
!
! OB_PUTC ('T');
icat (tindex);
if (tindex > 9)
OB_PUTC ('_');
+
+ return 1;
}
/* Returns nonzero iff this is a type to which we will want to make
*************** static int
*** 330,337 ****
is_back_referenceable_type (type)
tree type;
{
! if (btypelist == NULL)
! /* We're not generating any back-references. */
return 0;
switch (TREE_CODE (type))
--- 335,342 ----
is_back_referenceable_type (type)
tree type;
{
! /* For some reason, the Java folks don't want back refs on these. */
! if (TYPE_FOR_JAVA (type))
return 0;
switch (TREE_CODE (type))
*************** issue_nrepeats (nrepeats, type)
*** 376,384 ****
OB_PUTC ('_');
}
}
- /* Check to see if a tree node has been entered into the Kcode typelist */
- /* if not, add it. Return -1 if it isn't found, otherwise return the index */
static int
check_ktype (node, add)
tree node;
--- 381,391 ----
OB_PUTC ('_');
}
}
+
+ /* Check to see if a tree node has been entered into the Kcode typelist.
+ If not, add it. Returns -1 if it isn't found, otherwise returns the
+ index. */
static int
check_ktype (node, add)
tree node;
*************** check_ktype (node, add)
*** 395,404 ****
for (x=0; x < maxktype; x++)
{
! if (localnode == ktypelist[x])
! return x ;
}
! /* Didn't find it, so add it here */
if (add)
{
if (maxksize <= maxktype)
--- 402,411 ----
for (x=0; x < maxktype; x++)
{
! if (same_type_p (localnode, ktypelist[x]))
! return x;
}
! /* Didn't find it, so add it here. */
if (add)
{
if (maxksize <= maxktype)
*************** build_overload_value (type, value, in_te
*** 864,870 ****
/* Add encodings for the declaration of template template parameters.
! PARMLIST must be a TREE_VEC */
static void
build_template_template_parm_names (parmlist)
--- 871,877 ----
/* Add encodings for the declaration of template template parameters.
! PARMLIST must be a TREE_VEC. */
static void
build_template_template_parm_names (parmlist)
*************** build_template_parm_names (parmlist, arg
*** 921,929 ****
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
! /* This parameter is a template. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
! /* Output parameter declaration, argument index and level */
build_mangled_name_for_type (arg);
else
{
--- 928,936 ----
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
! /* This parameter is a template. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
! /* Output parameter declaration, argument index and level. */
build_mangled_name_for_type (arg);
else
{
*************** build_template_parm_names (parmlist, arg
*** 931,937 ****
and template name */
OB_PUTC ('z');
! build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
icat (IDENTIFIER_LENGTH (DECL_NAME (arg)));
OB_PUTID (DECL_NAME (arg));
}
--- 938,945 ----
and template name */
OB_PUTC ('z');
! build_template_template_parm_names
! (DECL_INNERMOST_TEMPLATE_PARMS (parm));
icat (IDENTIFIER_LENGTH (DECL_NAME (arg)));
OB_PUTID (DECL_NAME (arg));
}
*************** build_qualified_name (decl)
*** 1012,1026 ****
}
context = decl;
! /* if we can't find a Ktype, do it the hard way */
if (check_ktype (context, FALSE) == -1)
{
! /* count type and namespace scopes */
! while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace)
{
i += 1;
! context = DECL_CONTEXT (context);
! if (check_ktype (context, FALSE) != -1) /* found it! */
break;
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
--- 1020,1037 ----
}
context = decl;
! /* If we can't find a Ktype, do it the hard way. */
if (check_ktype (context, FALSE) == -1)
{
! /* Count type and namespace scopes. */
! while (1)
{
+ context = CP_DECL_CONTEXT (context);
+ if (context == global_namespace)
+ break;
i += 1;
! if (check_ktype (context, FALSE) != -1)
! /* Found one! */
break;
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
*************** build_mangled_name_for_type_with_Gcode (
*** 1047,1053 ****
{
if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- type = canonical_type_variant (type);
process_modifiers (type);
process_overload_item (type, extra_Gcode);
}
--- 1058,1063 ----
*************** build_mangled_name (parmtypes, begin, en
*** 1111,1181 ****
for (; parmtypes && parmtypes != void_list_node;
parmtypes = TREE_CHAIN (parmtypes))
{
! tree parmtype = canonical_type_variant (TREE_VALUE (parmtypes));
if (old_style_repeats)
{
/* Every argument gets counted. */
my_friendly_assert (maxtype < typevec_size, 387);
typevec[maxtype++] = parmtype;
}
!
! if (parmtype == last_type)
{
! if (flag_do_squangling
! || (old_style_repeats && TREE_USED (parmtype)
! && !TYPE_FOR_JAVA (parmtype)))
{
/* The next type is the same as this one. Keep
track of the repetition, and output the repeat
count later. */
nrepeats++;
continue;
- }
- }
- else if (nrepeats != 0)
- {
- /* Indicate how many times the previous parameter was
- repeated. */
- if (old_style_repeats)
- flush_repeats (nrepeats, last_type);
- else
- issue_nrepeats (nrepeats, last_type);
- nrepeats = 0;
- }
-
- last_type = parmtype;
-
- if (old_style_repeats)
- {
- if (nrepeats)
- {
- flush_repeats (nrepeats, last_type);
- nrepeats = 0;
}
!
! if (TREE_USED (parmtype))
{
! #if 0
! /* We can turn this on at some point when we want
! improved symbol mangling. */
! nrepeats++;
! #else
! /* This is bug compatible with 2.7.x */
! flush_repeats (nrepeats, parmtype);
! #endif
nrepeats = 0;
- continue;
}
-
- /* Only cache types which take more than one character. */
- if ((parmtype != TYPE_MAIN_VARIANT (parmtype)
- || (TREE_CODE (parmtype) != INTEGER_TYPE
- && TREE_CODE (parmtype) != REAL_TYPE))
- && ! TYPE_FOR_JAVA (parmtype))
- TREE_USED (parmtype) = 1;
}
/* Output the PARMTYPE. */
build_mangled_name_for_type_with_Gcode (parmtype, 1);
}
--- 1121,1166 ----
for (; parmtypes && parmtypes != void_list_node;
parmtypes = TREE_CHAIN (parmtypes))
{
! /* We used to call canonical_type_variant here, but that isn't
! good enough; it doesn't handle pointers to typedef types. So
! we can't just set TREE_USED to say we've seen a type already;
! we have to check each of the earlier types with same_type_p. */
! tree parmtype = TREE_VALUE (parmtypes);
if (old_style_repeats)
{
+ /* Note that for bug-compatibility with 2.7.2, we can't build
+ up repeats. So we call try_old_backref (formerly
+ flush_repeats) every round, and only emit Tn codes. */
+
/* Every argument gets counted. */
my_friendly_assert (maxtype < typevec_size, 387);
typevec[maxtype++] = parmtype;
}
! else if (flag_do_squangling)
{
! if (last_type && same_type_p (parmtype, last_type))
{
/* The next type is the same as this one. Keep
track of the repetition, and output the repeat
count later. */
nrepeats++;
continue;
}
! else if (nrepeats != 0)
{
! /* Indicate how many times the previous parameter was
! repeated. */
! issue_nrepeats (nrepeats, last_type);
nrepeats = 0;
}
}
+
+ last_type = parmtype;
+ if (old_style_repeats && try_old_backref (parmtype))
+ continue;
+
/* Output the PARMTYPE. */
build_mangled_name_for_type_with_Gcode (parmtype, 1);
}
*************** build_mangled_name (parmtypes, begin, en
*** 1184,1193 ****
necessary. */
if (nrepeats != 0)
{
! if (old_style_repeats)
! flush_repeats (nrepeats, last_type);
! else
! issue_nrepeats (nrepeats, last_type);
nrepeats = 0;
}
--- 1169,1175 ----
necessary. */
if (nrepeats != 0)
{
! issue_nrepeats (nrepeats, last_type);
nrepeats = 0;
}
*************** check_btype (type)
*** 1243,1254 ****
if (!is_back_referenceable_type (type))
return 0;
- /* We assume that our caller has put out any necessary
- qualifiers. */
- type = TYPE_MAIN_VARIANT (type);
-
for (x = 0; x < maxbtype; x++)
! if (type == btypelist[x])
{
OB_PUTC ('B');
icat (x);
--- 1225,1232 ----
if (!is_back_referenceable_type (type))
return 0;
for (x = 0; x < maxbtype; x++)
! if (same_type_p (type, btypelist[x]))
{
OB_PUTC ('B');
icat (x);
*************** process_overload_item (parmtype, extra_G
*** 1279,1284 ****
--- 1257,1270 ----
{
numeric_output_need_bar = 0;
+ /* Our caller should have already handed any qualifiers, so pull out the
+ TYPE_MAIN_VARIANT to avoid typedef confusion. Except we can't do that
+ for arrays, because they are transparent to qualifiers. Sigh. */
+ if (TREE_CODE (parmtype) == ARRAY_TYPE)
+ parmtype = canonical_type_variant (parmtype);
+ else
+ parmtype = TYPE_MAIN_VARIANT (parmtype);
+
/* These tree types are considered modifiers for B code squangling,
and therefore should not get entries in the Btypelist. They are,
however, repeatable types. */
*************** process_overload_item (parmtype, extra_G
*** 1382,1388 ****
}
case INTEGER_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == integer_type_node
|| parmtype == unsigned_type_node
|| parmtype == java_int_type_node)
--- 1368,1373 ----
*************** process_overload_item (parmtype, extra_G
*** 1431,1437 ****
break;
case REAL_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == long_double_type_node)
OB_PUTC ('r');
else if (parmtype == double_type_node
--- 1416,1421 ----
*************** build_decl_overload_real (dname, parms,
*** 1609,1620 ****
OB_PUTC ('v');
else
{
! if (!flag_do_squangling) /* Allocate typevec array. */
{
maxtype = 0;
typevec_size = list_length (parms);
if (!for_method && current_namespace != global_namespace)
! /* the namespace of a global function needs one slot */
typevec_size++;
typevec = (tree *)alloca (typevec_size * sizeof (tree));
}
--- 1593,1605 ----
OB_PUTC ('v');
else
{
! if (!flag_do_squangling)
{
+ /* Allocate typevec array. */
maxtype = 0;
typevec_size = list_length (parms);
if (!for_method && current_namespace != global_namespace)
! /* The namespace of a global function needs one slot. */
typevec_size++;
typevec = (tree *)alloca (typevec_size * sizeof (tree));
}
*************** build_decl_overload_real (dname, parms,
*** 1635,1646 ****
{
my_friendly_assert (maxtype < typevec_size, 387);
typevec[maxtype++] = this_type;
- TREE_USED (this_type) = 1;
-
- /* By setting up PARMS in this way, the loop below will
- automatically clear TREE_USED on THIS_TYPE. */
- parms = temp_tree_cons (NULL_TREE, this_type,
- TREE_CHAIN (parms));
}
if (TREE_CHAIN (parms))
--- 1620,1625 ----
*************** build_decl_overload_real (dname, parms,
*** 1661,1680 ****
build_mangled_name (parms, 0, 0);
}
! if (!flag_do_squangling) /* Deallocate typevec array */
! {
! tree t = parms;
! typevec = NULL;
! while (t)
! {
! tree temp = TREE_VALUE (t);
! TREE_USED (temp) = 0;
! /* clear out the type variant in case we used it */
! temp = canonical_type_variant (temp);
! TREE_USED (temp) = 0;
! t = TREE_CHAIN (t);
! }
! }
}
if (ret_type != NULL_TREE && for_method != 2)
--- 1640,1648 ----
build_mangled_name (parms, 0, 0);
}
! if (!flag_do_squangling)
! /* Deallocate typevec array. */
! typevec = NULL;
}
if (ret_type != NULL_TREE && for_method != 2)
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.322
diff -c -p -r1.322 decl.c
*** decl.c 1999/03/13 01:16:31 1.322
--- decl.c 1999/03/14 09:28:41
*************** duplicate_decls (newdecl, olddecl)
*** 3242,3248 ****
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
! if (newtype != canonical_type_variant (oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
--- 3242,3248 ----
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
! if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
More information about the Gcc-patches
mailing list