Hi,

with -fno-toplevel-reorder (and -fwhole-program), there apparently can
be local functions without any callers.  This is something that IPA-CP
does not like because its propagation verifier checks that local
functions do not end up with TOP in their lattices.  Therefore there
is an assert checking that all call-less unreachable functions have
been removed, which triggers in PR 106260 with these two options.

This patch detects the situation and marks the lattices as variable,
thus avoiding both the assert trigger and the verification failure.

Bootstrapped and tested on x86_64-linux.  OK for master and then all
active release branches?

Thanks,

Martin


gcc/ChangeLog:

2022-07-13  Martin Jambor  <mjam...@suse.cz>

        PR ipa/106260
        * ipa-cp.cc (initialize_node_lattices): Replace assert that there are
        callers with handling that situation when -fno-toplevel_reorder.

gcc/testsuite/ChangeLog:

2022-07-13  Martin Jambor  <mjam...@suse.cz>

        PR ipa/106260
        * g++.dg/ipa/pr106260.C: New test.
---
 gcc/ipa-cp.cc                       |  6 ++-
 gcc/testsuite/g++.dg/ipa/pr106260.C | 64 +++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ipa/pr106260.C

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 543a9334e2c..f699a8dadc0 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1286,10 +1286,14 @@ initialize_node_lattices (struct cgraph_node *node)
       int caller_count = 0;
       node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
                                                true);
-      gcc_checking_assert (caller_count > 0);
       if (caller_count == 1)
        node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
                                                  NULL, true);
+      else if (caller_count == 0)
+       {
+         gcc_checking_assert (!opt_for_fn (node->decl, flag_toplevel_reorder));
+         variable = true;
+       }
     }
   else
     {
diff --git a/gcc/testsuite/g++.dg/ipa/pr106260.C 
b/gcc/testsuite/g++.dg/ipa/pr106260.C
new file mode 100644
index 00000000000..bd3b6e0af79
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr106260.C
@@ -0,0 +1,64 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=gnu++14 -fwhole-program -fno-unit-at-a-time" }
+
+struct A;
+template <class T>
+struct Q { Q (T); };
+template<typename T, class D>
+struct U {
+  ~U () { m1 (nullptr); }
+  D m2 ();
+  T *u;
+  void m1 (T *) { m2 () (u); }
+};
+struct F { F (int *); };
+template <class, class T = F>
+using W = Q<T>;
+int a, b;
+void fn1 (void *);
+template <class T>
+void
+fn2 (T *x)
+{
+  if (x)
+    x->~T();
+  fn1 (x);
+}
+template <typename T>
+struct C {
+  void operator() (T *x) { fn2 (x); }
+};
+struct D;
+template <typename T, typename D = C<T> >
+using V = U<T, D>;
+struct A {
+  A (int *);
+};
+struct S;
+struct G {
+  V<S> m3 ();
+};
+struct S {
+  int e;
+  virtual ~S () {}
+};
+template<typename T>
+struct H {
+  H (int, T x, int) : h(x) {}
+  G g;
+  void m4 () { g.m3 (); }
+  T h;
+};
+struct I {
+  I(A, W<D>);
+};
+void
+test ()
+{
+  A c (&b);
+  W<D> d (&b);
+  I e (c, d);
+  H<I> f (0, e, a);
+  f.m4 ();
+}
+
-- 
2.36.1

Reply via email to