analyzer: fix ICE on unreachable calls [PR 93947]
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 26 Feb 2020 14:43:57 +0000 (09:43 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 27 Feb 2020 02:02:53 +0000 (21:02 -0500)
PR analyzer/93947 reports an ICE at -O1 when attempting to analyze a
call that has been optimized away as unreachable.

The root cause is a NULL dereference due to the fndecl having a NULL
cgraph_node: the cgraph_node was created by
pass_build_cgraph_edges::execute, but was later removed by
symbol_table::remove_unreachable_nodes before the analyzer pass.

This patch fixes it by checking for NULL before handling the
cgraph_node.

The reproducer demonstrates a weakness in the analyzer's constraint
handling, where region_model::apply_constraints_for_gswitch fails
to spot when the cases fully cover the data type, and thus make the
default impossible.  For now this is xfail-ed in the testcase.

gcc/analyzer/ChangeLog:
PR analyzer/93947
* region-model.cc (region_model::get_fndecl_for_call): Gracefully
fail for fn_decls that don't have a cgraph_node.

gcc/testsuite/ChangeLog:
PR analyzer/93947
* gcc.dg/analyzer/torture/pr93947.c: New test.

gcc/analyzer/ChangeLog
gcc/analyzer/region-model.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/analyzer/torture/pr93947.c [new file with mode: 0644]

index 982cc3ca9fd48643cfe3656acc9c4cb10b2f3f24..92377be49929263c728fb5e081193717560683c4 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-26  David Malcolm  <dmalcolm@redhat.com>
+
+       PR analyzer/93947
+       * region-model.cc (region_model::get_fndecl_for_call): Gracefully
+       fail for fn_decls that don't have a cgraph_node.
+
 2020-02-26  David Malcolm  <dmalcolm@redhat.com>
 
        * bar-chart.cc: New file.
index a71884d7b118699ca38de3a210064305cb29a1b5..b2179bd220aa4d34863540393095a73ec9012a6d 100644 (file)
@@ -6732,8 +6732,10 @@ region_model::get_fndecl_for_call (const gcall *call,
          tree fn_decl = code->get_tree_for_child_region (fn_rid);
          if (!fn_decl)
            return NULL_TREE;
-         const cgraph_node *ultimate_node
-           = cgraph_node::get (fn_decl)->ultimate_alias_target ();
+         cgraph_node *node = cgraph_node::get (fn_decl);
+         if (!node)
+           return NULL_TREE;
+         const cgraph_node *ultimate_node = node->ultimate_alias_target ();
          if (ultimate_node)
            return ultimate_node->decl;
        }
index 105fa854160cb02cf2f07cbe2785e1cd805fbb56..c6158b38ca07909b306f4c1ed3d15f9eeb6a5b8f 100644 (file)
@@ -1,3 +1,8 @@
+2020-02-26  David Malcolm  <dmalcolm@redhat.com>
+
+       PR analyzer/93947
+       * gcc.dg/analyzer/torture/pr93947.c: New test.
+
 2020-02-26  Iain Sandoe  <iain@sandoe.co.uk>
 
        * g++.dg/coroutines/coro1-refs-and-ctors.h: New.
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr93947.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr93947.c
new file mode 100644 (file)
index 0000000..73982ef
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+#include "../analyzer-decls.h"
+
+struct pf {
+  unsigned int iu : 2;
+};
+
+enum {
+  qr, jv, vm, mz,
+};
+
+int uh;
+
+void
+w9 (struct pf *x2)
+{
+  /* We ought to know the following based on the bitfield width.  */
+  __analyzer_eval (x2->iu >= 0 ); /* { dg-warning "TRUE" } */
+  __analyzer_eval (x2->iu < 4 ); /* { dg-warning "TRUE" } */
+
+  switch (x2->iu)
+    {
+    case qr:
+    case jv:
+    case vm:
+      uh = 0;
+      break;
+
+    case mz:
+      break;
+
+    default:
+      /* We ought to know from the enum values that this code is unreachable,
+        and thus not print anything.
+        TODO(xfail): currently this doesn't work.  */
+      __analyzer_eval (x2->iu); /* { dg-bogus "" "" { xfail *-*-* } } */
+      __builtin_abort ();
+    }
+}