https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86585

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
So the issue is that for 1.ii we do _not_ emit debug information for

namespace Inkscape {
class a;
}

but we _do_ stream its NAMESPACE_DECL which then gets tree-merged with
the NAMESPACE_DECL from 2.ii losing debug info for it.

Interestingly we prune down the debug for 1.ii to just contain a
declaration for class b.  This is because we have TYPE_DECL_SUPPRESS_DEBUG
set on class b and thus run into:

static void
gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
                                enum debug_info_usage usage)
{
...
  int complete = (TYPE_SIZE (type)
                  && (! TYPE_STUB_DECL (type)
                      || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))));

The C++ FE sets this here:

void
maybe_suppress_debug_info (tree t)
{
...
  /* If the class has a vtable, write out the debug info along with
     the vtable.  */
  else if (TYPE_CONTAINS_VPTR_P (t))
    TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;

but we do not emit the vtable of b in this case which leads to incomplete
debug info.


Note that again we may run into such a situation with combining -g and -g0
units and tree-merging to a -g0 entity will drop early debug references
from entities from -g units.  So we _may_ want to do sth more clever in
case a SCC is thrown away.  Currently we do

          /* Drop DIE references.  */
          dref_queue.truncate (0);

but we could do better here, trying to merge any debug info references we
get like with (for the easy case of SCC of size one).  This fixes the testcase
up to the expected link failure.

diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index d1add15efeb..8db280ecefc 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1638,6 +1638,21 @@ unify_scc (struct data_in *data_in, unsigned from,
             to the tree node mapping computed by compare_tree_sccs.  */
          if (len == 1)
            {
+             /* If we got a debug reference queued, see if the prevailing
+                tree has a debug reference and if not, register the one
+                for the tree we are about to throw away.  */
+             if (dref_queue.length () == 1)
+               {
+                 dref_entry e = dref_queue.pop ();
+                 gcc_assert (e.decl
+                             == streamer_tree_cache_get_tree (cache, from));
+                 const char *sym;
+                 unsigned HOST_WIDE_INT off;
+                 if (!debug_hooks->die_ref_for_decl (pscc->entries[0], &sym,
+                                                     &off))
+                   debug_hooks->register_external_die (pscc->entries[0],
+                                                       e.sym, e.off);
+               }
              lto_maybe_register_decl (data_in, pscc->entries[0], from);
              streamer_tree_cache_replace_tree (cache, pscc->entries[0], from);
            }
@@ -1669,7 +1684,9 @@ unify_scc (struct data_in *data_in, unsigned from,
              free_node (scc->entries[i]);
            }

-         /* Drop DIE references.  */
+         /* Drop DIE references.
+            ???  Do as in the size-one SCC case which involves sorting
+            the queue.  */
          dref_queue.truncate (0);

          break;

Testing that now.

Reply via email to