Re: [PATCHv5 3/4] gdb/fortran: add support for parsing array strides in expressions

Andrew Burgess
2020-10-22T10:42:25Z

I've pushed patches 1, 2, and 3 from this series (after addressing the
issues Simon pointed out in #3).

I'll review the feedback on patch #4 and repost this soon.

Thanks,
Andrew

* Andrew Burgess <andrew.burgess@embecosm.com> [2020-10-11 19:12:12 +0100]:

> With this commit GDB now understands the syntax of Fortran array
> strides, a user can type an expression including an array stride, but
> they will only get an error informing them that array strides are not
> supported.
>
> This alone is an improvement on what we had before in GDB, better to
> give the user a helpful message that a particular feature is not
> supported than to just claim a syntax error.
>
> Before:
>
> (gdb) p array (1:10:2, 2:10:2)
> A syntax error in expression, near `:2, 2:10:2)'.
>
> Now:
>
> (gdb) p array (1:10:2, 2:10:2)
> Fortran array strides are not currently supported
>
> Later commits will allow GDB to handle array strides correctly.
>
> gdb/ChangeLog:
>
> * expprint.c (dump_subexp_body_standard): Print RANGE_HAS_STRIDE.
> * expression.h (enum range_type): Add RANGE_HAS_STRIDE.
> * f-exp.y (arglist): Allow for a series of subranges.
> (subrange): Add cases for subranges with strides.
> * f-lang.c (value_f90_subarray): Catch use of array strides and
> throw an error.
> * parse.c (operator_length_standard): Handle RANGE_HAS_STRIDE.
>
> gdb/testsuite/ChangeLog:
>
> * gdb.fortran/array-slices.exp: Add a new test.
> ---
> gdb/ChangeLog | 10 ++++++
> gdb/expprint.c | 4 +++
> gdb/expression.h | 3 ++
> gdb/f-exp.y | 38 ++++++++++++++++++++++
> gdb/f-lang.c | 10 +++++-
> gdb/parse.c | 2 ++
> gdb/testsuite/ChangeLog | 4 +++
> gdb/testsuite/gdb.fortran/array-slices.exp | 15 +++++++++
> 8 files changed, 85 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/expprint.c b/gdb/expprint.c
> index 2dee2bb1932..a14eeb00f19 100644
> --- a/gdb/expprint.c
> +++ b/gdb/expprint.c
> @@ -1120,12 +1120,16 @@ dump_subexp_body_standard (struct expression *exp,
> fputs_filtered ("..", stream);
> if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
> fputs_filtered ("EXP", stream);
> + if (range_flag & RANGE_HAS_STRIDE)
> + fputs_filtered (":EXP", stream);
> fputs_filtered ("'", stream);
>
> if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
> elt = dump_subexp (exp, stream, elt);
> if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
> elt = dump_subexp (exp, stream, elt);
> + if (range_flag & RANGE_HAS_STRIDE)
> + elt = dump_subexp (exp, stream, elt);
> }
> break;
>
> diff --git a/gdb/expression.h b/gdb/expression.h
> index fd483e5f277..8de712310ec 100644
> --- a/gdb/expression.h
> +++ b/gdb/expression.h
> @@ -199,6 +199,9 @@ enum range_flag : unsigned
>
> /* The high bound of this range is exclusive. */
> RANGE_HIGH_BOUND_EXCLUSIVE = 1 << 2,
> +
> + /* The range has a stride. */
> + RANGE_HAS_STRIDE = 1 << 3,
> };
>
> DEF_ENUM_FLAGS_TYPE (enum range_flag, range_flags);
> diff --git a/gdb/f-exp.y b/gdb/f-exp.y
> index a3314082d90..f227690cea6 100644
> --- a/gdb/f-exp.y
> +++ b/gdb/f-exp.y
> @@ -284,6 +284,10 @@ arglist : arglist ',' exp %prec ABOVE_COMMA
> { pstate->arglist_len++; }
> ;
>
> +arglist : arglist ',' subrange %prec ABOVE_COMMA
> + { pstate->arglist_len++; }
> + ;
> +
> /* There are four sorts of subrange types in F90. */
>
> subrange: exp ':' exp %prec ABOVE_COMMA
> @@ -314,6 +318,40 @@ subrange: ':' %prec ABOVE_COMMA
> write_exp_elt_opcode (pstate, OP_RANGE); }
> ;
>
> +/* And each of the four subrange types can also have a stride. */
> +subrange: exp ':' exp ':' exp %prec ABOVE_COMMA
> + { write_exp_elt_opcode (pstate, OP_RANGE);
> + write_exp_elt_longcst (pstate,
> + (RANGE_STANDARD
> + | RANGE_HAS_STRIDE));
> + write_exp_elt_opcode (pstate, OP_RANGE); }
> + ;
> +
> +subrange: exp ':' ':' exp %prec ABOVE_COMMA
> + { write_exp_elt_opcode (pstate, OP_RANGE);
> + write_exp_elt_longcst (pstate,
> + (RANGE_HIGH_BOUND_DEFAULT
> + | RANGE_HAS_STRIDE));
> + write_exp_elt_opcode (pstate, OP_RANGE); }
> + ;
> +
> +subrange: ':' exp ':' exp %prec ABOVE_COMMA
> + { write_exp_elt_opcode (pstate, OP_RANGE);
> + write_exp_elt_longcst (pstate,
> + (RANGE_LOW_BOUND_DEFAULT
> + | RANGE_HAS_STRIDE));
> + write_exp_elt_opcode (pstate, OP_RANGE); }
> + ;
> +
> +subrange: ':' ':' exp %prec ABOVE_COMMA
> + { write_exp_elt_opcode (pstate, OP_RANGE);
> + write_exp_elt_longcst (pstate,
> + (RANGE_LOW_BOUND_DEFAULT
> + | RANGE_HIGH_BOUND_DEFAULT
> + | RANGE_HAS_STRIDE));
> + write_exp_elt_opcode (pstate, OP_RANGE); }
> + ;
> +
> complexnum: exp ',' exp
> { }
> ;
> diff --git a/gdb/f-lang.c b/gdb/f-lang.c
> index 37d05b27653..b888e3d4122 100644
> --- a/gdb/f-lang.c
> +++ b/gdb/f-lang.c
> @@ -124,7 +124,7 @@ value_f90_subarray (struct value *array,
> struct expression *exp, int *pos, enum noside noside)
> {
> int pc = (*pos) + 1;
> - LONGEST low_bound, high_bound;
> + LONGEST low_bound, high_bound, stride;
> struct type *range = check_typedef (value_type (array)->index_type ());
> enum range_flag range_flag
> = (enum range_flag) longest_to_int (exp->elts[pc].longconst);
> @@ -141,6 +141,14 @@ value_f90_subarray (struct value *array,
> else
> high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
>
> + if ((range_flag & RANGE_HAS_STRIDE) == RANGE_HAS_STRIDE)
> + stride = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
> + else
> + stride = 1;
> +
> + if (stride != 1)
> + error (_("Fortran array strides are not currently supported"));
> +
> return value_slice (array, low_bound, high_bound - low_bound + 1);
> }
>
> diff --git a/gdb/parse.c b/gdb/parse.c
> index 4a15de8a499..359ab6211aa 100644
> --- a/gdb/parse.c
> +++ b/gdb/parse.c
> @@ -924,6 +924,8 @@ operator_length_standard (const struct expression *expr, int endpos,
> /* Assume the range has 2 arguments (low bound and high bound), then
> reduce the argument count if any bounds are set to default. */
> args = 2;
> + if (range_flag & RANGE_HAS_STRIDE)
> + ++args;
> if (range_flag & RANGE_LOW_BOUND_DEFAULT)
> --args;
> if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
> diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
> index 31f95a3668d..a0e1d1fe8fc 100644
> --- a/gdb/testsuite/gdb.fortran/array-slices.exp
> +++ b/gdb/testsuite/gdb.fortran/array-slices.exp
> @@ -69,3 +69,18 @@ foreach result $array_contents msg $message_strings {
> }
>
> gdb_continue_to_breakpoint "continue to Final Breakpoint"
> +
> +# Next test that asking for an array with stride at the CLI gives an
> +# error.
> +clean_restart ${testfile}
> +
> +if ![fortran_runto_main] then {
> + perror "couldn't run to main"
> + continue
> +}
> +
> +gdb_breakpoint "show"
> +gdb_continue_to_breakpoint "show"
> +gdb_test "up" ".*"
> +gdb_test "p array (1:10:2, 1:10:2)" \
> + "Fortran array strides are not currently supported"
> --
> 2.25.4
>