This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [PATCH] C++: Fix three mangling bugs



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;
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]