Hi all, this rather old PR reported a parsing bug, when a coarray'ed character substring ref is to be parsed, aka CHARACTER(:) :: str[:] ... str(2:5). In this case the parser confused the substring ref with an array-ref, because an array_spec was present. This patch fixes this by requesting only coarray parsing from gfc_match_array_ref when no regular dimension is present. The patch is not involved when an array of coarray'ed strings is parsed (that worked beforehand).
I had to fix the dg-error clauses in the testcase pr102532 because now the error of having to many refs is detected by the parsing stage and no longer by the resolve stage. It has become a simple syntax error. I hope this is ok. Regtests ok on x86_64-pc-linux-gnu / Fedora 39. Ok for mainline? Regards, Andre -- Andre Vehreschild * Email: vehre ad gmx dot de
From 1d5e0abd0e6df0ec05c3dfb4bf7cee433b885994 Mon Sep 17 00:00:00 2001 From: Andre Vehreschild <ve...@gcc.gnu.org> Date: Tue, 1 Oct 2024 09:30:59 +0200 Subject: [PATCH] [Fortran] 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. gcc/testsuite/ChangeLog: * gfortran.dg/pr102532.f90: Fix dg-errors: Now a syntax error. * gfortran.dg/coarray/substring_1.f90: New test. --- gcc/fortran/array.cc | 9 ++++-- gcc/fortran/match.h | 3 +- gcc/fortran/primary.cc | 30 ++++++++++++------- .../gfortran.dg/coarray/substring_1.f90 | 16 ++++++++++ gcc/testsuite/gfortran.dg/pr102532.f90 | 13 ++++---- 5 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/coarray/substring_1.f90 diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc index 1fa61ebfe2a..ed8cb54803b 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 84d84b81825..2c76afb179a 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 09add925fcd..d73d5eaed84 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) { 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 00000000000..3c3ddc7fac4 --- /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 714379a6ac2..999ca88482f 100644 --- a/gcc/testsuite/gfortran.dg/pr102532.f90 +++ b/gcc/testsuite/gfortran.dg/pr102532.f90 @@ -5,12 +5,15 @@ ! 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 "Expected '\\)' or ','" } + end associate ! { dg-error "Expecting END SUBROUTINE" } + associate (a => c(:)(:)(2:)) ! { dg-error "Expected '\\)' or ','" } + 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 + associate (y => x(:)(:)) ! { dg-error "Expected '\\)' or ','" } + end associate ! { dg-error "Expecting END SUBROUTINE" } +end -- 2.46.2