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]
Other format: [Raw text]

C++ PATCH: PR 17324


This patch fixes PR c++/17324, a regression introduced by my recent
changes to the name-mangler to build names on the same obstack used by
the identifier hash table.  Unfortunately, there are a few situations
in which the name-mangler calls functions which indirectly call
get_identifier, which stomps on the mangled name presently being built
up.  

The only one of these of which I am aware is the ill-named
mangle_class_name_for_template, which sets TYPE_IDENTIFIER for a class
template instantiation to "A<int>" as opposed to just "A".  That's a
bad design; really, the error printing and debug-info generating code
should just add the "<int>" when it needs to do so.  However, that's a
more invasive change than I'm willing to undertake just now, so I'm
going with this work-around.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-09-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/17324
	* mangle.c (partially_mangled_name): New variable.
	(partially_mangled_name_len): Likewise.
	(save_partially_mangled_name): New function.
	(restore_partially_mangled_name): Likewise.
	(write_encoding): Save and restore partially mangled names around
	calls to get_mostly_instantiated_function_type.
	(write_unqualified_name): Likewise.

2004-09-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/17324
	* g++.dg/template/mangle1.C: New test.

Index: cp/mangle.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/mangle.c,v
retrieving revision 1.111
diff -c -5 -p -r1.111 mangle.c
*** cp/mangle.c	10 Sep 2004 11:12:13 -0000	1.111
--- cp/mangle.c	15 Sep 2004 03:04:15 -0000
*************** static struct obstack *mangle_obstack;
*** 113,126 ****
  
  /* The obstack on which we build mangled names that are not going to
     be IDENTIFIER_NODEs.  */
  static struct obstack name_obstack;
  
!   /* The first object on the name_obstack; we use this to free memory
!      allocated on the name_obstack.  */
  static void *name_base;
  
  /* Indices into subst_identifiers.  These are identifiers used in
     special substitution rules.  */
  typedef enum
  {
    SUBID_ALLOCATOR,
--- 113,133 ----
  
  /* The obstack on which we build mangled names that are not going to
     be IDENTIFIER_NODEs.  */
  static struct obstack name_obstack;
  
! /* The first object on the name_obstack; we use this to free memory
!    allocated on the name_obstack.  */
  static void *name_base;
  
+ /* An incomplete mangled name.  There will be no NUL terminator.  If
+    there is no incomplete mangled name, this variable is NULL.  */
+ static char *partially_mangled_name;
+ 
+ /* The number of characters in the PARTIALLY_MANGLED_NAME.  */
+ static size_t partially_mangled_name_len;
+ 
  /* Indices into subst_identifiers.  These are identifiers used in
     special substitution rules.  */
  typedef enum
  {
    SUBID_ALLOCATOR,
*************** static void write_java_integer_type_code
*** 252,261 ****
--- 259,304 ----
  
  /* Write out an unsigned quantity in base 10.  */
  #define write_unsigned_number(NUMBER) \
    write_number ((NUMBER), /*unsigned_p=*/1, 10)
  
+ /* Save the current (incomplete) mangled name and release the obstack
+    storage holding it.  This function should be used during mangling
+    when making a call that could result in a call to get_identifier,
+    as such a call will clobber the same obstack being used for
+    mangling.  This function may not be called twice without an
+    intervening call to restore_partially_mangled_name.  */
+ 
+ static void
+ save_partially_mangled_name (void)
+ {
+   if (mangle_obstack == &ident_hash->stack)
+     {
+       gcc_assert (!partially_mangled_name);
+       partially_mangled_name_len = obstack_object_size (mangle_obstack);
+       partially_mangled_name = xmalloc (partially_mangled_name_len);
+       memcpy (partially_mangled_name, obstack_base (mangle_obstack),
+ 	      partially_mangled_name_len);
+       obstack_free (mangle_obstack, obstack_finish (mangle_obstack));
+     }
+ }
+ 
+ /* Restore the incomplete mangled name saved with
+    save_partially_mangled_name.  */
+ 
+ static void
+ restore_partially_mangled_name (void)
+ {
+   if (partially_mangled_name)
+     {
+       obstack_grow (mangle_obstack, partially_mangled_name,
+ 		    partially_mangled_name_len);
+       free (partially_mangled_name);
+       partially_mangled_name = NULL;
+     }
+ }
+ 
  /* If DECL is a template instance, return nonzero and, if
     TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
     Otherwise return zero.  */
  
  static int
*************** write_encoding (const tree decl)
*** 700,710 ****
--- 743,755 ----
        tree fn_type;
        tree d;
  
        if (decl_is_template_id (decl, NULL))
  	{
+ 	  save_partially_mangled_name ();
  	  fn_type = get_mostly_instantiated_function_type (decl);
+ 	  restore_partially_mangled_name ();
  	  /* FN_TYPE will not have parameter types for in-charge or
  	     VTT parameters.  Therefore, we pass NULL_TREE to
  	     write_bare_function_type -- otherwise, it will get
  	     confused about which artificial parameters to skip.  */
  	  d = NULL_TREE;
*************** write_unqualified_name (const tree decl)
*** 1061,1071 ****
        /* Conversion operator. Handle it right here.  
             <operator> ::= cv <type>  */
        tree type;
        if (decl_is_template_id (decl, NULL))
  	{
! 	  tree fn_type = get_mostly_instantiated_function_type (decl);
  	  type = TREE_TYPE (fn_type);
  	}
        else
  	type = DECL_CONV_FN_TYPE (decl);
        write_conversion_operator_name (type);
--- 1106,1119 ----
        /* Conversion operator. Handle it right here.  
             <operator> ::= cv <type>  */
        tree type;
        if (decl_is_template_id (decl, NULL))
  	{
! 	  tree fn_type;
! 	  save_partially_mangled_name ();
! 	  fn_type = get_mostly_instantiated_function_type (decl);
! 	  restore_partially_mangled_name ();
  	  type = TREE_TYPE (fn_type);
  	}
        else
  	type = DECL_CONV_FN_TYPE (decl);
        write_conversion_operator_name (type);
Index: testsuite/g++.dg/template/mangle1.C
===================================================================
RCS file: testsuite/g++.dg/template/mangle1.C
diff -N testsuite/g++.dg/template/mangle1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/mangle1.C	15 Sep 2004 03:04:14 -0000
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/17324
+ // { dg-do assemble }
+ 
+ template<int, typename T> struct A
+ {
+   template<int I> void foo(const A<I,T>&) {}
+ };
+ 
+ template<typename> struct B
+ {
+   template<int J> void bar(const A<J,B>&);
+   void baz() { A<0,B>().foo(A<0,B>()); }
+ };
+ 
+ template struct B<void>;
+ template struct B<int>;


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