[C++ PATCH] Fix cxx_printable_name caching
Jakub Jelinek
jakub@redhat.com
Mon Sep 24 21:02:00 GMT 2007
Hi!
On x86_64-linux running ./cc1plus -O0 -fdump-tree-eh (or any other tree dump
option) shows duplicate function names:
// { dg-do compile }
// { dg-options "-O0 -fdump-tree-eh" }
static int foo (void);
void f (void);
int g (void);
static int
foo (void)
{
int result;
try
{
result = g ();
f ();
}
catch (const int &)
{
}
return result;
}
int
bar ()
{
int result;
for (;;)
if (foo ())
return 1;
}
// { dg-final { scan-tree-dump-times ";; Function int foo\\(\\)" 1 "eh" } }
// { dg-final { scan-tree-dump-times ";; Function int bar\\(\\)" 1 "eh" } }
// { dg-final { cleanup-tree-dump "eh" } }
grep '^;; Function' printablename1.C.012t.eh
;; Function int foo() (_Z3barv)
;; Function int foo() (_ZL3foov)
The problem seems to be cxx_printable_name's caching. If it was asked to
print some FUNCTION_DECL, which is later on garbage collected and later on
happens to be ggc_alloced to a different FUNCTION_DECL, which
cxx_printable_name is called on soon afterwards, then it returns cached
string for the already garbage collected FUNCTION_DECL.
The following patch fixes this by also remembering DECL_UID, which is
increasing monotonically and so does not suffer from this problem.
I have tried to move decl_ring array to file scope instead and
mark it with GTY((deletable)), but that didn't work, as the old
FUNCTION_DECL in this case is ggc_free'd (during duplicate_decls) rather
than normally garbage collected, so there isn't anything that would set
it to NULL in between the ggc_free call and next cxx_printable_name.
As ggc_free is a promise that such a pointer isn't held anywhere, that is
not a GC bug.
Unfortunately, when adding further options this is no longer reproduceable
on this testcase, so I have nothing to add into the testsuite.
2007-09-24 Jakub Jelinek <jakub@redhat.com>
* tree.c (cxx_printable_name): Add uid_ring. Only consider
a match if decl is equal to decl_ring[x] and DECL_UID (decl)
is equal to uid_ring[x].
--- gcc/cp/tree.c.jj 2007-09-24 17:14:12.000000000 +0200
+++ gcc/cp/tree.c 2007-09-24 21:38:09.000000000 +0200
@@ -1156,6 +1156,7 @@ const char *
cxx_printable_name (tree decl, int v)
{
static tree decl_ring[PRINT_RING_SIZE];
+ static unsigned int uid_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
static int ring_counter;
int i;
@@ -1168,7 +1169,7 @@ cxx_printable_name (tree decl, int v)
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
- if (decl_ring[i] == decl)
+ if (decl_ring[i] == decl && uid_ring[i] == DECL_UID (decl))
/* yes, so return it. */
return print_ring[i];
@@ -1177,11 +1178,14 @@ cxx_printable_name (tree decl, int v)
if (current_function_decl != NULL_TREE)
{
- if (decl_ring[ring_counter] == current_function_decl)
+ if (decl_ring[ring_counter] == current_function_decl
+ && uid_ring[ring_counter] == DECL_UID (current_function_decl))
ring_counter += 1;
if (ring_counter == PRINT_RING_SIZE)
ring_counter = 0;
- gcc_assert (decl_ring[ring_counter] != current_function_decl);
+ gcc_assert (decl_ring[ring_counter] != current_function_decl
+ || uid_ring[ring_counter]
+ != DECL_UID (current_function_decl));
}
if (print_ring[ring_counter])
@@ -1189,6 +1193,7 @@ cxx_printable_name (tree decl, int v)
print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
decl_ring[ring_counter] = decl;
+ uid_ring[ring_counter] = DECL_UID (decl);
return print_ring[ring_counter];
}
Jakub
More information about the Gcc-patches
mailing list