analyzer: fix ICE getting void return value (PR 93379)
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 31 Jan 2020 17:05:03 +0000 (12:05 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Fri, 31 Jan 2020 19:29:09 +0000 (14:29 -0500)
PR analyzer/93379 reports an ICE within
region_model::update_for_return_superedge when writing the
returned svalue_id to the lhs of the call_stmt

The root cause is that this analyzer code assumed that for any call
with a non-NULL gimple_call_lhs, the called fndecl would have non-void
return type, and thus that a non-null svalue_id would be returned from
region_model::pop_frame.  This isn't the case e.g. for a call with
conflicting types where the callee returns void but the caller assumes
int.

This patch fixes the ICE by moving the check for null result so that
it also guards setting the lhs.

gcc/analyzer/ChangeLog:
PR analyzer/93379
* region-model.cc (region_model::update_for_return_superedge):
Move check for null result so that it also guards setting the
lhs.

gcc/testsuite/ChangeLog:
PR analyzer/93379
* gcc.dg/analyzer/torture/pr93379-2.c: New test.
* gcc.dg/analyzer/torture/pr93379.c: New test.

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

index 8806a775acb14356667e9150e3eacc098486f756..fa791f70d34de112bcbf87c1ebb358d2f6de2ca1 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-31  David Malcolm  <dmalcolm@redhat.com>
+
+       PR analyzer/93379
+       * region-model.cc (region_model::update_for_return_superedge):
+       Move check for null result so that it also guards setting the
+       lhs.
+
 2020-01-31  David Malcolm  <dmalcolm@redhat.com>
 
        PR analyzer/93438
index f116c0ae7a28788217e0d4863d2f692284708bc3..d43aef3a4d79e07f75d97b5f4852ec3d2d0d46ec 100644 (file)
@@ -5694,12 +5694,15 @@ region_model::update_for_return_superedge (const return_superedge &return_edge,
   svalue_id result_sid = pop_frame (true, &stats, ctxt);
   // TODO: do something with the stats?
 
+  if (result_sid.null_p ())
+    return;
+
   /* Set the result of the call, within the caller frame.  */
   const gcall *call_stmt = return_edge.get_call_stmt ();
   tree lhs = gimple_call_lhs (call_stmt);
   if (lhs)
     set_value (get_lvalue (lhs, ctxt), result_sid, ctxt);
-  else if (!result_sid.null_p ())
+  else
     {
       /* This could be a leak; try purging again, but this time,
         don't special-case the result_sid.  */
index f8051b44085035af09beb2cfdb3258b02f03bca8..cce52ea696109fedfec30866d3b92370e183143c 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-31  David Malcolm  <dmalcolm@redhat.com>
+
+       PR analyzer/93379
+       * gcc.dg/analyzer/torture/pr93379-2.c: New test.
+       * gcc.dg/analyzer/torture/pr93379.c: New test.
+
 2020-01-31  David Malcolm  <dmalcolm@redhat.com>
 
        PR analyzer/93438
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr93379-2.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr93379-2.c
new file mode 100644 (file)
index 0000000..6e533db
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wno-implicit-function-declaration" } */
+
+void foo (void)
+{
+  int i = actually_returns_void ();
+}
+
+void actually_returns_void (void) /* { dg-warning "conflicting types" } */
+{
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr93379.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr93379.c
new file mode 100644 (file)
index 0000000..01465cf
--- /dev/null
@@ -0,0 +1,2 @@
+/* { dg-do compile } */
+#include "../../torture/pr57330.c"