[PATCH] Fix -gdwarf-4 -fdebug-types-section cloning (PR debug/51950)

Jakub Jelinek jakub@redhat.com
Wed Jan 25 20:18:00 GMT 2012


Hi!

As detailed in the PR, when copy_decls_walk uses clone_tree,
it enters just the clone node of tag into the hash table and not
any children.  On the testcase in that PR this DIE (DW_TAG_subroutine_type)
contains DW_AT_object_pointer attribute which refers to its child node
(DW_TAG_formal_parameter).   As the child has been just cloned, but not
added to the hash table, when copy_decls_walk adjusts attributes of
the DW_TAG_subroutine_type clone, it doesn't find that the child
DW_TAG_formal_parameter has been cloned and creates a new clone and
adjusts DW_AT_object_pointer to point to that.  It then goes on to attempt
to clone its ancestors, but the parent is already in the hash table,
so just adds this second DW_TAG_formal_parameter as another child
of that.

Fixed by adding all the children DIE clones to the hash table.
IMHO they can't appear in the hash table before (checked now with
an assert), because otherwise we'd have cloned the ancestors too.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2012-01-25  Jakub Jelinek  <jakub@redhat.com>

	PR debug/51950
	* dwarf2out.c (clone_tree_hash): New function.
	(copy_decls_walk): Use it instead of clone_tree.

--- gcc/dwarf2out.c.jj	2012-01-23 18:23:45.000000000 +0100
+++ gcc/dwarf2out.c	2012-01-25 18:32:24.026350399 +0100
@@ -7406,6 +7406,32 @@ copy_ancestor_tree (dw_die_ref unit, dw_
   return copy;
 }
 
+/* Like clone_tree, but additionally enter all the children into
+   the hash table decl_table.  */
+
+static dw_die_ref
+clone_tree_hash (dw_die_ref die, htab_t decl_table)
+{
+  dw_die_ref c;
+  dw_die_ref clone = clone_die (die);
+  struct decl_table_entry *entry;
+  void **slot = htab_find_slot_with_hash (decl_table, die,
+					  htab_hash_pointer (die), INSERT);
+  /* Assert that DIE isn't in the hash table yet.  If it would be there
+     before, the ancestors would be necessarily there as well, therefore
+     clone_tree_hash wouldn't be called.  */
+  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+  entry = XCNEW (struct decl_table_entry);
+  entry->orig = die;
+  entry->copy = clone;
+  *slot = entry;
+
+  FOR_EACH_CHILD (die, c,
+		  add_child_die (clone, clone_tree_hash (c, decl_table)));
+
+  return clone;
+}
+
 /* Walk the DIE and its children, looking for references to incomplete
    or trivial types that are unmarked (i.e., that are not in the current
    type_unit).  */
@@ -7442,7 +7468,11 @@ copy_decls_walk (dw_die_ref unit, dw_die
           else
             {
               dw_die_ref parent = unit;
-              dw_die_ref copy = clone_tree (targ);
+	      dw_die_ref copy = clone_die (targ);
+
+	      FOR_EACH_CHILD (targ, c,
+			      add_child_die (copy,
+					     clone_tree_hash (c, decl_table)));
 
               /* Make sure the cloned tree is marked as part of the
                  type unit.  */

	Jakub



More information about the Gcc-patches mailing list