blarsen / rpms / gdb

Forked from rpms/gdb 2 years ago
Clone
8594aea
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
8594aea
From: Kevin Buettner <kevinb@redhat.com>
8594aea
Date: Mon, 24 May 2021 22:30:32 -0700
8594aea
Subject: gdb-rhbz1964167-fortran-array-strides-in-expressions.patch
8594aea
8594aea
;; [fortran] Backport Andrew Burgess's commit which adds support
8594aea
;; for array strides in expressions.
8594aea
8594aea
gdb/fortran: add support for parsing array strides in expressions
8594aea
8594aea
With this commit GDB now understands the syntax of Fortran array
8594aea
strides, a user can type an expression including an array stride, but
8594aea
they will only get an error informing them that array strides are not
8594aea
supported.
8594aea
8594aea
This alone is an improvement on what we had before in GDB, better to
8594aea
give the user a helpful message that a particular feature is not
8594aea
supported than to just claim a syntax error.
8594aea
8594aea
Before:
8594aea
8594aea
  (gdb) p array (1:10:2, 2:10:2)
8594aea
  A syntax error in expression, near `:2, 2:10:2)'.
8594aea
8594aea
Now:
8594aea
8594aea
  (gdb) p array (1:10:2, 2:10:2)
8594aea
  Fortran array strides are not currently supported
8594aea
8594aea
Later commits will allow GDB to handle array strides correctly.
8594aea
8594aea
gdb/ChangeLog:
8594aea
8594aea
	* expprint.c (dump_subexp_body_standard): Print RANGE_HAS_STRIDE.
8594aea
	* expression.h (enum range_type): Add RANGE_HAS_STRIDE.
8594aea
	* f-exp.y (arglist): Allow for a series of subranges.
8594aea
	(subrange): Add cases for subranges with strides.
8594aea
	* f-lang.c (value_f90_subarray): Catch use of array strides and
8594aea
	throw an error.
8594aea
	* parse.c (operator_length_standard): Handle RANGE_HAS_STRIDE.
8594aea
8594aea
gdb/testsuite/ChangeLog:
8594aea
8594aea
	* gdb.fortran/array-slices.exp: Add a new test.
8594aea
8594aea
diff --git a/gdb/expprint.c b/gdb/expprint.c
8594aea
--- a/gdb/expprint.c
8594aea
+++ b/gdb/expprint.c
8594aea
@@ -1118,12 +1118,16 @@ dump_subexp_body_standard (struct expression *exp,
8594aea
 	fputs_filtered ("..", stream);
8594aea
 	if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
8594aea
 	  fputs_filtered ("EXP", stream);
8594aea
+	if (range_flag & RANGE_HAS_STRIDE)
8594aea
+	  fputs_filtered (":EXP", stream);
8594aea
 	fputs_filtered ("'", stream);
8594aea
 
8594aea
 	if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
8594aea
 	  elt = dump_subexp (exp, stream, elt);
8594aea
 	if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
8594aea
 	  elt = dump_subexp (exp, stream, elt);
8594aea
+	if (range_flag & RANGE_HAS_STRIDE)
8594aea
+	  elt = dump_subexp (exp, stream, elt);
8594aea
       }
8594aea
       break;
8594aea
 
8594aea
diff --git a/gdb/expression.h b/gdb/expression.h
8594aea
--- a/gdb/expression.h
8594aea
+++ b/gdb/expression.h
8594aea
@@ -199,6 +199,9 @@ enum range_flag : unsigned
8594aea
 
8594aea
   /* The high bound of this range is exclusive.  */
8594aea
   RANGE_HIGH_BOUND_EXCLUSIVE = 1 << 2,
8594aea
+
8594aea
+  /* The range has a stride.  */
8594aea
+  RANGE_HAS_STRIDE = 1 << 3,
8594aea
 };
8594aea
 
8594aea
 DEF_ENUM_FLAGS_TYPE (enum range_flag, range_flags);
8594aea
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
8594aea
--- a/gdb/f-exp.y
8594aea
+++ b/gdb/f-exp.y
8594aea
@@ -284,6 +284,10 @@ arglist	:	arglist ',' exp   %prec ABOVE_COMMA
8594aea
 			{ pstate->arglist_len++; }
8594aea
 	;
8594aea
 
8594aea
+arglist	:	arglist ',' subrange   %prec ABOVE_COMMA
8594aea
+			{ pstate->arglist_len++; }
8594aea
+	;
8594aea
+
8594aea
 /* There are four sorts of subrange types in F90.  */
8594aea
 
8594aea
 subrange:	exp ':' exp	%prec ABOVE_COMMA
8594aea
@@ -314,6 +318,38 @@ subrange:	':'	%prec ABOVE_COMMA
8594aea
 			  write_exp_elt_opcode (pstate, OP_RANGE); }
8594aea
 	;
8594aea
 
8594aea
+/* And each of the four subrange types can also have a stride.  */
8594aea
+subrange:	exp ':' exp ':' exp	%prec ABOVE_COMMA
8594aea
+			{ write_exp_elt_opcode (pstate, OP_RANGE);
8594aea
+			  write_exp_elt_longcst (pstate, RANGE_HAS_STRIDE);
8594aea
+			  write_exp_elt_opcode (pstate, OP_RANGE); }
8594aea
+	;
8594aea
+
8594aea
+subrange:	exp ':' ':' exp	%prec ABOVE_COMMA
8594aea
+			{ write_exp_elt_opcode (pstate, OP_RANGE);
8594aea
+			  write_exp_elt_longcst (pstate,
8594aea
+						 (RANGE_HIGH_BOUND_DEFAULT
8594aea
+						  | RANGE_HAS_STRIDE));
8594aea
+			  write_exp_elt_opcode (pstate, OP_RANGE); }
8594aea
+	;
8594aea
+
8594aea
+subrange:	':' exp ':' exp	%prec ABOVE_COMMA
8594aea
+			{ write_exp_elt_opcode (pstate, OP_RANGE);
8594aea
+			  write_exp_elt_longcst (pstate,
8594aea
+						 (RANGE_LOW_BOUND_DEFAULT
8594aea
+						  | RANGE_HAS_STRIDE));
8594aea
+			  write_exp_elt_opcode (pstate, OP_RANGE); }
8594aea
+	;
8594aea
+
8594aea
+subrange:	':' ':' exp	%prec ABOVE_COMMA
8594aea
+			{ write_exp_elt_opcode (pstate, OP_RANGE);
8594aea
+			  write_exp_elt_longcst (pstate,
8594aea
+						 (RANGE_LOW_BOUND_DEFAULT
8594aea
+						  | RANGE_HIGH_BOUND_DEFAULT
8594aea
+						  | RANGE_HAS_STRIDE));
8594aea
+			  write_exp_elt_opcode (pstate, OP_RANGE); }
8594aea
+	;
8594aea
+
8594aea
 complexnum:     exp ',' exp 
8594aea
                 	{ }                          
8594aea
         ;
8594aea
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
8594aea
--- a/gdb/f-lang.c
8594aea
+++ b/gdb/f-lang.c
8594aea
@@ -124,7 +124,7 @@ value_f90_subarray (struct value *array,
8594aea
 		    struct expression *exp, int *pos, enum noside noside)
8594aea
 {
8594aea
   int pc = (*pos) + 1;
8594aea
-  LONGEST low_bound, high_bound;
8594aea
+  LONGEST low_bound, high_bound, stride;
8594aea
   struct type *range = check_typedef (value_type (array)->index_type ());
8594aea
   enum range_flag range_flag
8594aea
     = (enum range_flag) longest_to_int (exp->elts[pc].longconst);
8594aea
@@ -141,6 +141,14 @@ value_f90_subarray (struct value *array,
8594aea
   else
8594aea
     high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
8594aea
 
8594aea
+  if (range_flag & RANGE_HAS_STRIDE)
8594aea
+    stride = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
8594aea
+  else
8594aea
+    stride = 1;
8594aea
+
8594aea
+  if (stride != 1)
8594aea
+    error (_("Fortran array strides are not currently supported"));
8594aea
+
8594aea
   return value_slice (array, low_bound, high_bound - low_bound + 1);
8594aea
 }
8594aea
 
8594aea
diff --git a/gdb/parse.c b/gdb/parse.c
8594aea
--- a/gdb/parse.c
8594aea
+++ b/gdb/parse.c
8594aea
@@ -924,6 +924,8 @@ operator_length_standard (const struct expression *expr, int endpos,
8594aea
       /* Assume the range has 2 arguments (low bound and high bound), then
8594aea
 	 reduce the argument count if any bounds are set to default.  */
8594aea
       args = 2;
8594aea
+      if (range_flag & RANGE_HAS_STRIDE)
8594aea
+	++args;
8594aea
       if (range_flag & RANGE_LOW_BOUND_DEFAULT)
8594aea
 	--args;
8594aea
       if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
8594aea
diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
8594aea
--- a/gdb/testsuite/gdb.fortran/array-slices.exp
8594aea
+++ b/gdb/testsuite/gdb.fortran/array-slices.exp
8594aea
@@ -66,3 +66,19 @@ foreach result $array_contents msg $message_strings {
8594aea
 }
8594aea
 
8594aea
 gdb_continue_to_breakpoint "continue to Final Breakpoint"
8594aea
+
8594aea
+# Next test that asking for an array with stride at the CLI gives an
8594aea
+# error.
8594aea
+clean_restart ${testfile}
8594aea
+
8594aea
+if ![fortran_runto_main] then {
8594aea
+    perror "couldn't run to main"
8594aea
+    continue
8594aea
+}
8594aea
+
8594aea
+gdb_breakpoint "show"
8594aea
+gdb_continue_to_breakpoint "show"
8594aea
+gdb_test "up" ".*"
8594aea
+gdb_test "p array (1:10:2, 1:10:2)" \
8594aea
+    "Fortran array strides are not currently supported" \
8594aea
+    "using array stride gives an error"