[PATCH] analyzer: fix ICE on failed casts [PR 93777]

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] analyzer: fix ICE on failed casts [PR 93777]

David Malcolm
PR analyzer/93777 reports ICEs in Fortran and C++ cases involving
a cast of a NULL pointer to a REFERENCE_TYPE.

In both cases the call to build_cast fails and returns a NULL type, but
region_model::maybe_cast_1 asserts that a non-NULL type was returned.

This patch fixes the ICEs by converting the assertion to a conditional.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

I think I have permission to self-approve the analyzer part and the C++
testcase.

Is the Fortran testcase OK for master?

gcc/analyzer/ChangeLog:
        PR analyzer/93777
        * region-model.cc (region_model::maybe_cast_1): Replace assertion
        that build_cast returns non-NULL with a conditional, falling
        through to the logic which returns a new unknown value of the
        desired type if it fails.

gcc/testsuite/ChangeLog:
        PR analyzer/93777
        * g++.dg/analyzer/pr93777.C: New test.
        * gfortran.dg/analyzer/pr93777.f90: New test.
---
 gcc/analyzer/region-model.cc                  |  7 +++---
 gcc/testsuite/g++.dg/analyzer/pr93777.C       |  1 +
 .../gfortran.dg/analyzer/pr93777.f90          | 22 +++++++++++++++++++
 3 files changed, 26 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/analyzer/pr93777.C
 create mode 100644 gcc/testsuite/gfortran.dg/analyzer/pr93777.f90

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c8ee031dc8f..d061552da37 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -5089,10 +5089,9 @@ region_model::maybe_cast_1 (tree dst_type, svalue_id sid)
   /* Attempt to cast constants.  */
   if (tree src_cst = sval->maybe_get_constant ())
     {
-      tree dst = build_cast (dst_type, src_cst);
-      gcc_assert (dst != NULL_TREE);
-      if (CONSTANT_CLASS_P (dst))
- return get_or_create_constant_svalue (dst);
+      if (tree dst = build_cast (dst_type, src_cst))
+ if (CONSTANT_CLASS_P (dst))
+  return get_or_create_constant_svalue (dst);
     }
 
   /* Otherwise, return a new unknown value.  */
diff --git a/gcc/testsuite/g++.dg/analyzer/pr93777.C b/gcc/testsuite/g++.dg/analyzer/pr93777.C
new file mode 100644
index 00000000000..e94e75f5e83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/pr93777.C
@@ -0,0 +1 @@
+#include "../../g++.old-deja/g++.pt/spec36.C"
diff --git a/gcc/testsuite/gfortran.dg/analyzer/pr93777.f90 b/gcc/testsuite/gfortran.dg/analyzer/pr93777.f90
new file mode 100644
index 00000000000..1c198358829
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/analyzer/pr93777.f90
@@ -0,0 +1,22 @@
+! { dg-additional-options "-O0 -Wno-analyzer-possible-null-dereference -Wno-analyzer-null-dereference -Wno-analyzer-malloc-leak" }
+
+program cb
+  implicit none
+  type :: jn
+     real, allocatable :: ie
+     character(len = :), allocatable :: e5
+  end type jn
+  real, parameter :: gm = 5.0
+
+  block
+    type(jn) :: r2
+
+    r2 = jn (gm, "")
+    call vz (r2%ie, gm)
+  end block
+contains
+  subroutine vz (arg1, arg2)
+    real :: arg1, arg2
+    if (arg1 .ne. arg2) STOP 1
+  end subroutine vz
+end program cb
--
2.21.0