Currently a _lot_ of packages fail to build with LTO because LTO
messes up fortify wrappers by replacing the call to the alias with
the symbol itself, making the wrapper look like infinitely
recursing.

The following patch fixes this by dropping the bodies of
DECL_EXTERN always-inline functions on the floor before IPA
(and when doing LTO).  IMHO we should at some point do this
unconditional on LTO as the early inliner is supposed to
remove all references to always-inline functions.

I'm not 100% sure about the cgraph API use to drop the function
body, but at least it seems to work ;)  I'm not sure if we want
to restrict the set of functions to apply this even more than
just those with always-inline and DECL_EXTERNAL set?

Now double-checking with a fortified LTO bootstrap.

Ok for trunk?

Thanks,
Richard.

2014-03-24  Richard Biener  <rguent...@suse.de>

        PR lto/59626
        * passes.c (ipa_write_summaries): Drop function bodies of
        extern always-inline functions.

        * gcc.dg/lto/pr59626_0.c: New testcase.
        * gcc.dg/lto/pr59626_1.c: Likewise.

Index: gcc/passes.c
===================================================================
*** gcc/passes.c        (revision 208745)
--- gcc/passes.c        (working copy)
*************** ipa_write_summaries (void)
*** 2390,2404 ****
  
        if (cgraph_function_with_gimple_body_p (node))
        {
!         /* When streaming out references to statements as part of some IPA
!            pass summary, the statements need to have uids assigned and the
!            following does that for all the IPA passes here. Naturally, this
!            ordering then matches the one IPA-passes get in their stmt_fixup
!            hooks.  */
! 
!         push_cfun (DECL_STRUCT_FUNCTION (node->decl));
!         renumber_gimple_stmt_uids ();
!         pop_cfun ();
        }
        if (node->definition)
          lto_set_symtab_encoder_in_partition (encoder, node);
--- 2396,2427 ----
  
        if (cgraph_function_with_gimple_body_p (node))
        {
!         if (DECL_EXTERNAL (node->decl)
!             && lookup_attribute ("always_inline",
!                                  DECL_ATTRIBUTES (node->decl)) != NULL)
!           {
!             /* We mess up uses of extern always-inline wrappers that
!                end up calling an alias to itself like glibc _FORTIFY_SOURCE
!                wrappers.  Simply drop the bodies of the extern inlines
!                here to avoid that.  */
!             cgraph_release_function_body (node);
!             node->analyzed = false;
!             node->definition = false;
!             DECL_ATTRIBUTES (node->decl)
!               = remove_attribute ("always_inline",
!                                   DECL_ATTRIBUTES (node->decl));
!           }
!         else
!           {
!             /* When streaming out references to statements as part of some
!                IPA pass summary, the statements need to have uids assigned
!                and the following does that for all the IPA passes here.
!                Naturally, this ordering then matches the one IPA-passes get
!                in their stmt_fixup hooks.  */
!             push_cfun (DECL_STRUCT_FUNCTION (node->decl));
!             renumber_gimple_stmt_uids ();
!             pop_cfun ();
!           }
        }
        if (node->definition)
          lto_set_symtab_encoder_in_partition (encoder, node);
Index: gcc/testsuite/gcc.dg/lto/pr59626_0.c
===================================================================
*** gcc/testsuite/gcc.dg/lto/pr59626_0.c        (revision 0)
--- gcc/testsuite/gcc.dg/lto/pr59626_0.c        (working copy)
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-lto-do run } */
+ 
+ int __atoi  (const char *) __asm__("atoi");
+ extern inline __attribute__((always_inline,gnu_inline))
+ int atoi (const char *x)
+ {
+   return __atoi (x);
+ }
+ 
+ int bar (int (*)(const char *));
+ 
+ int main()
+ {
+   return bar (atoi);
+ }
Index: gcc/testsuite/gcc.dg/lto/pr59626_1.c
===================================================================
*** gcc/testsuite/gcc.dg/lto/pr59626_1.c        (revision 0)
--- gcc/testsuite/gcc.dg/lto/pr59626_1.c        (working copy)
***************
*** 0 ****
--- 1,4 ----
+ int bar (int (*fn)(const char *))
+ {
+   return fn ("0");
+ }

Reply via email to