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]

C++ PATCH: fix mangling and demangling bugs


This patch fixes several mangling-related bugs.  It corrects an
ambiguity in the mangling grammar, and corrects a few outdated mangled
names in libio.

Commited on approval from Mark Mitchell.


in libiberty/ChangeLog:

	* cp-demangle.c (demangle_encoding): Accept no substitutions.
	(demangle_name): Handle <substitution> followed by
	<unqualified-template-name>.
	(demangle_type): Follow special substitutions with
	<class-enum-type>
	(demangle_subtitution): Set template_p for special substitutions.
	(main): Fix typos.

in gcc/cp/ChangeLog:

	* mangle.c (find_substitution): Use same_type_p.
	(write_encoding): Don't check for substitutions.

in libio/ChangeLog:

	* libioP.h (VTABLE_LABEL): Update for new vtable mangling.
	* stdstrbufs.cc (filebuf_vtable): Likewise.
	(stdiobuf_vtable): Likewise.


Index: cp-demangle.c
===================================================================
RCS file: /cvs/gcc/egcs/libiberty/cp-demangle.c,v
retrieving revision 1.9
diff -c -p -r1.9 cp-demangle.c
*** cp-demangle.c	2000/06/28 06:08:27	1.9
--- cp-demangle.c	2000/06/29 03:25:26
*************** demangle_mangled_name (dm)
*** 902,917 ****
  
      <encoding>		::= <function name> <bare-function-type>
  			::= <data name>
! 			::= <substitution>  */
  
  static status_t
  demangle_encoding (dm)
       demangling_t dm;
  {
    int template_p;
-   int special_std_substitution;
    int start_position;
-   int start = substitution_start (dm);
    template_arg_list_t old_arg_list = current_template_arg_list (dm);
    char peek = peek_char (dm);
  
--- 902,915 ----
  
      <encoding>		::= <function name> <bare-function-type>
  			::= <data name>
! 			::= <special-name>  */
  
  static status_t
  demangle_encoding (dm)
       demangling_t dm;
  {
    int template_p;
    int start_position;
    template_arg_list_t old_arg_list = current_template_arg_list (dm);
    char peek = peek_char (dm);
  
*************** demangle_encoding (dm)
*** 921,938 ****
       function, we'll have to insert the return type here.  */
    start_position = result_length (dm);
  
!   if (peek == 'S')
!     {
!       RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
! 					      &special_std_substitution));
!       if (special_std_substitution)
! 	{
! 	  /* This was the magic `std::' substitution.  */
! 	  RETURN_IF_ERROR (result_append (dm, "::"));
! 	  RETURN_IF_ERROR (demangle_encoding (dm));
! 	}
!     }
!   else if (peek == 'G' || peek == 'T')
      RETURN_IF_ERROR (demangle_special_name (dm));
    else
      {
--- 919,925 ----
       function, we'll have to insert the return type here.  */
    start_position = result_length (dm);
  
!   if (peek == 'G' || peek == 'T')
      RETURN_IF_ERROR (demangle_special_name (dm));
    else
      {
*************** demangle_encoding (dm)
*** 955,963 ****
  	    RETURN_IF_ERROR 
  	      (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE)); 
  	}
- 
-       RETURN_IF_ERROR (substitution_add (dm, start, template_p, 
- 					 NOT_TEMPLATE_PARM));
      }
  
    /* Pop off template argument lists that were built during the
--- 942,947 ----
*************** demangle_name (dm, template_p)
*** 1004,1011 ****
  
      case 'S':
        /* The `St' substitution allows a name nested in std:: to appear
! 	 without being enclosed in a nested name.
! 	   <name> ::= St <unqualified-name>     # ::std::  */
        if (peek_char_next (dm) == 't') 
  	{
  	  (void) next_char (dm);
--- 988,994 ----
  
      case 'S':
        /* The `St' substitution allows a name nested in std:: to appear
! 	 without being enclosed in a nested name.  */
        if (peek_char_next (dm) == 't') 
  	{
  	  (void) next_char (dm);
*************** demangle_name (dm, template_p)
*** 1026,1031 ****
--- 1009,1022 ----
  	      RETURN_IF_ERROR (demangle_name (dm, template_p));
  	    }
  	}
+       /* Check if a template argument list immediately follows.
+ 	 If so, then we just demangled an <unqualified-template-name>.  */
+       if (peek_char (dm) == 'I') 
+ 	{
+ 	  RETURN_IF_ERROR (substitution_add (dm, start, 0, 
+ 					     NOT_TEMPLATE_PARM));
+ 	  RETURN_IF_ERROR (demangle_template_args (dm));
+ 	}
        break;
  
      default:
*************** demangle_type (dm)
*** 1947,1952 ****
--- 1938,1944 ----
  {
    int start = substitution_start (dm);
    char peek = peek_char (dm);
+   char peek_next;
    int template_p = 0;
    int special_std_substitution;
    int is_builtin_type = 0;
*************** demangle_type (dm)
*** 2016,2030 ****
  	break;
  
        case 'S':
! 	RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
! 						&special_std_substitution));
! 	if (special_std_substitution)
! 	  {
! 	    /* This was the magic `std::' substitution.  What follows
! 	       must be a class name in that namespace.  */
! 	    RETURN_IF_ERROR (result_append (dm, "::"));
! 	    RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
! 	  }
  	break;
  
        case 'P':
--- 2008,2023 ----
  	break;
  
        case 'S':
! 	/* First check if this is a special substitution.  If it is,
! 	   this is a <class-enum-type>.  Special substitutions have a
! 	   letter following the `S'; other substitutions have a digit
! 	   or underscore.  */
! 	peek_next = peek_char_next (dm);
! 	if (IS_DIGIT (peek_next) || peek_next == '_')
! 	  RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
! 						  &special_std_substitution));
! 	else
! 	  demangle_class_enum_type (dm, &template_p);
  	break;
  
        case 'P':
*************** demangle_substitution (dm, template_p, s
*** 2792,2802 ****
--- 2785,2797 ----
  	case 'a':
  	  RETURN_IF_ERROR (result_append (dm, "std::allocator"));
  	  new_last_source_name = "allocator";
+ 	  *template_p = 1;
  	  break;
  
  	case 'b':
  	  RETURN_IF_ERROR (result_append (dm, "std::basic_string"));
  	  new_last_source_name = "basic_string";
+ 	  *template_p = 1;
  	  break;
  	  
  	case 's':
*************** demangle_substitution (dm, template_p, s
*** 2810,2815 ****
--- 2805,2811 ----
  	      RETURN_IF_ERROR (result_append (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
  	      new_last_source_name = "basic_string";
  	    }
+ 	  *template_p = 0;
  	  break;
  
  	case 'i':
*************** demangle_substitution (dm, template_p, s
*** 2823,2828 ****
--- 2819,2825 ----
  	      RETURN_IF_ERROR (result_append (dm, "std::basic_istream<char, std::char_traints<char> >"));
  	      new_last_source_name = "basic_istream";
  	    }
+ 	  *template_p = 0;
  	  break;
  
  	case 'o':
*************** demangle_substitution (dm, template_p, s
*** 2836,2841 ****
--- 2833,2839 ----
  	      RETURN_IF_ERROR (result_append (dm, "std::basic_ostream<char, std::char_traits<char> >"));
  	      new_last_source_name = "basic_ostream";
  	    }
+ 	  *template_p = 0;
  	  break;
  
  	case 'd':
*************** demangle_substitution (dm, template_p, s
*** 2849,2854 ****
--- 2847,2853 ----
  	      RETURN_IF_ERROR (result_append (dm, "std::basic_iostream<char, std::char_traits<char> >"));
  	      new_last_source_name = "basic_iostream";
  	    }
+ 	  *template_p = 0;
  	  break;
  
  	default:
*************** demangle_substitution (dm, template_p, s
*** 2872,2878 ****
       substitution, `S0_' is the second-most-recent, etc., shift the
       numbering by one.  */
    text = substitution_get (dm, seq_id + 1, template_p);
!   if (text == NULL)
      return "Substitution number out of range.";
  
    /* Emit the substitution text.  */
--- 2871,2877 ----
       substitution, `S0_' is the second-most-recent, etc., shift the
       numbering by one.  */
    text = substitution_get (dm, seq_id + 1, template_p);
!   if (text == NULL) 
      return "Substitution number out of range.";
  
    /* Emit the substitution text.  */
*************** main (argc, argv)
*** 3390,3399 ****
  	  if (STATUS_NO_ERROR (status))
  	    printf ("%s\n", dyn_string_buf (result));
  	  /* Abort on allocaiton failures.  */
! 	  if (status == STATUS_ALLOCATION_FAILED)
  	    {
  	      fprintf (stderr, "Memory allocaiton failed.\n");
! 	      abort ():
  	    }
  	  /* If not, print the error message to stderr instead.  */
  	  else 
--- 3389,3398 ----
  	  if (STATUS_NO_ERROR (status))
  	    printf ("%s\n", dyn_string_buf (result));
  	  /* Abort on allocaiton failures.  */
! 	  else if (status == STATUS_ALLOCATION_FAILED)
  	    {
  	      fprintf (stderr, "Memory allocaiton failed.\n");
! 	      abort ();
  	    }
  	  /* If not, print the error message to stderr instead.  */
  	  else 



Index: mangle.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/mangle.c,v
retrieving revision 1.10
diff -c -p -r1.10 mangle.c
*** mangle.c	2000/06/23 01:14:40	1.10
--- mangle.c	2000/06/29 03:27:33
*************** find_substitution (node)
*** 463,469 ****
  	    {
  	      tree args = CLASSTYPE_TI_ARGS (type);
  	      if (TREE_VEC_LENGTH (args) == 3
! 		  && TREE_VEC_ELT (args, 0) == char_type_node
  		  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
  					       SUBID_CHAR_TRAITS)
  		  && is_std_substitution_char (TREE_VEC_ELT (args, 2),
--- 463,469 ----
  	    {
  	      tree args = CLASSTYPE_TI_ARGS (type);
  	      if (TREE_VEC_LENGTH (args) == 3
! 		  && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
  		  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
  					       SUBID_CHAR_TRAITS)
  		  && is_std_substitution_char (TREE_VEC_ELT (args, 2),
*************** find_substitution (node)
*** 493,499 ****
  	 args <char, std::char_traits<char> > .  */
        tree args = CLASSTYPE_TI_ARGS (type);
        if (TREE_VEC_LENGTH (args) == 2
! 	  && TREE_VEC_ELT (args, 0) == char_type_node
  	  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
  				       SUBID_CHAR_TRAITS))
  	{
--- 493,499 ----
  	 args <char, std::char_traits<char> > .  */
        tree args = CLASSTYPE_TI_ARGS (type);
        if (TREE_VEC_LENGTH (args) == 2
! 	  && same_type_p (TREE_VEC_ELT (args, 0), char_type_node)
  	  && is_std_substitution_char (TREE_VEC_ELT (args, 1),
  				       SUBID_CHAR_TRAITS))
  	{
*************** write_mangled_name (decl)
*** 570,577 ****
  }
  
  /*   <encoding>		::= <function name> <bare-function-type>
! 			::= <data name>
! 			::= <substitution>  */
  
  static void
  write_encoding (decl)
--- 570,576 ----
  }
  
  /*   <encoding>		::= <function name> <bare-function-type>
! 			::= <data name>  */
  
  static void
  write_encoding (decl)
*************** write_encoding (decl)
*** 579,587 ****
  {
    MANGLE_TRACE_TREE ("encoding", decl);
  
-   if (find_substitution (decl))
-     return;
- 
    if (DECL_LANG_SPECIFIC (decl) && DECL_EXTERN_C_FUNCTION_P (decl))
      {
        write_source_name (DECL_NAME (decl));
--- 578,583 ----
*************** write_encoding (decl)
*** 600,607 ****
  
        write_bare_function_type (fn_type, DECL_TEMPLATE_ID_P (decl));
      }
- 
-   add_substitution (decl);
  }
  
  /* <name> ::= <unscoped-name>
--- 596,601 ----




Index: libioP.h
===================================================================
RCS file: /cvs/gcc/egcs/libio/libioP.h,v
retrieving revision 1.15
diff -c -p -r1.15 libioP.h
*** libioP.h	2000/06/10 03:02:21	1.15
--- libioP.h	2000/06/29 03:05:46
***************
*** 1,4 ****
! /* Copyright (C) 1993, 1997 Free Software Foundation, Inc.
     This file is part of the GNU IO Library.
  
     This library is free software; you can redistribute it and/or
--- 1,4 ----
! /* Copyright (C) 1993, 1997, 2000 Free Software Foundation, Inc.
     This file is part of the GNU IO Library.
  
     This library is free software; you can redistribute it and/or
*************** extern int _IO_vscanf __P ((const char *
*** 603,609 ****
  #  endif
  # else
  #  define VTABLE_LABEL(NAME, CLASS, CNLENGTH) \
!   extern char NAME[] asm ("_ZN" #CNLENGTH #CLASS "TVE");
  # endif /* (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) */
  #endif /* __GNUC__ */
  
--- 603,609 ----
  #  endif
  # else
  #  define VTABLE_LABEL(NAME, CLASS, CNLENGTH) \
!   extern char NAME[] asm ("_ZTV" #CNLENGTH #CLASS);
  # endif /* (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) */
  #endif /* __GNUC__ */
  


Index: stdstrbufs.cc
===================================================================
RCS file: /cvs/gcc/egcs/libio/stdstrbufs.cc,v
retrieving revision 1.6
diff -c -p -r1.6 stdstrbufs.cc
*** stdstrbufs.cc	2000/06/10 03:02:21	1.6
--- stdstrbufs.cc	2000/06/29 03:05:47
***************
*** 1,5 ****
  /*
! Copyright (C) 1994 Free Software Foundation
  
  This file is part of the GNU IO Library.  This library is free
  software; you can redistribute it and/or modify it under the
--- 1,5 ----
  /*
! Copyright (C) 1994, 2000 Free Software Foundation
  
  This file is part of the GNU IO Library.  This library is free
  software; you can redistribute it and/or modify it under the
*************** extern char filebuf_vtable[]
*** 42,48 ****
  #endif
         "filebuf");
  #else
!   asm ( "_ZN7filebufTVE" );
  #endif /* (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) */
  #else /* !__GNUC__ */
  #if _G_VTABLE_LABEL_HAS_LENGTH
--- 42,48 ----
  #endif
         "filebuf");
  #else
!   asm ( "_ZTV7filebuf" );
  #endif /* (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) */
  #else /* !__GNUC__ */
  #if _G_VTABLE_LABEL_HAS_LENGTH
*************** extern struct _IO_jump_t stdiobuf_vtable
*** 98,104 ****
  #endif
         "stdiobuf");
  #else
!   asm ( "_ZN15stdiobuf_vtableTVE" );
  #endif /* (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) */
  #else /* !__GNUC__ */
  #if _G_VTABLE_LABEL_HAS_LENGTH
--- 98,104 ----
  #endif
         "stdiobuf");
  #else
!   asm ( "_ZTV15stdiobuf_vtable" );
  #endif /* (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) */
  #else /* !__GNUC__ */
  #if _G_VTABLE_LABEL_HAS_LENGTH

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