The following makes sure to generate early debug for globals that
end up being pushed to the backend via the write_out_vars call in
c_parse_final_cleanups.  rest_of_decl_compilation is confused
by seeing current_function_decl set and skips the debug-hook
invocation because of that.  So the easy fix is to flush out
globals before starting the init function.

I verified we now properly generate early DIEs for
e_missingvar and related structure types which otherwise with
LTO are completely missing (and we ICE).  Without LTO we
may not be able to recover DIEs for those late once we start
to run free-lang-data unconditionally.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

OK for trunk?

Thanks,
Richard.

>From f73561b03a38a448115726a27749a06011507d65 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguent...@suse.de>
Date: Tue, 17 Jul 2018 14:24:17 +0200
Subject: [PATCH] fix-pr86523-2

2018-07-17  Richard Biener  <rguent...@suse.de>

        PR debug/86523
        cp/
        * decl2.c (c_parse_final_cleanups): Call write_out_vars before
        start_static_storage_duration_function sets current_function_decl.

        * g++.dg/lto/pr86523-3_0.C: New testcase.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f8fc20e4093..d67ced097da 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4754,14 +4754,14 @@ c_parse_final_cleanups (void)
             inline, with resulting performance improvements.  */
          tree ssdf_body;
 
+         /* Make sure the back end knows about all the variables.  */
+         write_out_vars (vars);
+
          /* Set the line and file, so that it is obviously not from
             the source file.  */
          input_location = locus_at_end_of_parsing;
          ssdf_body = start_static_storage_duration_function (ssdf_count);
 
-         /* Make sure the back end knows about all the variables.  */
-         write_out_vars (vars);
-
          /* First generate code to do all the initializations.  */
          if (vars)
            do_static_initialization_or_destruction (vars, /*initp=*/true);
diff --git a/gcc/testsuite/g++.dg/lto/pr86523-3_0.C 
b/gcc/testsuite/g++.dg/lto/pr86523-3_0.C
new file mode 100644
index 00000000000..31063b8773a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr86523-3_0.C
@@ -0,0 +1,24 @@
+// { dg-lto-do link }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target shared }
+// { dg-lto-options { { -fPIC -flto -g -shared } } }
+class a {
+    int b;
+};
+int const c = 0, d = 1, f = 2, g = 3;
+struct B {
+    typedef a h;
+    h i;
+};
+template <class> B j();
+template <class> struct k_context { static B const e_missingvar; };
+template <class l> B const k_context<l>::e_missingvar = j<l>();
+inline B m() {
+    switch (0) {
+      case c:
+      case d:
+      return k_context<int>::e_missingvar;
+      case f:
+      case g:;
+    }
+}

Reply via email to