ipa/96291: don't crash on unoptimized lto functions
authorSergei Trofimovich <siarheit@google.com>
Sat, 25 Jul 2020 18:26:50 +0000 (19:26 +0100)
committerSergei Trofimovich <siarheit@google.com>
Tue, 28 Jul 2020 22:19:00 +0000 (23:19 +0100)
In PR ipa/96291 the test contained an SCC with one
unoptimized function. This tricked ipa-cp into NULL dereference.

has_undead_caller_from_outside_scc_p() did not take into account
that unoptimized funtions don't have IPA summary analysis. And
dereferenced NULL pointer causing an ICE.

gcc/
PR ipa/96291
* ipa-cp.c (has_undead_caller_from_outside_scc_p): Consider
unoptimized callers as undead.

gcc/testsuite/
PR ipa/96291
* gcc.dg/lto/pr96291_0.c: New testcase.
* gcc.dg/lto/pr96291_1.c: Support file.
* gcc.dg/lto/pr96291_2.c: Likewise.
* gcc.dg/lto/pr96291.h: Likewise.

gcc/ipa-cp.c
gcc/testsuite/gcc.dg/lto/pr96291.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/pr96291_0.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/pr96291_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/pr96291_2.c [new file with mode: 0644]

index b0c8f40..fe010ff 100644 (file)
@@ -5667,8 +5667,9 @@ has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
          (has_undead_caller_from_outside_scc_p, NULL, true))
       return true;
     else if (!ipa_edge_within_scc (cs)
-            && !IPA_NODE_REF (cs->caller)->node_dead)
-      return true;
+            && (!IPA_NODE_REF (cs->caller) /* Unoptimized caller.  */
+                || !IPA_NODE_REF (cs->caller)->node_dead))
+         return true;
   return false;
 }
 
diff --git a/gcc/testsuite/gcc.dg/lto/pr96291.h b/gcc/testsuite/gcc.dg/lto/pr96291.h
new file mode 100644 (file)
index 0000000..70eb3cb
--- /dev/null
@@ -0,0 +1,4 @@
+void e(void);
+void f(void);
+void a(void *, void *);
+void c(int);
diff --git a/gcc/testsuite/gcc.dg/lto/pr96291_0.c b/gcc/testsuite/gcc.dg/lto/pr96291_0.c
new file mode 100644 (file)
index 0000000..07e6303
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-lto-do link } */
+
+#include "pr96291.h"
+
+static void * b;
+void c(int d) {
+  f();
+  a(b, b);
+}
+
+void e(void) { c(0); }
diff --git a/gcc/testsuite/gcc.dg/lto/pr96291_1.c b/gcc/testsuite/gcc.dg/lto/pr96291_1.c
new file mode 100644 (file)
index 0000000..44744a9
--- /dev/null
@@ -0,0 +1,3 @@
+#include "pr96291.h"
+
+void f(void) { c(0); }
diff --git a/gcc/testsuite/gcc.dg/lto/pr96291_2.c b/gcc/testsuite/gcc.dg/lto/pr96291_2.c
new file mode 100644 (file)
index 0000000..5febffb
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-options {-O0} } */
+
+#include "pr96291.h"
+
+void a(void * a1, void * a2) { e(); }
+
+int main(){}