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: demangler fixes


This patch fixes three problems in the new-ABI C++ demangler.

 1. The demangler now assumes that mangled constructor names do not
    encode a return value, even if the constructor is a member
    template.

 2. A bug is fixed whereby a mangled name containing a substitution
    for a type template name followed by a template argument list was
    not being demangled.

 3. An extra space is inserted before the opening angle bracket in a
    template argument list if necessary to prevent it from mushing
    into a previous less-than, as in a templated operator< or
    operator<< .

Ok to commit?


In libiberty:

	* cp-demangle.c (result_close_template_list): Remove function.
	(result_add_separated_char): New function.
	(result_open_template_list): New macro.
	(result_close_template_list): Likewise.
	(demangle_prefix): Don't set template_p if the
	prefix ends with a ctor name.
	(demangle_type_ptr): Remove duplicate RETURN_IF_ERROR.
	(demangle_type): Check for template args after substitution.
	(demangle_template_args): Use result_open_template_list.



Index: cp-demangle.c
===================================================================
RCS file: /cvs/gcc/egcs/libiberty/cp-demangle.c,v
retrieving revision 1.13
diff -c -p -r1.13 cp-demangle.c
*** cp-demangle.c	2000/07/23 17:55:13	1.13
--- cp-demangle.c	2000/08/23 07:35:31
*************** static string_list_t string_list_new
*** 196,203 ****
    PARAMS ((int));
  static void string_list_delete
    PARAMS ((string_list_t));
! static status_t result_close_template_list 
!   PARAMS ((demangling_t));
  static status_t result_push
    PARAMS ((demangling_t));
  static string_list_t result_pop
--- 196,203 ----
    PARAMS ((int));
  static void string_list_delete
    PARAMS ((string_list_t));
! static status_t result_add_separated_char
!   PARAMS ((demangling_t, char));
  static status_t result_push
    PARAMS ((demangling_t));
  static string_list_t result_pop
*************** static void demangling_delete 
*** 297,302 ****
--- 297,309 ----
    (dyn_string_append_space (&(DM)->result->string)                      \
     ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  
+ /* Appends a (less-than, greater-than) character to the result in DM
+    to (open, close) a template argument or parameter list.  Appends a
+    space first if necessary to prevent spurious elision of angle
+    brackets with the previous character.  */
+ #define result_open_template_list(DM) result_add_separated_char(DM, '<')
+ #define result_close_template_list(DM) result_add_separated_char(DM, '>')
+ 
  /* Appends a base 10 representation of VALUE to DS.  STATUS_OK on
     success.  On failure, deletes DS and returns an error code.  */
  
*************** string_list_delete (node)
*** 378,405 ****
      }
  }
  
! /* Appends a greater-than character to the demangled result.  If the
!    last character is a greater-than character, a space is inserted
!    first, so that the two greater-than characters don't look like a
!    right shift token.  */
  
  static status_t
! result_close_template_list (dm)
       demangling_t dm;
  {
    dyn_string_t s = &dm->result->string;
  
    /* Add a space if the last character is already a closing angle
       bracket, so that a nested template arg list doesn't look like
       it's closed with a right-shift operator.  */
!   if (dyn_string_last_char (s) == '>')
      {
        if (!dyn_string_append_char (s, ' '))
  	return STATUS_ALLOCATION_FAILED;
      }
  
    /* Add closing angle brackets.  */
!   if (!dyn_string_append_char (s, '>'))
      return STATUS_ALLOCATION_FAILED;
  
    return STATUS_OK;
--- 385,411 ----
      }
  }
  
! /* Appends CHARACTER to the demangled result.  If the current trailing
!    character of the result is CHARACTER, a space is inserted first.  */
  
  static status_t
! result_add_separated_char (dm, character)
       demangling_t dm;
+      char character;
  {
    dyn_string_t s = &dm->result->string;
  
    /* Add a space if the last character is already a closing angle
       bracket, so that a nested template arg list doesn't look like
       it's closed with a right-shift operator.  */
!   if (dyn_string_last_char (s) == character)
      {
        if (!dyn_string_append_char (s, ' '))
  	return STATUS_ALLOCATION_FAILED;
      }
  
    /* Add closing angle brackets.  */
!   if (!dyn_string_append_char (s, character))
      return STATUS_ALLOCATION_FAILED;
  
    return STATUS_OK;
*************** demangle_prefix (dm, template_p)
*** 1108,1113 ****
--- 1114,1123 ----
    int start = substitution_start (dm);
    int nested = 0;
  
+   /* This flag is set to non-zero if the most recent (rightmost)
+      element in the prefix was a constructor.  */
+   int last_was_ctor = 0;
+ 
    /* TEMPLATE_P is updated as we decend the nesting chain.  After
       <template-args>, it is set to non-zero; after everything else it
       is set to zero.  */
*************** demangle_prefix (dm, template_p)
*** 1124,1129 ****
--- 1134,1148 ----
  
        peek = peek_char (dm);
        
+       /* We'll initialize last_was_ctor to false, and set it to true
+ 	 if we end up demangling a constructor name.  However, make
+ 	 sure we're not actually about to demangle template arguments
+ 	 -- if so, this is the <template-args> following a
+ 	 <template-prefix>, so we'll want the previous flag value
+ 	 around.  */
+       if (peek != 'I')
+ 	last_was_ctor = 0;
+ 
        if (IS_DIGIT ((unsigned char) peek)
  	  || (peek >= 'a' && peek <= 'z')
  	  || peek == 'C' || peek == 'D'
*************** demangle_prefix (dm, template_p)
*** 1137,1161 ****
  
  	  if (peek == 'S')
  	    /* The substitution determines whether this is a
! 	       template-id.   */
  	    RETURN_IF_ERROR (demangle_substitution (dm, template_p, 
  						    &unused));
  	  else
  	    {
  	      RETURN_IF_ERROR (demangle_unqualified_name (dm));
  	      *template_p = 0;
  	    }
  	}
        else if (peek == 'Z')
  	RETURN_IF_ERROR (demangle_local_name (dm));
        else if (peek == 'I')
  	{
! 	  if (*template_p)
! 	    return STATUS_INTERNAL_ERROR;
  	  /* The template name is a substitution candidate.  */
  	  RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
  	  RETURN_IF_ERROR (demangle_template_args (dm));
! 	  *template_p = 1;
  	}
        else if (peek == 'E')
  	/* All done.  */
--- 1156,1202 ----
  
  	  if (peek == 'S')
  	    /* The substitution determines whether this is a
! 	       template-id.  */
  	    RETURN_IF_ERROR (demangle_substitution (dm, template_p, 
  						    &unused));
  	  else
  	    {
+ 	      /* It's just a name.  Remember whether it's a
+ 		 constructor.  */
  	      RETURN_IF_ERROR (demangle_unqualified_name (dm));
  	      *template_p = 0;
  	    }
+ 
+ 	  /* If this element was a constructor name, make a note of
+ 	     that.  */
+ 	  if (peek == 'C')
+ 	    last_was_ctor = 1;
  	}
        else if (peek == 'Z')
  	RETURN_IF_ERROR (demangle_local_name (dm));
        else if (peek == 'I')
  	{
! 	  /* If the template flag is already set, this is the second
!              set of template args in a row.  Something is wrong with
!              the mangled name.  */
! 	  if (*template_p) 
! 	    return "Unexpected second consecutive template args in <prefix>.";
  	  /* The template name is a substitution candidate.  */
  	  RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
  	  RETURN_IF_ERROR (demangle_template_args (dm));
! 
! 	  /* Now we want to indicate to the caller that we've
! 	     demangled template arguments, thus the prefix was a
! 	     <template-prefix>.  That's so that the caller knows to
! 	     demangle the function's return type, if this turns out to
! 	     be a function name.  */
! 	  if (!last_was_ctor)
! 	    *template_p = 1;
! 	  else
! 	    /* But, if it's a member template constructor, report it
! 	       as untemplated.  We don't ever want to demangle the
! 	       return type of a constructor.  */
! 	    *template_p = 0;
  	}
        else if (peek == 'E')
  	/* All done.  */
*************** demangle_type_ptr (dm)
*** 1904,1916 ****
  	}
        else
  	{
! 	  /* No more pointe or reference tokens.  Finish up.  */
  	  status = demangle_type (dm);
  
  	  if (STATUS_NO_ERROR (status))
  	    status = result_append_string (dm, symbols);
  	  dyn_string_delete (symbols);
- 	  RETURN_IF_ERROR (status);
  
  	  RETURN_IF_ERROR (status);
  	  return STATUS_OK;
--- 1945,1956 ----
  	}
        else
  	{
! 	  /* No more pointer or reference tokens.  Finish up.  */
  	  status = demangle_type (dm);
  
  	  if (STATUS_NO_ERROR (status))
  	    status = result_append_string (dm, symbols);
  	  dyn_string_delete (symbols);
  
  	  RETURN_IF_ERROR (status);
  	  return STATUS_OK;
*************** demangle_type (dm)
*** 2016,2023 ****
  	   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;
--- 2056,2072 ----
  	   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));
! 	    
! 	    /* The substituted name may have been a template name.
! 	       Check if template arguments follow, and if so, demangle
! 	       them.  */
! 	    if (peek_char (dm) == 'I')
! 	      RETURN_IF_ERROR (demangle_template_args (dm));
! 	  }
  	else
  	  demangle_class_enum_type (dm, &template_p);
  	break;
*************** demangle_template_args (dm)
*** 2440,2446 ****
      return STATUS_ALLOCATION_FAILED;
  
    RETURN_IF_ERROR (demangle_char (dm, 'I'));
!   RETURN_IF_ERROR (result_append_char (dm, '<'));
    do
      {
        string_list_t arg;
--- 2489,2495 ----
      return STATUS_ALLOCATION_FAILED;
  
    RETURN_IF_ERROR (demangle_char (dm, 'I'));
!   RETURN_IF_ERROR (result_open_template_list (dm));
    do
      {
        string_list_t arg;

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