(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