aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-02-17 09:18:39 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2020-02-18 08:12:06 -0500
commita674c7b8b8028c5d7e52dd38783e8e2b02034b63 (patch)
treec5aaa4e81dd37da06b6b6a74c77efa2ea63b502e
parent68f9c41d54a7839e90d10e1400c8726c8ccde88d (diff)
downloadgcc-a674c7b8b8028c5d7e52dd38783e8e2b02034b63.zip
gcc-a674c7b8b8028c5d7e52dd38783e8e2b02034b63.tar.gz
gcc-a674c7b8b8028c5d7e52dd38783e8e2b02034b63.tar.bz2
analyzer: fix ICE on pointer arithmetic with incomplete types [PR 93774]
PR analyzer/93774 reports an ICE in gfortran with -fanalyzer within region_model::convert_byte_offset_to_array_index on a pointer of incomplete type ("character(kind=1)[0:][1:0] * restrict"). This patch bulletproofs the routine against incomplete types, fixing the ICE. gcc/analyzer/ChangeLog: PR analyzer/93774 * region-model.cc (region_model::convert_byte_offset_to_array_index): Use int_size_in_bytes before calling size_in_bytes, to gracefully fail on incomplete types. gcc/testsuite/ChangeLog: PR analyzer/93774 * gfortran.dg/analyzer/deferred_character_25.f90: New test, based on gfortran.dg/deferred_character_25.f90.
-rw-r--r--gcc/analyzer/ChangeLog8
-rw-r--r--gcc/analyzer/region-model.cc33
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gfortran.dg/analyzer/deferred_character_25.f9032
4 files changed, 64 insertions, 15 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index f9fd80c..9e57209 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,11 @@
+2020-02-18 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/93774
+ * region-model.cc
+ (region_model::convert_byte_offset_to_array_index): Use
+ int_size_in_bytes before calling size_in_bytes, to gracefully fail
+ on incomplete types.
+
2020-02-17 David Malcolm <dmalcolm@redhat.com>
PR analyzer/93775
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index deb2015..659255a 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -6514,24 +6514,27 @@ region_model::convert_byte_offset_to_array_index (tree ptr_type,
/* Arithmetic on void-pointers is a GNU C extension, treating the size
of a void as 1.
- https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
-
- Returning early for this case avoids a diagnostic from within the
- call to size_in_bytes. */
+ https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html */
if (TREE_CODE (elem_type) == VOID_TYPE)
return offset_sid;
- /* This might not be a constant. */
- tree byte_size = size_in_bytes (elem_type);
-
- /* Try to get a constant by dividing, ensuring that we're in a
- signed representation first. */
- tree index
- = fold_binary (TRUNC_DIV_EXPR, ssizetype,
- fold_convert (ssizetype, offset_cst),
- fold_convert (ssizetype, byte_size));
- if (index && TREE_CODE (index) == INTEGER_CST)
- return get_or_create_constant_svalue (index);
+ /* First, use int_size_in_bytes, to reject the case where we have an
+ incomplete type, or a non-constant value. */
+ HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type);
+ if (hwi_byte_size > 0)
+ {
+ /* Now call size_in_bytes to get the answer in tree form. */
+ tree byte_size = size_in_bytes (elem_type);
+ gcc_assert (byte_size);
+ /* Try to get a constant by dividing, ensuring that we're in a
+ signed representation first. */
+ tree index
+ = fold_binary (TRUNC_DIV_EXPR, ssizetype,
+ fold_convert (ssizetype, offset_cst),
+ fold_convert (ssizetype, byte_size));
+ if (index && TREE_CODE (index) == INTEGER_CST)
+ return get_or_create_constant_svalue (index);
+ }
}
/* Otherwise, we don't know the array index; generate a new unknown value.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c6b76df..3bc22ec 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2020-02-18 David Malcolm <dmalcolm@redhat.com>
+ PR analyzer/93774
+ * gfortran.dg/analyzer/deferred_character_25.f90: New test,
+ based on gfortran.dg/deferred_character_25.f90.
+
+2020-02-18 David Malcolm <dmalcolm@redhat.com>
+
PR analyzer/93779
* gfortran.dg/analyzer/pr88304-2.f90: New test, adapted from
gfortran.fortran-torture/compile/pr88304-2.f90
diff --git a/gcc/testsuite/gfortran.dg/analyzer/deferred_character_25.f90 b/gcc/testsuite/gfortran.dg/analyzer/deferred_character_25.f90
new file mode 100644
index 0000000..81877b0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/analyzer/deferred_character_25.f90
@@ -0,0 +1,32 @@
+! { dg-do compile }
+! { dg-additional-options "-Wno-analyzer-too-complex" }
+
+! Copy of gfortran.dg/deferred_character_25.f90
+! as a regression test for ICE with -fanalyzer (PR analyzer/93774)
+
+PROGRAM TEST
+ IMPLICIT NONE
+ INTEGER, PARAMETER :: I = 3
+ character (len = i), parameter :: str(5) = ['abc','cde','fgh','ijk','lmn']
+
+ TYPE T
+ CHARACTER(LEN=:), ALLOCATABLE :: C(:)
+ END TYPE T
+ TYPE(T), TARGET :: S
+ CHARACTER (LEN=I), POINTER :: P(:)
+
+ ALLOCATE ( CHARACTER(LEN=I) :: S%C(5) )
+ s%c = str
+
+! This PR uncovered several problems associated with determining the
+! element length and indexing. Test fairly thoroughly!
+ if (SIZE(S%C, 1) .ne. 5) stop 1
+ if (LEN(S%C) .ne. 3) stop 2
+ if (any (s%c .ne. str)) stop 3
+ if (s%c(3) .ne. str(3)) stop 4
+ P => S%C
+ if (SIZE(p, 1) .ne. 5) stop 5
+ if (LEN(p) .ne. 3) stop 6
+ if (any (p .ne. str)) stop 7
+ if (p(5) .ne. str(5)) stop 8
+END PROGRAM TEST