https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128415
Bug ID: 128415
Summary: [17 regression] dtype incorrectly set for ALLOCATE
with an array subreference SOURCE
Product: gcc
Version: 17.0
URL: https://gcc.sashiko.dev/#/patchset/20261021092953.3158
4-1-morin-mikael%40orange.fr
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: mikael at gcc dot gnu.org
Target Milestone: ---
This is based on the AI review of the PR108033 fix (AKA r17-5758) at:
https://gcc.sashiko.dev/#/patchset/20261021092953.31584-1-morin-mikael%40orange.fr
More exactly, the testcase combines item 1 first bullet and item 2 first bullet
program prog
implicit none
integer, parameter :: n = 5
type :: t1
integer :: c1, c2
end type
type(t1), allocatable :: a(:)
integer :: i
a = [ (t1(2*i*i+1, 3*i+2), i=1,n) ]
call sub(a)
contains
subroutine sub(x)
type(t1), allocatable :: x(:)
class(*), pointer :: p(:)
allocate(p, source=x%c1)
if (.not. is_contiguous(p)) error stop 1
end subroutine
end program
This examples fails at runtime with ERROR STOP 1.
gfortran-16 executes it without error.
Citing the relevant parts of the URL above:
> Removing the gfc_get_parentheses wrapper here causes wrong-code and runtime
> heap buffer overflows when an array is allocated without an explicit shape
> specification from a non-character subreference array variable in SOURCE= or
> MOLD= (for example, allocate(xx, source=cmp%re), allocate(aa, source=x%c),
> or allocate(pp, source=cc%rr%re)).
> With this change, gfc_trans_allocate takes the EXPR_VARIABLE path for
> subreference arrays and calls gfc_conv_expr_descriptor (&se, code->expr3)
> with a default-initialized gfc_se (where se.direct_byref == 0 and
> se.force_no_tmp == 0) while leaving e3_has_nodescriptor false:
> 1. Inside gfc_conv_expr_descriptor (gcc/fortran/trans-array.cc),
> subref_array_target is false for expr->ts.type != BT_CHARACTER when both
> se->direct_byref and se->force_no_tmp are false, and
> gfc_ref_needs_temporary_p returns false for REF_COMPONENT and
> REF_INQUIRY.
> - If the base array is descriptor-backed (allocatable, pointer, or
> assumed-shape) and its array reference is AR_FULL followed by
> REF_COMPONENT or REF_INQUIRY, full remains 1 and
> gfc_conv_expr_descriptor returns the parent derived-type or complex
> array's descriptor directly in se.expr.
(...)
> 2. In gfc_array_init_size (gcc/fortran/trans-array.cc), the branch:
> else if (expr3_desc && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr3_desc)))
> gfc_conv_descriptor_dtype_set (pblock, descriptor,
> gfc_conv_descriptor_dtype_get
> (expr3_desc));
> copies expr3_desc's dtype directly into the newly allocated array's
> descriptor. The allocated array is stamped with the parent array's
> dtype.type (BT_COMPLEX or BT_DERIVED instead of BT_REAL or BT_INTEGER)
> and dtype.elem_len (e.g., 8 bytes instead of 4), while descriptor.span is
> set to 4 bytes. Consequently:
> - Calling is_contiguous(pp) on a freshly allocated pointer
> (real, pointer :: pp(:); allocate(pp, source=cc%rr%re)) compares
> span == dtype.elem_len (4 == 8) and wrongly evaluates to .false.