gdb/fortran: add support for parsing array strides in expressions
authorAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 8 Oct 2020 15:34:58 +0000 (16:34 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 22 Oct 2020 08:24:43 +0000 (09:24 +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
gdb/expprint.c
gdb/expression.h
gdb/f-exp.y
gdb/f-lang.c
gdb/parse.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.fortran/array-slices.exp

index d67de7c05a738fce3120d5ba4186e33f88fbf943..bf93e1b8a26e2e53cb41d80995a68c30eaaef336 100644 (file)
@@ -1,3 +1,13 @@
+2020-10-22  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * 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.
+
 2020-10-22  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * expprint.c (print_subexp_standard): Change enum range_type to
index 2dee2bb193285018699cbf4ae69d785b00fd9dfe..a14eeb00f19a25b13ac79f36eaa74d55cdee768f 100644 (file)
@@ -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;
 
index fd483e5f277fd9315e3a39b4e3213d4c308c6edd..8de712310ecfe72f9f08fdff3c4300f366d6e31b 100644 (file)
@@ -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);
index a3314082d909c252530aa27d152fe437d49128dd..eaa721424313b767f12dc8503725f817068b139f 100644 (file)
@@ -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,38 @@ 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_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 
                        { }                          
         ;
index 37d05b276537b2bdd36c28ee2fed93b51831cf78..f7c54b462a49ae9888ee42e2b4cb0d83223116bb 100644 (file)
@@ -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)
+    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);
 }
 
index 4a15de8a4993ed913d5bb486eb90737c77582740..359ab6211aae5ad02fd3f9a5ecb855daad0a93cf 100644 (file)
@@ -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)
index 4061d1789ccdd99d28bf539ae41d773e4c97e79a..19b423beb3c2080f50aa6d21ca95f9051013b293 100644 (file)
@@ -1,3 +1,7 @@
+2020-10-22  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.fortran/array-slices.exp: Add a new test.
+
 2020-10-21  Gary Benson <gbenson@redhat.com>
 
        * gdb.mi/mi-fullname-deleted.exp: Fix substituted
index 31f95a3668d0f6898cf2f8961b3b33c4026af52a..aa6bc6327eb8a36efdf9366e7eb349456ed617fa 100644 (file)
@@ -69,3 +69,19 @@ 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" \
+    "using array stride gives an error"