In addition to the approved part of the patch, I finally got the
testsuite and a full Linux distribution to build without false warnings,
with the additional following changes:
* two false warnings detected during a Linux distrib rebuild
- __typeof (__error) doesn't propagate the inline keyword. even if
the function had attribute always_inline.
- extern inline function redefinition would inherit the attribute,
even if they are not inline
DECL_UNINLINABLE is set for redefining extern inline functions.
(commented in c-decl.c:2340). So indeed testing this flags in the
cgraphunit.c part fixed both.
I checked that this doesn't conflict with other DECL_UNINLINABLE
warning emitted from ree_inlinable_function_p. (which is called after)
* One silent bug revealed, undetected in the GCC testuite:
- PR43564.c compiled in -O0, the "__clz" function was silently not
inlined. Fixed in ipa-inline.c:inline_forbidden_p_stmt
* LTO pitfall: It's OK to not have a body to inline when generating the
LTO Gimple. Enforced by PR20090218-1_0.c
* In addition to the parts of the patch that was approved, I had to fix
the tests that didn't use the inline keyword but enforced the
always_inline attribute to pass without the warning
I choose to add -Wno-attributes to the option list. Could as well fix
the test by adding the inline keyword, but I preferred to not modify the
original test when possible.
* A minor code optimization in ipa-inline-transform.c: Don't call
optimize_inline_calls if there is not callee.
Comments, OK to apply ?
Many thanks
Christian
2011-06-16 Christian Bruel <christian.br...@st.com>
PR 49139/43654
* cgraphunit.c (process_function_and_variable_attributes): warn
for always_inline functions that are not inline.
* ipa-inline-transform.c (inline_transform): Always call
optimize_inline.
* ipa-inline.c (can_inline_edge_p): Check always_inline.
* tree-inline.c (tree_inlinable_function_p): Call error instead
of sorry.
(expand_call_inline): Likewise.
2011-06-16 Christian Bruel <christian.br...@st.com>
* gcc.dg/always_inline.c: Removed -Winline. Update checks
* gcc.dg/always_inline2.c: Likewise.
* gcc.dg/always_inline3.c: Likewise.
* gcc.dg/debug/pr41264-1.c: Add -Wno-attributes.
* gcc.dg/inline_1.c: Likewise.
* gcc.dg/inline_2.c: Likewise.
* gcc.dg/inline_3.c: Likewise.
* gcc.dg/inline_4.c: Likewise.
* gcc.dg/20051201-1.c: Likewise.
* gcc.dg/torture/pta-structcopy-1.c: Likewise.
* gcc.dg/inline-22.c: Likewise.
* gcc.dg/lto/20090218-1_0.c: Set inline keyword.
* gcc.dg/lto/20090218-1_1.c: Likewise.
* g++.dg/ipa/devirt-7.C: Likewise.
* gcc.dg/uninit-pred-5_a.c: Likewise.
* gcc.dg/uninit-pred-5_b.c: Likewise.
* gcc.dg/fail_always_inline.c: New.
2011-06-16 Christian Bruel <christian.br...@st.com>
PR 49139/43654
* cgraphunit.c (process_function_and_variable_attributes): warn when
always_inline functions that are not inline.
* ipa-inline-transform.c (inline_transform): Always call
optimize_inline.
* ipa-inline.c (can_inline_edge_p): Check always_inline.
* tree-inline.c (tree_inlinable_function_p): Use error instead of sorry.
(expand_call_inline): Likewise.
Index: ipa-inline-transform.c
===================================================================
--- ipa-inline-transform.c (revision 175201)
+++ ipa-inline-transform.c (working copy)
@@ -348,8 +348,7 @@
{
unsigned int todo = 0;
struct cgraph_edge *e;
- bool inline_p = false;
-
+
/* FIXME: Currently the pass manager is adding inline transform more than
once to some clones. This needs revisiting after WPA cleanups. */
if (cfun->after_inlining)
@@ -361,20 +360,17 @@
save_inline_function_body (node);
for (e = node->callees; e; e = e->next_callee)
+ cgraph_redirect_edge_call_stmt_to_callee (e);
+
+ timevar_push (TV_INTEGRATION);
+ if (node->callees)
{
- cgraph_redirect_edge_call_stmt_to_callee (e);
- if (!e->inline_failed || warn_inline)
- inline_p = true;
/* Redirecting edges might lead to a need for vops to be recomputed. */
todo |= TODO_update_ssa_only_virtuals;
- }
-
- if (inline_p)
- {
- timevar_push (TV_INTEGRATION);
todo = optimize_inline_calls (current_function_decl);
- timevar_pop (TV_INTEGRATION);
}
+ timevar_pop (TV_INTEGRATION);
+
cfun->always_inline_functions_inlined = true;
cfun->after_inlining = true;
return todo | execute_fixup_cfg ();
Index: cgraphunit.c
===================================================================
--- cgraphunit.c (revision 175201)
+++ cgraphunit.c (working copy)
@@ -986,6 +986,14 @@
DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
DECL_ATTRIBUTES (decl));
}
+
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))
+ && !DECL_DECLARED_INLINE_P (decl)
+ /* redefining always_inline function makes it DECL_UNINLINABLE. */
+ && !DECL_UNINLINABLE (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "always_inline function might not be inlinable");
+
process_common_attributes (decl);
}
for (vnode = varpool_nodes; vnode != first_var; vnode = vnode->next)
Index: ipa-inline.c
===================================================================
--- ipa-inline.c (revision 175201)
+++ ipa-inline.c (working copy)
@@ -318,8 +318,10 @@
? callee_tree
: optimization_default_node);
- if ((caller_opt->x_optimize > callee_opt->x_optimize)
- || (caller_opt->x_optimize_size != callee_opt->x_optimize_size))
+ if (((caller_opt->x_optimize > callee_opt->x_optimize)
+ || (caller_opt->x_optimize_size != callee_opt->x_optimize_size))
+ /* gcc.dg/pr43564.c. look at forced inline even in -O0. */
+ && !lookup_attribute ("always_inline", DECL_ATTRIBUTES
(e->callee->decl)))
{
e->inline_failed = CIF_TARGET_OPTIMIZATION_MISMATCH;
inlinable = false;
Index: tree-inline.c
===================================================================
--- tree-inline.c (revision 175201)
+++ tree-inline.c (working copy)
@@ -3192,7 +3192,7 @@
As a bonus we can now give more details about the reason why a
function is not inlinable. */
if (always_inline)
- sorry (inline_forbidden_reason, fn);
+ error (inline_forbidden_reason, fn);
else if (do_warning)
warning (OPT_Winline, inline_forbidden_reason, fn);
@@ -3742,11 +3742,13 @@
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
/* Avoid warnings during early inline pass. */
- && cgraph_global_info_ready)
+ && cgraph_global_info_ready
+ /* PR 20090218-1_0.c. Body can be provided by another module. */
+ && (reason != CIF_BODY_NOT_AVAILABLE || !flag_generate_lto))
{
- sorry ("inlining failed in call to %q+F: %s", fn,
- _(cgraph_inline_failed_string (reason)));
- sorry ("called from here");
+ error ("inlining failed in call to always_inline %q+F: %s", fn,
+ cgraph_inline_failed_string (reason));
+ error ("called from here");
}
else if (warn_inline
&& DECL_DECLARED_INLINE_P (fn)
Index: testsuite/ChangeLog
2011-06-16 Christian Bruel <christian.br...@st.com>
* gcc.dg/always_inline.c: Removed -Winline. Update checks
* gcc.dg/always_inline2.c: Likewise.
* gcc.dg/always_inline3.c: Likewise.
* gcc.dg/debug/pr41264-1.c: Add -Wno-attributes.
* gcc.dg/inline_1.c: Likewise.
* gcc.dg/inline_2.c: Likewise.
* gcc.dg/inline_3.c: Likewise.
* gcc.dg/inline_4.c: Likewise.
* gcc.dg/20051201-1.c: Likewise.
* gcc.dg/torture/pta-structcopy-1.c: Likewise.
* gcc.dg/inline-22.c: Likewise.
* gcc.dg/lto/20090218-1_0.c: Set inline keyword.
* gcc.dg/lto/20090218-1_1.c: Likewise.
* g++.dg/ipa/devirt-7.C: Likewise.
* gcc.dg/uninit-pred-5_a.c: Likewise.
* gcc.dg/uninit-pred-5_b.c: Likewise.
* gcc.dg/fail_always_inline.c: New.
Index: testsuite/gcc.dg/always_inline.c
===================================================================
--- testsuite/gcc.dg/always_inline.c (revision 175201)
+++ testsuite/gcc.dg/always_inline.c (working copy)
@@ -1,8 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-Winline -O2" } */
+/* { dg-options "-O2" } */
#include <stdarg.h>
inline __attribute__ ((always_inline)) void
-e(int t, ...) /* { dg-message "sorry\[^\n\]*variable argument" "" } */
+e(int t, ...) /* { dg-error "variable argument lists" } */
{
va_list q;
va_start (q, t);
Index: testsuite/gcc.dg/inline_2.c
===================================================================
--- testsuite/gcc.dg/inline_2.c (revision 175201)
+++ testsuite/gcc.dg/inline_2.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline=0:100
-fdisable-ipa-inline" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline=0:100
-fdisable-ipa-inline -Wno-attributes" } */
int g;
__attribute__((always_inline)) void bar (void)
{
Index: testsuite/gcc.dg/20051201-1.c
===================================================================
--- testsuite/gcc.dg/20051201-1.c (revision 175201)
+++ testsuite/gcc.dg/20051201-1.c (working copy)
@@ -2,7 +2,7 @@
tree_flow_call_edges_add. */
/* { dg-do compile } */
-/* { dg-options "-O1 -fprofile-generate" } */
+/* { dg-options "-O1 -fprofile-generate -Wno-attributes" } */
static __attribute__ ((always_inline)) void
baz ()
Index: testsuite/gcc.dg/debug/pr41264-1.c
===================================================================
--- testsuite/gcc.dg/debug/pr41264-1.c (revision 175201)
+++ testsuite/gcc.dg/debug/pr41264-1.c (working copy)
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-options "-Wno-attributes" } */
#if (__SIZEOF_INT__ <= 2)
typedef unsigned long hashval_t;
Index: testsuite/gcc.dg/uninit-pred-5_a.c
===================================================================
--- testsuite/gcc.dg/uninit-pred-5_a.c (revision 175201)
+++ testsuite/gcc.dg/uninit-pred-5_a.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Wuninitialized -O2" } */
+/* { dg-options "-Wuninitialized -Wno-attributes -O2" } */
int g;
int bar();
Index: testsuite/gcc.dg/inline_3.c
===================================================================
--- testsuite/gcc.dg/inline_3.c (revision 175201)
+++ testsuite/gcc.dg/inline_3.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
-/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline=foo,foo2
-fdisable-ipa-inline" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline=foo,foo2
-fdisable-ipa-inline -Wno-attributes" } */
int g;
__attribute__((always_inline)) void bar (void)
{
Index: testsuite/gcc.dg/inline-22.c
===================================================================
--- testsuite/gcc.dg/inline-22.c (revision 175201)
+++ testsuite/gcc.dg/inline-22.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-funit-at-a-time" } */
+/* { dg-options "-funit-at-a-time -Wno-attributes" } */
/* Verify we can inline without a complete prototype and with promoted
arguments. See also PR32492. */
__attribute__((always_inline)) void f1() {}
Index: testsuite/gcc.dg/always_inline2.c
===================================================================
--- testsuite/gcc.dg/always_inline2.c (revision 175201)
+++ testsuite/gcc.dg/always_inline2.c (working copy)
@@ -1,8 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-Winline -O2" } */
-inline __attribute__ ((always_inline)) void t(void); /* { dg-message
"sorry\[^\n\]*body not available" "" } */
+/* { dg-options "-O2" } */
+inline __attribute__ ((always_inline)) void t(void); /* { dg-error "body not
available" } */
void
q(void)
{
- t(); /* { dg-message "sorry\[^\n\]*called
from here" "" } */
+ t(); /* { dg-error "called from here" } */
}
Index: testsuite/gcc.dg/uninit-pred-5_b.c
===================================================================
--- testsuite/gcc.dg/uninit-pred-5_b.c (revision 175201)
+++ testsuite/gcc.dg/uninit-pred-5_b.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Wuninitialized -O2" } */
+/* { dg-options "-Wuninitialized -Wno-attributes -O2" } */
int g;
int bar();
Index: testsuite/gcc.dg/inline_4.c
===================================================================
--- testsuite/gcc.dg/inline_4.c (revision 175201)
+++ testsuite/gcc.dg/inline_4.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
-/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline=foo2
-fdisable-ipa-inline" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline=foo2
-fdisable-ipa-inline -Wno-attributes" } */
int g;
__attribute__((always_inline)) void bar (void)
{
Index: testsuite/gcc.dg/lto/20090218-1_0.c
===================================================================
--- testsuite/gcc.dg/lto/20090218-1_0.c (revision 175201)
+++ testsuite/gcc.dg/lto/20090218-1_0.c (working copy)
@@ -1,4 +1,4 @@
-void set_mem_alias_set () __attribute__ ((always_inline));
+void inline set_mem_alias_set () __attribute__ ((always_inline));
void emit_push_insn () {
set_mem_alias_set ();
}
Index: testsuite/gcc.dg/lto/20090218-1_1.c
===================================================================
--- testsuite/gcc.dg/lto/20090218-1_1.c (revision 175201)
+++ testsuite/gcc.dg/lto/20090218-1_1.c (working copy)
@@ -4,6 +4,6 @@
}
static void __attribute__ ((noinline)) get_mem_attrs () {
}
-void __attribute__ ((always_inline)) set_mem_alias_set () {
+void inline __attribute__ ((always_inline)) set_mem_alias_set () {
get_mem_attrs ();
}
Index: testsuite/gcc.dg/torture/pta-structcopy-1.c
===================================================================
--- testsuite/gcc.dg/torture/pta-structcopy-1.c (revision 175201)
+++ testsuite/gcc.dg/torture/pta-structcopy-1.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-fdump-tree-ealias" } */
+/* { dg-options "-fdump-tree-ealias -Wno-attributes" } */
/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
struct X
Index: testsuite/gcc.dg/tree-ssa/pr40087.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/pr40087.c (revision 175201)
+++ testsuite/gcc.dg/tree-ssa/pr40087.c (working copy)
@@ -3,7 +3,7 @@
extern void abort (void);
-static void __attribute__((always_inline))
+static inline void __attribute__((always_inline))
reverse(int *first, int *last)
{
if (first == last--)
Index: testsuite/gcc.dg/always_inline3.c
===================================================================
--- testsuite/gcc.dg/always_inline3.c (revision 175201)
+++ testsuite/gcc.dg/always_inline3.c (working copy)
@@ -1,11 +1,11 @@
/* { dg-do compile } */
-/* { dg-options "-Winline -O2" } */
+/* { dg-options "-O2" } */
int do_something_evil (void);
inline __attribute__ ((always_inline)) void
-q2(void) /* { dg-message "sorry\[^\n\]*recursive" "" } */
+q2(void) /* { dg-error "recursive inlining" } */
{
if (do_something_evil ())
return;
- q2(); /* { dg-message "sorry\[^\n\]*called from here"
"" } */
+ q2(); /* { dg-error "called from here" } */
q2(); /* With -O2 we don't warn here, it is eliminated by tail recursion. */
}
Index: testsuite/gcc.dg/inline_1.c
===================================================================
--- testsuite/gcc.dg/inline_1.c (revision 175201)
+++ testsuite/gcc.dg/inline_1.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline
-fdisable-ipa-inline" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdisable-tree-einline
-fdisable-ipa-inline -Wno-attributes" } */
int g;
__attribute__((always_inline)) void bar (void)
{
Index: testsuite/g++.dg/ipa/devirt-7.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-7.C (revision 175201)
+++ testsuite/g++.dg/ipa/devirt-7.C (working copy)
@@ -56,7 +56,7 @@
return 1;
}
-int __attribute__ ((always_inline))
+int inline __attribute__ ((always_inline))
A::middleman_1 (int i)
{
return this->foo (i);