diff options
author | David Malcolm <dmalcolm@redhat.com> | 2020-02-17 09:18:39 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-02-18 08:12:06 -0500 |
commit | a674c7b8b8028c5d7e52dd38783e8e2b02034b63 (patch) | |
tree | c5aaa4e81dd37da06b6b6a74c77efa2ea63b502e | |
parent | 68f9c41d54a7839e90d10e1400c8726c8ccde88d (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/analyzer/region-model.cc | 33 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/analyzer/deferred_character_25.f90 | 32 |
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 |