[committed] analyzer: fix ICE getting void return value (PR 93379)

Message ID 20200131193440.19881-1-dmalcolm@redhat.com
State New
Headers show
Series
  • [committed] analyzer: fix ICE getting void return value (PR 93379)
Related show

Commit Message

David Malcolm Jan. 31, 2020, 7:34 p.m.
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to master as r10-6383-gf1c807e887d43551bca0acc16a438d880cfaf7c9.

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/region-model.cc                      |  5 ++++-
 gcc/testsuite/gcc.dg/analyzer/torture/pr93379-2.c | 11 +++++++++++
 gcc/testsuite/gcc.dg/analyzer/torture/pr93379.c   |  2 ++
 3 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/torture/pr93379-2.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/torture/pr93379.c

-- 
2.21.0

Patch

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index f116c0ae7a2..d43aef3a4d7 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -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.  */
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
index 00000000000..6e533dbca68
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr93379-2.c
@@ -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
index 00000000000..01465cf60e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr93379.c
@@ -0,0 +1,2 @@ 
+/* { dg-do compile } */
+#include "../../torture/pr57330.c"