The following patch avoids streaming extern var and function decls
into the global decls and types section when streaming a tree
chain list (effectively only when processing BLOCK_VARS).  This
avoids the last LTO debug-info ICE I know of (knocks on wood)
and provides a cleaner (well ...) fix for PR48437 as well.

LTO bootstrapped on x86_64-unknown-linux-gnu, testing in progress,
so is SPEC 2k6 build with -g (hopefully now without ICEs as well).

I plan to commit this tomorrow if all goes well and declare
LTO debug-info perfect for 4.7.

Richard.

2011-12-14  Richard Guenther  <rguent...@suse.de>

        Revert
        PR lto/48437
        * lto-streamer-out.c (tree_is_indexable): Exclude block-local
        extern declarations.

        PR lto/48508
        PR lto/48437
        * tree-streamer-out.c (streamer_write_chain): Stream DECL_EXTERNAL
        VAR_DECLs and FUNCTION_DECLs locally.

        * g++.dg/lto/pr48508-1_0.C: New testcase.
        * g++.dg/lto/pr48508-1_1.C: Likewise.

Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c      (revision 182335)
--- gcc/lto-streamer-out.c      (working copy)
*************** tree_is_indexable (tree t)
*** 129,144 ****
    else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
           && !TREE_STATIC (t))
      return false;
-   /* If this is a decl generated for block local externs for
-      debug info generation, stream it unshared alongside BLOCK_VARS.  */
-   else if (VAR_OR_FUNCTION_DECL_P (t)
-          /* ???  The following tests are a literal match on what
-             c-decl.c:pop_scope does.  */
-          && TREE_PUBLIC (t)
-          && DECL_EXTERNAL (t)
-          && DECL_CONTEXT (t)
-          && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
-     return false;
    /* Variably modified types need to be streamed alongside function
       bodies because they can refer to local entities.  Together with
       them we have to localize their members as well.
--- 129,134 ----
Index: gcc/tree-streamer-out.c
===================================================================
*** gcc/tree-streamer-out.c     (revision 182335)
--- gcc/tree-streamer-out.c     (working copy)
*************** streamer_write_chain (struct output_bloc
*** 405,411 ****
        saved_chain = TREE_CHAIN (t);
        TREE_CHAIN (t) = NULL_TREE;
  
!       stream_write_tree (ob, t, ref_p);
  
        TREE_CHAIN (t) = saved_chain;
        t = TREE_CHAIN (t);
--- 405,417 ----
        saved_chain = TREE_CHAIN (t);
        TREE_CHAIN (t) = NULL_TREE;
  
!       /* We avoid outputting external vars or functions by reference
!          to the global decls section as we do not want to have them
!        enter decl merging.  This is, of course, only for the call
!        for streaming BLOCK_VARS, but other callers are safe.  */
!       stream_write_tree (ob, t,
!                        ref_p && !(VAR_OR_FUNCTION_DECL_P (t)
!                                   && DECL_EXTERNAL (t)));
  
        TREE_CHAIN (t) = saved_chain;
        t = TREE_CHAIN (t);
Index: gcc/testsuite/g++.dg/lto/pr48508-1_0.C
===================================================================
*** gcc/testsuite/g++.dg/lto/pr48508-1_0.C      (revision 0)
--- gcc/testsuite/g++.dg/lto/pr48508-1_0.C      (revision 0)
***************
*** 0 ****
--- 1,7 ----
+ // { dg-lto-do link }
+ // { dg-lto-options { { -g -O2 -flto -flto-partition=none } } }
+ 
+ void __attribute__((externally_visible))
+ foo (int i)
+ {
+ }
Index: gcc/testsuite/g++.dg/lto/pr48508-1_1.C
===================================================================
*** gcc/testsuite/g++.dg/lto/pr48508-1_1.C      (revision 0)
--- gcc/testsuite/g++.dg/lto/pr48508-1_1.C      (revision 0)
***************
*** 0 ****
--- 1,10 ----
+ static void
+ bar (void)
+ {
+   extern void foo (int);
+   foo (0);
+ }
+ int main()
+ {
+   bar ();
+ }

Reply via email to