The following avoids diagnosing failed always-inlining on speculated
calls where the function has cleared DECL_DISREGARD_INLINE_LIMITS
because we earlier detected recursive callgraph edges.  Instead
of just checking for the always_inline attribute we should also
check that always-inlining is still active before diagnosing.

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

This regresses

FAIL: gcc.dg/always_inline3.c  (test for errors, line 5)
FAIL: gcc.dg/always_inline3.c  (test for warnings, line 9)

which looks for the diagnostic.  It seems to me that disabling
DECL_DISREGARD_INLINE_LIMITS in inline_small_functions is
overly aggressive and also affects not recursive calls as I
see

../../../../ompi/mca/part/persist/part_persist.h:484:1: error: inlining 
failed in call to 'always_inline' 'mca_part_persist_start': --param 
max-inline-insns-single limit reached

so another fix would be to remove this and instead properly guard
whatever code breaks?

        PR ipa/123459
        * tree-inline.cc (expand_call_inline): Check
        DECL_DISREGARD_INLINE_LIMITS before diagnosting a failed
        always-inlining.

        * gcc.dg/torture/pr123459.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr123459.c | 22 ++++++++++++++++++++++
 gcc/tree-inline.cc                      |  3 +++
 2 files changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr123459.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr123459.c 
b/gcc/testsuite/gcc.dg/torture/pr123459.c
new file mode 100644
index 00000000000..711ec1d3721
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr123459.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+struct handler_chain {
+    struct handler_chain *next;
+    void (*handler)(struct handler_chain *);
+};
+
+__attribute__((always_inline))
+static inline
+void noop_handler(struct handler_chain *h)
+{
+    h = h->next;
+    if (h) {
+        h->handler(h);
+    }
+}
+
+void test(struct handler_chain *h)
+{
+    h->handler = noop_handler;
+    noop_handler(h);
+}
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index df5597ef30d..37b1ff56caa 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -4910,6 +4910,9 @@ expand_call_inline (basic_block bb, gimple *stmt, 
copy_body_data *id,
        goto egress;
 
       if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
+         /* Make sure we didn't disabling always_inline previously
+            when detecting self-recursion.  */
+         && DECL_DISREGARD_INLINE_LIMITS (fn)
           /* For extern inline functions that get redefined we always
             silently ignored always_inline flag. Better behavior would
             be to be able to keep both bodies and use extern inline body
-- 
2.51.0

Reply via email to