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.

Reply via email to