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

Andrew Burgess andrew.burgess@embecosm.com
Thu Oct 22 10:42:16 GMT 2020


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
> 


More information about the Gdb-patches mailing list