This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 17324
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 14 Sep 2004 20:25:48 -0700
- Subject: C++ PATCH: PR 17324
- Reply-to: mark at codesourcery dot com
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>;