This fixes PR83157 (well, not the guality fail...) and avoids creating
references to abstract instances that actually end up refering to
the concrete instance thereby eventually picking up invalid location
attributes (and whatever else there may be).

As said in the PR a simple testcase

int foo (int i)
{
  volatile int boring = 1;
  return boring + i;
}

int bar()
{
  int tem = 1;
  return tem + foo (0);
}

shows the inline instance of foo in bar refering to the concrete
instance of 'boring' rather than the abstract instance.  Analysis
of the guality fail referenced in the PR shows such a case where
gdb picks up a location attribute from the wrong place (the inline
instance doesn't have one).

The issue here is that dwarf2out_function_decl (late annotation
of the function) creates new concrete DIEs refering back to
the abstract DIEs but also registers those concrete DIEs with
equate_decl_number_to_die.  This causes late annotation of
bar to pick those as abstract instance when creating inline
instance DIEs.

Somehow this doesn't happen with GCC 5, not sure why.

The fix is to not put concrete instances into the decl -> DIE
mapping over the dwarf2out_function_decl call but unwind any
changes that replaced DIEs (just occured to me we could assert
that the replacement DIEs always have an abstract origin of the
DIE replaced -- if that works, possibly not for multiple instances
of recursive inlining which may have its own share of similar
issues...).

A different fix might be to do sth like getting the ultimate
origin when adding an abstract origin (following DW_AT_abstract_origin
links on the destination), but GCC 5 didn't do that and I'm not
sure if that's the desired behavior anyway (it also might have
interesting side-effects for early LTO debug, not sure).

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Not really asking for an OK (well, maybe yes?) but for further
ideas.

PR83157 will still need further investigation as the guality test
still fails after the patch.

No testcase, I haven't been able to produce a simple one that
gets wrong location attributes inherited and thus might be
turned into a guality test.  I also don't have any good idea
how to scan-assembler the dwarf for the correct vs. the invalid
DW_AT_abstract_origin reference...  I suppose the python dwarf
parsing testsuite thing would make this feasible somehow.

Thanks,
Richard.

2018-01-12  Richard Biener  <rguent...@suse.de>

        PR debug/83157
        * dwarf2out.c (decl_die_table_undo_stack): New static vector.
        (equate_decl_number_to_die): If there's an undo stack record
        previous DIE for the decl.
        (dwarf2out_function_decl): Initialize decl_die_table_undo_stack
        and unwind changes before returning.

Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c     (revision 256535)
+++ gcc/dwarf2out.c     (working copy)
@@ -3159,6 +3159,8 @@ struct decl_die_hasher : ggc_ptr_hash<di
 /* A hash table of references to DIE's that describe declarations.
    The key is a DECL_UID() which is a unique number identifying each decl.  */
 static GTY (()) hash_table<decl_die_hasher> *decl_die_table;
+/* A stack to unwind changes to decl_die_table.  */
+static vec<std::pair<tree, dw_die_ref> > *decl_die_table_undo_stack;
 
 struct GTY ((for_user)) variable_value_struct {
   unsigned int decl_id;
@@ -5762,7 +5764,10 @@ equate_decl_number_to_die (tree decl, dw
 {
   unsigned int decl_id = DECL_UID (decl);
 
-  *decl_die_table->find_slot_with_hash (decl, decl_id, INSERT) = decl_die;
+  dw_die_ref *slot = decl_die_table->find_slot_with_hash (decl, decl_id, 
INSERT);
+  if (*slot && decl_die_table_undo_stack)
+    decl_die_table_undo_stack->safe_push (std::make_pair (decl, *slot));
+  *slot = decl_die;
   decl_die->decl_id = decl_id;
 }
 
@@ -26044,6 +26049,10 @@ dwarf2out_decl (tree decl)
 static void
 dwarf2out_function_decl (tree decl)
 {
+  vec<std::pair<tree, dw_die_ref> > *undo_stack
+    = new vec<std::pair<tree, dw_die_ref> > ();
+  decl_die_table_undo_stack = undo_stack;
+
   dwarf2out_decl (decl);
   call_arg_locations = NULL;
   call_arg_loc_last = NULL;
@@ -26051,6 +26060,17 @@ dwarf2out_function_decl (tree decl)
   tail_call_site_count = -1;
   decl_loc_table->empty ();
   cached_dw_loc_list_table->empty ();
+
+  /* Unwind changes to the decl -> DIE mapping so we keep the abstract
+     instances associated with the decl.  */
+  decl_die_table_undo_stack = NULL;
+  while (! undo_stack->is_empty ())
+    {
+      std::pair<tree, dw_die_ref> op = undo_stack->pop ();
+      equate_decl_number_to_die (op.first, op.second);
+    }
+
+  delete undo_stack;
 }
 
 /* Output a marker (i.e. a label) for the beginning of the generated code for

Reply via email to