Fix PR86585

Message ID alpine.LSU.2.20.1807201313450.16707@zhemvz.fhfr.qr
State New
Headers show
Series
  • Fix PR86585
Related show

Commit Message

Richard Biener July 20, 2018, 11:15 a.m.
I have committed the following patch to make debug refs prevail
in LTO tree merging.  This will fix mixing -g0 and -g units as
well as cases where we fail to emit early debug for some decls
in one unit but emit them for the copy in a second like for
the testcase.  So for the testcase a FE fix would be possible
as well to not lose debug info.

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

Richard.

2018-07-20  Richard Biener  <rguenther@suse.de>

	PR debug/86585
	* dwarf2out.c (dwarf2out_die_ref_for_decl): Test in_lto_p
	to cover -flto-partition=none.
	
	lto/
	* lto.c (unify_scc): Before we throw away an SCC see if we
	can amend prevailing single-entry SCC with debug refs.

	* g++.dg/lto/pr86585_0.C: New testcase.
	* g++.dg/lto/pr86585_1.C: Likewise.

Patch

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index bd45e0b0685..8377cbc5dd1 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -5851,8 +5851,7 @@  dwarf2out_die_ref_for_decl (tree decl, const char **sym,
 {
   dw_die_ref die;
 
-  if ((flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
-      && !decl_die_table)
+  if (in_lto_p && !decl_die_table)
     return false;
 
   if (TREE_CODE (decl) == BLOCK)
@@ -5865,8 +5864,7 @@  dwarf2out_die_ref_for_decl (tree decl, const char **sym,
   /* During WPA stage and incremental linking we currently use DIEs
      to store the decl <-> label + offset map.  That's quite inefficient
      but it works for now.  */
-  if (flag_wpa
-      || flag_incremental_link == INCREMENTAL_LINK_LTO)
+  if (in_lto_p)
     {
       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
       if (!ref)
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;
diff --git a/gcc/testsuite/g++.dg/lto/pr86585_0.C b/gcc/testsuite/g++.dg/lto/pr86585_0.C
new file mode 100644
index 00000000000..2c3ae9da414
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr86585_0.C
@@ -0,0 +1,18 @@ 
+// { dg-lto-do link }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target shared }
+// { dg-lto-options { { -flto -g -nostdlib -shared -fPIC } } }
+namespace Inkscape {
+    class a;
+}
+class b {
+    Inkscape::a *c;
+    virtual void d();
+};
+class e {
+    b f;
+};
+class g : e {
+    void h();
+};
+void g::h() {}
diff --git a/gcc/testsuite/g++.dg/lto/pr86585_1.C b/gcc/testsuite/g++.dg/lto/pr86585_1.C
new file mode 100644
index 00000000000..ebcbe126768
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr86585_1.C
@@ -0,0 +1,24 @@ 
+struct a {
+    struct b {
+	b();
+    } c;
+};
+class d {
+    a e;
+};
+namespace aa {
+    class h {};
+} // namespace aa
+class k {
+    typedef aa::h f;
+    f g;
+};
+namespace Inkscape {
+    class l {
+	k i;
+class : d {
+	} j;
+	l();
+    };
+    l::l() {}
+} // namespace Inkscape