Dear all, the attached, semi-obvious patch fixes bugging issues with passing of array subreferences when either an inquiry reference to a complex array or a substring reference to a character array was involved, and the array was a component of a derived type. The obvious cause was always an early termination of the scan of the reference.
The original PR was about complex issues, but since I was aware of a similar issue for substrings, I fixed that at the same time. Regtested on x86_64-pc-linux-gnu. OK for mainline? As this is a hideous wrong-code bug, I'd like to backport to at least 15-branch, if this is ok. Thanks, Harald
From 8d49cd9e0fe76d2c45495017cb87588e9b9824cf Mon Sep 17 00:00:00 2001 From: Harald Anlauf <anl...@gmx.de> Date: Sat, 3 May 2025 20:35:57 +0200 Subject: [PATCH] Fortran: array subreferences and components of derived types [PR119986] PR fortran/119986 gcc/fortran/ChangeLog: * expr.cc (is_subref_array): When searching for array references, do not terminate early so that inquiry references to complex components work. * primary.cc (gfc_variable_attr): A substring reference can refer to either a scalar or array character variable. Adjust search accordingly. gcc/testsuite/ChangeLog: * gfortran.dg/actual_array_subref.f90: New test. --- gcc/fortran/expr.cc | 1 + gcc/fortran/primary.cc | 13 ++- .../gfortran.dg/actual_array_subref.f90 | 103 ++++++++++++++++++ 3 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/actual_array_subref.f90 diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index 07e9bac37a1..92a9ebdcbe8 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -1194,6 +1194,7 @@ is_subref_array (gfc_expr * e) what follows cannot be a subreference array, unless there is a substring reference. */ if (!seen_array && ref->type == REF_COMPONENT + && ref->next == NULL && ref->u.c.component->ts.type != BT_CHARACTER && ref->u.c.component->ts.type != BT_CLASS && !gfc_bt_struct (ref->u.c.component->ts.type)) diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc index 161d4c26964..72ecc7ccf93 100644 --- a/gcc/fortran/primary.cc +++ b/gcc/fortran/primary.cc @@ -2893,6 +2893,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) gfc_symbol *sym; gfc_component *comp; bool has_inquiry_part; + bool has_substring_ref = false; if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION @@ -2955,7 +2956,12 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) has_inquiry_part = false; for (ref = expr->ref; ref; ref = ref->next) - if (ref->type == REF_INQUIRY) + if (ref->type == REF_SUBSTRING) + { + has_substring_ref = true; + optional = false; + } + else if (ref->type == REF_INQUIRY) { has_inquiry_part = true; optional = false; @@ -3003,9 +3009,8 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) *ts = comp->ts; /* Don't set the string length if a substring reference follows. */ - if (ts->type == BT_CHARACTER - && ref->next && ref->next->type == REF_SUBSTRING) - ts->u.cl = NULL; + if (ts->type == BT_CHARACTER && has_substring_ref) + ts->u.cl = NULL; } if (comp->ts.type == BT_CLASS) diff --git a/gcc/testsuite/gfortran.dg/actual_array_subref.f90 b/gcc/testsuite/gfortran.dg/actual_array_subref.f90 new file mode 100644 index 00000000000..932d7aba121 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/actual_array_subref.f90 @@ -0,0 +1,103 @@ +! { dg-do run } +! { dg-additional-options "-O2 -fcheck=bounds" } +! +! PR fortran/119986 +! +! Check passing of inquiry references of complex arrays and substring +! references of character arrays when these are components of derived types. +! +! Extended version of report by Neil Carlson. + +program main + implicit none + integer :: j + + complex, parameter :: z0(*) = [(cmplx(j,-j),j=1,4)] + type :: cx + real :: re + real :: im + end type cx + type(cx), parameter :: c0(*) = [(cx (j,-j),j=1,4)] + + type :: my_type + complex :: z(4) = z0 + type(cx) :: c(4) = c0 + end type my_type + type(my_type) :: x + + character(*), parameter :: s0(*) = ["abcd","efgh","ijkl","mnop"] + character(*), parameter :: expect(*) = s0(:)(2:3) + character(len(s0)) :: s1(4) = s0 + + type :: str1 + character(len(s0)) :: s(4) = s0 + end type str1 + type(str1) :: string1 + + type :: str2 + character(:), allocatable :: s(:) + end type str2 + type(str2) :: string2 + + integer :: stopcode = 0 + + if (len(expect) /= 2) stop 1 + if (expect(4) /= "no") stop 2 + if (any(c0 %re /= [ 1, 2, 3, 4])) stop 3 + if (any(c0 %im /= [-1,-2,-3,-4])) stop 4 + + stopcode = 10 + call fubar ( x%z %re, x%z %im) + call fubar ( x%c %re, x%c %im) + + stopcode = 20 + call fubar ((x%z %re), (x%z %im)) + call fubar ((x%c %re), (x%c %im)) + + stopcode = 30 + call fubar ([x%z %re], [x%z %im]) + call fubar ([x%c %re], [x%c %im]) + + stopcode = 50 + call chk ( s0(:)(2:3) ) + call chk ((s0(:)(2:3))) + call chk ([s0(:)(2:3)]) + + stopcode = 60 + call chk ( s1(:)(2:3) ) + call chk ((s1(:)(2:3))) + call chk ([s1(:)(2:3)]) + + stopcode = 70 + call chk ( string1%s(:)(2:3) ) + call chk ((string1%s(:)(2:3))) + call chk ([string1%s(:)(2:3)]) + + string2% s = s0 + if (len(string2%s) /= 4) stop 99 + stopcode = 80 + call chk ( string2%s(:)(2:3) ) + call chk ((string2%s(:)(2:3))) + call chk ([string2%s(:)(2:3)]) + deallocate (string2% s) + +contains + + subroutine fubar(u, v) + real, intent(in) :: u(:), v(:) + if (any (u /= z0%re)) stop stopcode + 1 + if (any (v /= z0%im)) stop stopcode + 2 + if (any (u /= c0%re)) stop stopcode + 3 + if (any (v /= c0%im)) stop stopcode + 4 + stopcode = stopcode + 4 + end subroutine + + subroutine chk (s) + character(*), intent(in) :: s(:) + if (size(s) /= 4) stop stopcode + 1 + if (len (s) /= 2) stop stopcode + 2 + if (any (s /= expect)) stop stopcode + 3 + stopcode = stopcode + 3 + end subroutine chk + +end program -- 2.43.0