gdb/fortran: Clean up array/string expression evaluation
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 6 May 2020 17:53:21 +0000 (18:53 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Sat, 19 Sep 2020 08:42:38 +0000 (09:42 +0100)
This commit is a refactor of part of the Fortran array and string
handling code.

The current code is split into two blocks, linked, weirdly, with a
goto.  After this commit all the code is moved to its own function,
and arrays and strings are now handled using the same code; this will
be useful later when I want to add array stride support where strings
will want to be treated just like arrays, but is a good clean up even
without the array stride work, which is why I'm merging it now.

For now the new function is added as a static within eval.c, even
though the function is Fortran only.  A following commit will remove
some of the Fortran specific code from eval.c into one of the Fortran
specific files, including this new function.

There should be no user visible changes after this commit.

gdb/ChangeLog:

* eval.c (fortran_value_subarray): New function, content is taken
from...
(evaluate_subexp_standard): ...here, in two places.  Now arrays
and strings both call the new function.
(calc_f77_array_dims): Add header comment, handle strings.

gdb/ChangeLog
gdb/eval.c

index 8b010e525f69a5a768b1c01d1256f2ca084ee2c0..6330a054c7e09b115a538b8bf4737cf2b91ab917 100644 (file)
@@ -1,3 +1,11 @@
+2020-09-19  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * eval.c (fortran_value_subarray): New function, content is taken
+       from...
+       (evaluate_subexp_standard): ...here, in two places.  Now arrays
+       and strings both call the new function.
+       (calc_f77_array_dims): Add header comment, handle strings.
+
 2020-09-18  Victor Collod  <vcollod@nvidia.com>
 
        PR gdb/26635
index ead4c5fa546a0849b46a9d329878ff5c7f084a89..da4bbb288ffd79eb24a9ade6501f3d9cff51cf3b 100644 (file)
@@ -1260,6 +1260,67 @@ is_integral_or_integral_reference (struct type *type)
          && is_integral_type (TYPE_TARGET_TYPE (type)));
 }
 
+/* Called from evaluate_subexp_standard to perform array indexing, and
+   sub-range extraction, for Fortran.  As well as arrays this function
+   also handles strings as they can be treated like arrays of characters.
+   ARRAY is the array or string being accessed.  EXP, POS, and NOSIDE are
+   as for evaluate_subexp_standard, and NARGS is the number of arguments
+   in this access (e.g. 'array (1,2,3)' would be NARGS 3).  */
+
+static struct value *
+fortran_value_subarray (struct value *array, struct expression *exp,
+                       int *pos, int nargs, enum noside noside)
+{
+  if (exp->elts[*pos].opcode == OP_RANGE)
+    return value_f90_subarray (array, exp, pos, noside);
+
+  if (noside == EVAL_SKIP)
+    {
+      skip_undetermined_arglist (nargs, exp, pos, noside);
+      /* Return the dummy value with the correct type.  */
+      return array;
+    }
+
+  LONGEST subscript_array[MAX_FORTRAN_DIMS];
+  int ndimensions = 1;
+  struct type *type = check_typedef (value_type (array));
+
+  if (nargs > MAX_FORTRAN_DIMS)
+    error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
+
+  ndimensions = calc_f77_array_dims (type);
+
+  if (nargs != ndimensions)
+    error (_("Wrong number of subscripts"));
+
+  gdb_assert (nargs > 0);
+
+  /* Now that we know we have a legal array subscript expression let us
+     actually find out where this element exists in the array.  */
+
+  /* Take array indices left to right.  */
+  for (int i = 0; i < nargs; i++)
+    {
+      /* Evaluate each subscript; it must be a legal integer in F77.  */
+      value *arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+      /* Fill in the subscript array.  */
+      subscript_array[i] = value_as_long (arg2);
+    }
+
+  /* Internal type of array is arranged right to left.  */
+  for (int i = nargs; i > 0; i--)
+    {
+      struct type *array_type = check_typedef (value_type (array));
+      LONGEST index = subscript_array[i - 1];
+
+      array = value_subscripted_rvalue (array, index,
+                                       f77_get_lowerbound (array_type));
+    }
+
+  return array;
+}
+
 struct value *
 evaluate_subexp_standard (struct type *expect_type,
                          struct expression *exp, int *pos,
@@ -1953,33 +2014,8 @@ evaluate_subexp_standard (struct type *expect_type,
       switch (code)
        {
        case TYPE_CODE_ARRAY:
-         if (exp->elts[*pos].opcode == OP_RANGE)
-           return value_f90_subarray (arg1, exp, pos, noside);
-         else
-           {
-             if (noside == EVAL_SKIP)
-               {
-                 skip_undetermined_arglist (nargs, exp, pos, noside);
-                 /* Return the dummy value with the correct type.  */
-                 return arg1;
-               }
-             goto multi_f77_subscript;
-           }
-
        case TYPE_CODE_STRING:
-         if (exp->elts[*pos].opcode == OP_RANGE)
-           return value_f90_subarray (arg1, exp, pos, noside);
-         else
-           {
-             if (noside == EVAL_SKIP)
-               {
-                 skip_undetermined_arglist (nargs, exp, pos, noside);
-                 /* Return the dummy value with the correct type.  */
-                 return arg1;
-               }
-             arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
-             return value_subscript (arg1, value_as_long (arg2));
-           }
+         return fortran_value_subarray (arg1, exp, pos, nargs, noside);
 
        case TYPE_CODE_PTR:
        case TYPE_CODE_FUNC:
@@ -2400,49 +2436,6 @@ evaluate_subexp_standard (struct type *expect_type,
        }
       return (arg1);
 
-    multi_f77_subscript:
-      {
-       LONGEST subscript_array[MAX_FORTRAN_DIMS];
-       int ndimensions = 1, i;
-       struct value *array = arg1;
-
-       if (nargs > MAX_FORTRAN_DIMS)
-         error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
-
-       ndimensions = calc_f77_array_dims (type);
-
-       if (nargs != ndimensions)
-         error (_("Wrong number of subscripts"));
-
-       gdb_assert (nargs > 0);
-
-       /* Now that we know we have a legal array subscript expression 
-          let us actually find out where this element exists in the array.  */
-
-       /* Take array indices left to right.  */
-       for (i = 0; i < nargs; i++)
-         {
-           /* Evaluate each subscript; it must be a legal integer in F77.  */
-           arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
-
-           /* Fill in the subscript array.  */
-
-           subscript_array[i] = value_as_long (arg2);
-         }
-
-       /* Internal type of array is arranged right to left.  */
-       for (i = nargs; i > 0; i--)
-         {
-           struct type *array_type = check_typedef (value_type (array));
-           LONGEST index = subscript_array[i - 1];
-
-           array = value_subscripted_rvalue (array, index,
-                                             f77_get_lowerbound (array_type));
-         }
-
-       return array;
-      }
-
     case BINOP_LOGICAL_AND:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
@@ -3354,12 +3347,17 @@ parse_and_eval_type (char *p, int length)
   return expr->elts[1].type;
 }
 
+/* Return the number of dimensions for a Fortran array or string.  */
+
 int
 calc_f77_array_dims (struct type *array_type)
 {
   int ndimen = 1;
   struct type *tmp_type;
 
+  if ((array_type->code () == TYPE_CODE_STRING))
+    return 1;
+
   if ((array_type->code () != TYPE_CODE_ARRAY))
     error (_("Can't get dimensions for a non-array type"));