https://gcc.gnu.org/g:0ad2c76bea20dbeac753f10df6f9f86d142348d4

commit r15-4171-g0ad2c76bea20dbeac753f10df6f9f86d142348d4
Author: Andre Vehreschild <ve...@gcc.gnu.org>
Date:   Tue Oct 1 09:30:59 2024 +0200

    Fix parsing of substring refs in coarrays. [PR51815]
    
    The parser was greadily taking the substring ref as an array ref because
    an array_spec was present.  Fix this by only parsing the coarray (pseudo)
    ref when no regular array is present.
    
    gcc/fortran/ChangeLog:
    
            PR fortran/51815
    
            * array.cc (gfc_match_array_ref): Only parse coarray part of
            ref.
            * match.h (gfc_match_array_ref): Add flag.
            * primary.cc (gfc_match_varspec): Request only coarray ref
            parsing when no regular array is present.  Report error on
            unexpected additional ref.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/pr102532.f90: Fix dg-errors: Add new error.
            * gfortran.dg/coarray/substring_1.f90: New test.

Diff:
---
 gcc/fortran/array.cc                              |  9 ++++--
 gcc/fortran/match.h                               |  3 +-
 gcc/fortran/primary.cc                            | 35 ++++++++++++++++-------
 gcc/testsuite/gfortran.dg/coarray/substring_1.f90 | 16 +++++++++++
 gcc/testsuite/gfortran.dg/pr102532.f90            | 16 +++++++----
 5 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc
index 1fa61ebfe2a0..ed8cb54803b8 100644
--- a/gcc/fortran/array.cc
+++ b/gcc/fortran/array.cc
@@ -179,7 +179,7 @@ matched:
 
 match
 gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init,
-                    int corank)
+                    int corank, bool coarray_only)
 {
   match m;
   bool matched_bracket = false;
@@ -198,6 +198,8 @@ gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, 
int init,
        matched_bracket = true;
        goto coarray;
     }
+  else if (coarray_only && corank != 0)
+    goto coarray;
 
   if (gfc_match_char ('(') != MATCH_YES)
     {
@@ -243,11 +245,12 @@ gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec 
*as, int init,
 coarray:
   if (!matched_bracket && gfc_match_char ('[') != MATCH_YES)
     {
-      if (ar->dimen > 0)
+      int dim = coarray_only ? 0 : ar->dimen;
+      if (dim > 0 || coarray_only)
        {
          if (corank != 0)
            {
-             for (int i = ar->dimen; i < GFC_MAX_DIMENSIONS; ++i)
+             for (int i = dim; i < GFC_MAX_DIMENSIONS; ++i)
                ar->dimen_type[i] = DIMEN_THIS_IMAGE;
              ar->codimen = corank;
            }
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 84d84b818259..2c76afb179af 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -317,7 +317,8 @@ match gfc_match_init_expr (gfc_expr **);
 
 /* array.cc.  */
 match gfc_match_array_spec (gfc_array_spec **, bool, bool);
-match gfc_match_array_ref (gfc_array_ref *, gfc_array_spec *, int, int);
+match gfc_match_array_ref (gfc_array_ref *, gfc_array_spec *, int, int,
+                          bool = false);
 match gfc_match_array_constructor (gfc_expr **);
 
 /* interface.cc.  */
diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 09add925fcd1..c11359a559b2 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2192,7 +2192,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
   bool intrinsic;
   bool inferred_type;
   locus old_loc;
-  char sep;
+  char peeked_char;
 
   tail = NULL;
 
@@ -2282,9 +2282,10 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
        sym->ts.u.derived = tgt_expr->ts.u.derived;
     }
 
-  if ((inferred_type && !sym->as && gfc_peek_ascii_char () == '(')
-      || (equiv_flag && gfc_peek_ascii_char () == '(')
-      || gfc_peek_ascii_char () == '[' || sym->attr.codimension
+  peeked_char = gfc_peek_ascii_char ();
+  if ((inferred_type && !sym->as && peeked_char == '(')
+      || (equiv_flag && peeked_char == '(') || peeked_char == '['
+      || sym->attr.codimension
       || (sym->attr.dimension && sym->ts.type != BT_CLASS
          && !sym->attr.proc_pointer && !gfc_is_proc_ptr_comp (primary)
          && !(gfc_matching_procptr_assignment
@@ -2295,6 +2296,8 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
              || CLASS_DATA (sym)->attr.codimension)))
     {
       gfc_array_spec *as;
+      bool coarray_only = sym->attr.codimension && !sym->attr.dimension
+                         && sym->ts.type == BT_CHARACTER;
 
       tail = extend_ref (primary, tail);
       tail->type = REF_ARRAY;
@@ -2310,12 +2313,18 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
       else
        as = sym->as;
 
-      m = gfc_match_array_ref (&tail->u.ar, as, equiv_flag,
-                              as ? as->corank : 0);
+      m = gfc_match_array_ref (&tail->u.ar, as, equiv_flag, as ? as->corank : 
0,
+                              coarray_only);
       if (m != MATCH_YES)
        return m;
 
       gfc_gobble_whitespace ();
+      if (coarray_only)
+       {
+         primary->ts = sym->ts;
+         goto check_substring;
+       }
+
       if (equiv_flag && gfc_peek_ascii_char () == '(')
        {
          tail = extend_ref (primary, tail);
@@ -2333,14 +2342,13 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
     return MATCH_YES;
 
   /* With DEC extensions, member separator may be '.' or '%'.  */
-  sep = gfc_peek_ascii_char ();
+  peeked_char = gfc_peek_ascii_char ();
   m = gfc_match_member_sep (sym);
   if (m == MATCH_ERROR)
     return MATCH_ERROR;
 
   inquiry = false;
-  if (m == MATCH_YES && sep == '%'
-      && primary->ts.type != BT_CLASS
+  if (m == MATCH_YES && peeked_char == '%' && primary->ts.type != BT_CLASS
       && (primary->ts.type != BT_DERIVED || inferred_type))
     {
       match mm;
@@ -2453,7 +2461,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
            && m == MATCH_YES && !inquiry)
     {
       gfc_error ("Unexpected %<%c%> for nonderived-type variable %qs at %C",
-                sep, sym->name);
+                peeked_char, sym->name);
       return MATCH_ERROR;
     }
 
@@ -2484,7 +2492,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
          if (inquiry)
            sym = NULL;
 
-         if (sep == '%')
+         if (peeked_char == '%')
            {
              if (tmp)
                {
@@ -2815,6 +2823,11 @@ check_substring:
          if (substring)
            primary->ts.u.cl = NULL;
 
+         if (gfc_peek_ascii_char () == '(')
+           {
+             gfc_error_now ("Unexpected array/substring ref at %C");
+             return MATCH_ERROR;
+           }
          break;
 
        case MATCH_NO:
diff --git a/gcc/testsuite/gfortran.dg/coarray/substring_1.f90 
b/gcc/testsuite/gfortran.dg/coarray/substring_1.f90
new file mode 100644
index 000000000000..3c3ddc7fac42
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/substring_1.f90
@@ -0,0 +1,16 @@
+!{ dg-do run }
+
+! Test PR51815 is fixed
+! Contributed by Bill Long  <longb ad cray dot com>
+
+PROGRAM pr51815
+   implicit none
+   character(10) :: s[*]
+   character(18) :: d = 'ABCDEFGHIJKLMNOPQR'
+   integer       :: img
+
+   img = this_image()
+   s = d(img:img+9)
+   if (img == 1 .and. s(2:4) /= 'BCD') stop 1
+END PROGRAM
+
diff --git a/gcc/testsuite/gfortran.dg/pr102532.f90 
b/gcc/testsuite/gfortran.dg/pr102532.f90
index 714379a6ac27..cc6e2e9215a8 100644
--- a/gcc/testsuite/gfortran.dg/pr102532.f90
+++ b/gcc/testsuite/gfortran.dg/pr102532.f90
@@ -5,12 +5,18 @@
 !
 subroutine foo
    character(:), allocatable :: x[:]
-   associate (y => x(:)(2:)) ! { dg-error "Rank mismatch|deferred type 
parameter" }
-   end associate
+   character(:), dimension(:), allocatable :: c[:]
+   associate (y => x(:)(2:)) ! { dg-error "Unexpected array/substring 
ref|Invalid association target" }
+   end associate ! { dg-error "Expecting END SUBROUTINE" }
+   associate (a => c(:)(:)(2:)) ! { dg-error "Unexpected array/substring 
ref|Invalid association target" }
+   end associate ! { dg-error "Expecting END SUBROUTINE" }
 end
 
 subroutine bar
    character(:), allocatable :: x[:]
-   associate (y => x(:)(:)) ! { dg-error "Rank mismatch|deferred type 
parameter" }
-   end associate
-end
\ No newline at end of file
+   character(:), allocatable :: c
+   
+   associate (y => x(:)(:)) ! { dg-error "Unexpected array/substring 
ref|Invalid association target" }
+   end associate ! { dg-error "Expecting END SUBROUTINE" }
+   c = x(:)(2:5) ! { dg-error "Unexpected array/substring ref" }
+end

Reply via email to