gdb: Convert enum range_type to a bit field enum
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 5 May 2020 15:03:53 +0000 (16:03 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 22 Oct 2020 08:24:42 +0000 (09:24 +0100)
The expression range_type enum represents the following ideas:

  - Lower bound is set to default,
  - Upper bound is set to default,
  - Upper bound is exclusive.

There are currently 6 entries in the enum to represent the combination
of all those ideas.

In a future commit I'd like to add stride information to the range,
this could in theory appear with any of the existing enum entries, so
this would take us to 12 enum entries.

This feels like its getting a little out of hand, so in this commit I
switch the range_type enum over to being a flags style enum.  There's
one entry to represent no flags being set, then 3 flags to represent
the 3 ideas above.  Adding stride information will require adding only
one more enum flag.

I've then gone through and updated the code to handle this change.

There should be no user visible changes after this commit.

gdb/ChangeLog:

* expprint.c (print_subexp_standard): Update to reflect changes to
enum range_type.
(dump_subexp_body_standard): Likewise.
* expression.h (enum range_type): Convert to a bit field enum, and
make the enum unsigned.
* f-exp.y (subrange): Update to reflect changes to enum
range_type.
* f-lang.c (value_f90_subarray): Likewise.
* parse.c (operator_length_standard): Likewise.
* rust-exp.y (rust_parser::convert_ast_to_expression): Likewise.
* rust-lang.c (rust_range): Likewise.
(rust_compute_range): Likewise.
(rust_subscript): Likewise.

gdb/ChangeLog
gdb/expprint.c
gdb/expression.h
gdb/f-exp.y
gdb/f-lang.c
gdb/parse.c
gdb/rust-exp.y
gdb/rust-lang.c

index 75e7ee1428c1281dffa7a75e35f067510dd33f55..427f02924f3ce7889508e92e3f7d75928f6e1a80 100644 (file)
@@ -1,3 +1,19 @@
+2020-10-22  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * expprint.c (print_subexp_standard): Update to reflect changes to
+       enum range_type.
+       (dump_subexp_body_standard): Likewise.
+       * expression.h (enum range_type): Convert to a bit field enum, and
+       make the enum unsigned.
+       * f-exp.y (subrange): Update to reflect changes to enum
+       range_type.
+       * f-lang.c (value_f90_subarray): Likewise.
+       * parse.c (operator_length_standard): Likewise.
+       * rust-exp.y (rust_parser::convert_ast_to_expression): Likewise.
+       * rust-lang.c (rust_range): Likewise.
+       (rust_compute_range): Likewise.
+       (rust_subscript): Likewise.
+
 2020-10-21  Simon Marchi  <simon.marchi@efficios.com>
 
        * infrun.c (displaced_step_in_progress_thread): Fix comment.
index d7d7c871bddd022e248f7620550eb3dbd9ae3cb4..bdb69a92f75ca83332d212c902260ee82bdc1f81 100644 (file)
@@ -585,17 +585,13 @@ print_subexp_standard (struct expression *exp, int *pos,
          longest_to_int (exp->elts[pc + 1].longconst);
        *pos += 2;
 
-       if (range_type == NONE_BOUND_DEFAULT_EXCLUSIVE
-           || range_type == LOW_BOUND_DEFAULT_EXCLUSIVE)
+       if (range_type & RANGE_HIGH_BOUND_EXCLUSIVE)
          fputs_filtered ("EXCLUSIVE_", stream);
        fputs_filtered ("RANGE(", stream);
-       if (range_type == HIGH_BOUND_DEFAULT
-           || range_type == NONE_BOUND_DEFAULT
-           || range_type == NONE_BOUND_DEFAULT_EXCLUSIVE)
+       if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
          print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
        fputs_filtered ("..", stream);
-       if (range_type == LOW_BOUND_DEFAULT
-           || range_type == NONE_BOUND_DEFAULT)
+       if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
          print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
        fputs_filtered (")", stream);
        return;
@@ -1116,36 +1112,19 @@ dump_subexp_body_standard (struct expression *exp,
          longest_to_int (exp->elts[elt].longconst);
        elt += 2;
 
-       switch (range_type)
-         {
-         case BOTH_BOUND_DEFAULT:
-           fputs_filtered ("Range '..'", stream);
-           break;
-         case LOW_BOUND_DEFAULT:
-           fputs_filtered ("Range '..EXP'", stream);
-           break;
-         case LOW_BOUND_DEFAULT_EXCLUSIVE:
-           fputs_filtered ("ExclusiveRange '..EXP'", stream);
-           break;
-         case HIGH_BOUND_DEFAULT:
-           fputs_filtered ("Range 'EXP..'", stream);
-           break;
-         case NONE_BOUND_DEFAULT:
-           fputs_filtered ("Range 'EXP..EXP'", stream);
-           break;
-         case NONE_BOUND_DEFAULT_EXCLUSIVE:
-           fputs_filtered ("ExclusiveRange 'EXP..EXP'", stream);
-           break;
-         default:
-           fputs_filtered ("Invalid Range!", stream);
-           break;
-         }
+       if (range_type & RANGE_HIGH_BOUND_EXCLUSIVE)
+         fputs_filtered ("Exclusive", stream);
+       fputs_filtered ("Range '", stream);
+       if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
+         fputs_filtered ("EXP", stream);
+       fputs_filtered ("..", stream);
+       if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
+         fputs_filtered ("EXP", stream);
+       fputs_filtered ("'", stream);
 
-       if (range_type == HIGH_BOUND_DEFAULT
-           || range_type == NONE_BOUND_DEFAULT)
+       if (!(range_type & RANGE_LOW_BOUND_DEFAULT))
          elt = dump_subexp (exp, stream, elt);
-       if (range_type == LOW_BOUND_DEFAULT
-           || range_type == NONE_BOUND_DEFAULT)
+       if (!(range_type & RANGE_HIGH_BOUND_DEFAULT))
          elt = dump_subexp (exp, stream, elt);
       }
       break;
index 5af10f05db186803daeca037efee204116220bc9..6bd3fc0c3c56a49a39b5768d3ade74ce8690b2c3 100644 (file)
@@ -185,22 +185,22 @@ extern void dump_prefix_expression (struct expression *, struct ui_file *);
    or inclusive.  So we have six sorts of subrange.  This enumeration
    type is to identify this.  */
 
-enum range_type
+enum range_type : unsigned
 {
-  /* Neither the low nor the high bound was given -- so this refers to
-     the entire available range.  */
-  BOTH_BOUND_DEFAULT,
-  /* The low bound was not given and the high bound is inclusive.  */
-  LOW_BOUND_DEFAULT,
-  /* The high bound was not given and the low bound in inclusive.  */
-  HIGH_BOUND_DEFAULT,
-  /* Both bounds were given and both are inclusive.  */
-  NONE_BOUND_DEFAULT,
-  /* The low bound was not given and the high bound is exclusive.  */
-  NONE_BOUND_DEFAULT_EXCLUSIVE,
-  /* Both bounds were given.  The low bound is inclusive and the high
-     bound is exclusive.  */
-  LOW_BOUND_DEFAULT_EXCLUSIVE,
+  /* This is a standard range.  Both the lower and upper bounds are
+     defined, and the bounds are inclusive.  */
+  RANGE_STANDARD = 0,
+
+  /* The low bound was not given.  */
+  RANGE_LOW_BOUND_DEFAULT = 1 << 0,
+
+  /* The high bound was not given.  */
+  RANGE_HIGH_BOUND_DEFAULT = 1 << 1,
+
+  /* The high bound of this range is exclusive.  */
+  RANGE_HIGH_BOUND_EXCLUSIVE = 1 << 2,
 };
 
+DEF_ENUM_FLAGS_TYPE (enum range_type, range_types);
+
 #endif /* !defined (EXPRESSION_H) */
index 0ccb3c68d3eaf51eb682ad8cf263ede9af63e3b5..a3314082d909c252530aa27d152fe437d49128dd 100644 (file)
@@ -287,26 +287,30 @@ arglist   :       arglist ',' exp   %prec ABOVE_COMMA
 /* There are four sorts of subrange types in F90.  */
 
 subrange:      exp ':' exp     %prec ABOVE_COMMA
-                       { write_exp_elt_opcode (pstate, OP_RANGE); 
-                         write_exp_elt_longcst (pstate, NONE_BOUND_DEFAULT);
+                       { write_exp_elt_opcode (pstate, OP_RANGE);
+                         write_exp_elt_longcst (pstate, RANGE_STANDARD);
                          write_exp_elt_opcode (pstate, OP_RANGE); }
        ;
 
 subrange:      exp ':' %prec ABOVE_COMMA
                        { write_exp_elt_opcode (pstate, OP_RANGE);
-                         write_exp_elt_longcst (pstate, HIGH_BOUND_DEFAULT);
+                         write_exp_elt_longcst (pstate,
+                                                RANGE_HIGH_BOUND_DEFAULT);
                          write_exp_elt_opcode (pstate, OP_RANGE); }
        ;
 
 subrange:      ':' exp %prec ABOVE_COMMA
                        { write_exp_elt_opcode (pstate, OP_RANGE);
-                         write_exp_elt_longcst (pstate, LOW_BOUND_DEFAULT);
+                         write_exp_elt_longcst (pstate,
+                                                RANGE_LOW_BOUND_DEFAULT);
                          write_exp_elt_opcode (pstate, OP_RANGE); }
        ;
 
 subrange:      ':'     %prec ABOVE_COMMA
                        { write_exp_elt_opcode (pstate, OP_RANGE);
-                         write_exp_elt_longcst (pstate, BOTH_BOUND_DEFAULT);
+                         write_exp_elt_longcst (pstate,
+                                                (RANGE_LOW_BOUND_DEFAULT
+                                                 | RANGE_HIGH_BOUND_DEFAULT));
                          write_exp_elt_opcode (pstate, OP_RANGE); }
        ;
 
index e13097baee453be7d98a8444991ba65efe5a0a17..fcab973f8745866140e667fda8fbe7e8a3e2413e 100644 (file)
@@ -131,12 +131,12 @@ value_f90_subarray (struct value *array,
 
   *pos += 3;
 
-  if (range_type == LOW_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
+  if (range_type & RANGE_LOW_BOUND_DEFAULT)
     low_bound = range->bounds ()->low.const_val ();
   else
     low_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
 
-  if (range_type == HIGH_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
+  if (range_type & RANGE_HIGH_BOUND_DEFAULT)
     high_bound = range->bounds ()->high.const_val ();
   else
     high_bound = value_as_long (evaluate_subexp (nullptr, exp, pos, noside));
index 6b9541bfdc2cf8441889dfd5fc5cc62263132e48..6661fba81d7e40c6db07748df384c01583ddd2a6 100644 (file)
@@ -921,21 +921,13 @@ operator_length_standard (const struct expression *expr, int endpos,
       range_type = (enum range_type)
        longest_to_int (expr->elts[endpos - 2].longconst);
 
-      switch (range_type)
-       {
-       case LOW_BOUND_DEFAULT:
-       case LOW_BOUND_DEFAULT_EXCLUSIVE:
-       case HIGH_BOUND_DEFAULT:
-         args = 1;
-         break;
-       case BOTH_BOUND_DEFAULT:
-         args = 0;
-         break;
-       case NONE_BOUND_DEFAULT:
-       case NONE_BOUND_DEFAULT_EXCLUSIVE:
-         args = 2;
-         break;
-       }
+      /* 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_type & RANGE_LOW_BOUND_DEFAULT)
+       --args;
+      if (range_type & RANGE_HIGH_BOUND_DEFAULT)
+       --args;
 
       break;
 
index db888098c4a6b878d3eb47bf87435149d1b11d60..ea9fbdc25fb36e1ab51513587a0b041bd8f3cc77 100644 (file)
@@ -2492,24 +2492,29 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation,
 
     case OP_RANGE:
       {
-       enum range_type kind = BOTH_BOUND_DEFAULT;
+       enum range_type kind = (RANGE_HIGH_BOUND_DEFAULT
+                               | RANGE_LOW_BOUND_DEFAULT);
 
        if (operation->left.op != NULL)
          {
            convert_ast_to_expression (operation->left.op, top);
-           kind = HIGH_BOUND_DEFAULT;
+           kind &= ~RANGE_LOW_BOUND_DEFAULT;
          }
        if (operation->right.op != NULL)
          {
            convert_ast_to_expression (operation->right.op, top);
-           if (kind == BOTH_BOUND_DEFAULT)
-             kind = (operation->inclusive
-                     ? LOW_BOUND_DEFAULT : LOW_BOUND_DEFAULT_EXCLUSIVE);
+           if (kind == (RANGE_HIGH_BOUND_DEFAULT | RANGE_LOW_BOUND_DEFAULT))
+             {
+               kind = RANGE_LOW_BOUND_DEFAULT;
+               if (!operation->inclusive)
+                 kind |= RANGE_HIGH_BOUND_EXCLUSIVE;
+             }
            else
              {
-               gdb_assert (kind == HIGH_BOUND_DEFAULT);
-               kind = (operation->inclusive
-                       ? NONE_BOUND_DEFAULT : NONE_BOUND_DEFAULT_EXCLUSIVE);
+               gdb_assert (kind == RANGE_HIGH_BOUND_DEFAULT);
+               kind = RANGE_STANDARD;
+               if (!operation->inclusive)
+                 kind |= RANGE_HIGH_BOUND_EXCLUSIVE;
              }
          }
        else
index f7c762eb640c1aadd573c443588db410d7b600e2..820ebb92c43dcc3469b4e09f750c528a00eb15b1 100644 (file)
@@ -1077,13 +1077,11 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
   kind = (enum range_type) longest_to_int (exp->elts[*pos + 1].longconst);
   *pos += 3;
 
-  if (kind == HIGH_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT
-      || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
+  if (!(kind & RANGE_LOW_BOUND_DEFAULT))
     low = evaluate_subexp (nullptr, exp, pos, noside);
-  if (kind == LOW_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT_EXCLUSIVE
-      || kind == NONE_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
+  if (!(kind & RANGE_HIGH_BOUND_DEFAULT))
     high = evaluate_subexp (nullptr, exp, pos, noside);
-  bool inclusive = (kind == NONE_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT);
+  bool inclusive = !(kind & RANGE_HIGH_BOUND_EXCLUSIVE);
 
   if (noside == EVAL_SKIP)
     return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
@@ -1166,13 +1164,13 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
 static void
 rust_compute_range (struct type *type, struct value *range,
                    LONGEST *low, LONGEST *high,
-                   enum range_type *kind)
+                   range_types *kind)
 {
   int i;
 
   *low = 0;
   *high = 0;
-  *kind = BOTH_BOUND_DEFAULT;
+  *kind = RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT;
 
   if (type->num_fields () == 0)
     return;
@@ -1180,15 +1178,15 @@ rust_compute_range (struct type *type, struct value *range,
   i = 0;
   if (strcmp (TYPE_FIELD_NAME (type, 0), "start") == 0)
     {
-      *kind = HIGH_BOUND_DEFAULT;
+      *kind = RANGE_HIGH_BOUND_DEFAULT;
       *low = value_as_long (value_field (range, 0));
       ++i;
     }
   if (type->num_fields () > i
       && strcmp (TYPE_FIELD_NAME (type, i), "end") == 0)
     {
-      *kind = (*kind == BOTH_BOUND_DEFAULT
-              ? LOW_BOUND_DEFAULT : NONE_BOUND_DEFAULT);
+      *kind = (*kind == (RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT)
+              ? RANGE_LOW_BOUND_DEFAULT : RANGE_STANDARD);
       *high = value_as_long (value_field (range, i));
 
       if (rust_inclusive_range_type_p (type))
@@ -1206,7 +1204,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
   struct type *rhstype;
   LONGEST low, high_bound;
   /* Initialized to appease the compiler.  */
-  enum range_type kind = BOTH_BOUND_DEFAULT;
+  range_types kind = RANGE_LOW_BOUND_DEFAULT | RANGE_HIGH_BOUND_DEFAULT;
   LONGEST high = 0;
   int want_slice = 0;
 
@@ -1303,8 +1301,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
       else
        error (_("Cannot subscript non-array type"));
 
-      if (want_slice
-         && (kind == BOTH_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT))
+      if (want_slice && (kind & RANGE_LOW_BOUND_DEFAULT))
        low = low_bound;
       if (low < 0)
        error (_("Index less than zero"));
@@ -1322,7 +1319,7 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
          CORE_ADDR addr;
          struct value *addrval, *tem;
 
-         if (kind == BOTH_BOUND_DEFAULT || kind == HIGH_BOUND_DEFAULT)
+         if (kind & RANGE_HIGH_BOUND_DEFAULT)
            high = high_bound;
          if (high < 0)
            error (_("High index less than zero"));