aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/fortran/expr.cc1
-rw-r--r--gcc/fortran/primary.cc13
-rw-r--r--gcc/testsuite/gfortran.dg/actual_array_subref.f90103
3 files changed, 113 insertions, 4 deletions
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 07e9bac..92a9ebd 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 161d4c2..72ecc7c 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 0000000..932d7ab
--- /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