Commit a674c7b8 by David Malcolm

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.
parent 68f9c41d
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> 2020-02-17 David Malcolm <dmalcolm@redhat.com>
PR analyzer/93775 PR analyzer/93775
......
...@@ -6514,24 +6514,27 @@ region_model::convert_byte_offset_to_array_index (tree ptr_type, ...@@ -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 /* Arithmetic on void-pointers is a GNU C extension, treating the size
of a void as 1. of a void as 1.
https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html 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. */
if (TREE_CODE (elem_type) == VOID_TYPE) if (TREE_CODE (elem_type) == VOID_TYPE)
return offset_sid; return offset_sid;
/* This might not be a constant. */ /* First, use int_size_in_bytes, to reject the case where we have an
tree byte_size = size_in_bytes (elem_type); incomplete type, or a non-constant value. */
HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type);
/* Try to get a constant by dividing, ensuring that we're in a if (hwi_byte_size > 0)
signed representation first. */ {
tree index /* Now call size_in_bytes to get the answer in tree form. */
= fold_binary (TRUNC_DIV_EXPR, ssizetype, tree byte_size = size_in_bytes (elem_type);
fold_convert (ssizetype, offset_cst), gcc_assert (byte_size);
fold_convert (ssizetype, byte_size)); /* Try to get a constant by dividing, ensuring that we're in a
if (index && TREE_CODE (index) == INTEGER_CST) signed representation first. */
return get_or_create_constant_svalue (index); 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. /* Otherwise, we don't know the array index; generate a new unknown value.
......
2020-02-18 David Malcolm <dmalcolm@redhat.com> 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 PR analyzer/93779
* gfortran.dg/analyzer/pr88304-2.f90: New test, adapted from * gfortran.dg/analyzer/pr88304-2.f90: New test, adapted from
gfortran.fortran-torture/compile/pr88304-2.f90 gfortran.fortran-torture/compile/pr88304-2.f90
......
! { 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment