Implement 'Enum_Val and 'Enum_Rep
authorTom Tromey <tromey@adacore.com>
Fri, 23 Jun 2023 15:59:38 +0000 (09:59 -0600)
committerTom Tromey <tromey@adacore.com>
Thu, 13 Jul 2023 17:45:09 +0000 (11:45 -0600)
This patch implements the Ada 2022 attributes 'Enum_Val and 'Enum_Rep.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
gdb/NEWS
gdb/ada-exp.h
gdb/ada-exp.y
gdb/ada-lang.c
gdb/ada-lex.l
gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp

index b924834d3d730ae578b7d7cb8174c14b7a0bb3ad..7e61c2354e0c638c6be0ec1f150cf915f8f7b20c 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -84,6 +84,8 @@
   is 64k.  To print longer strings you should increase
   'max-value-size'.
 
+* The Ada 2022 Enum_Rep and Enum_Val attributes are now supported.
+
 * New commands
 
 maintenance print record-instruction [ N ]
index 54ae4529def698c24bd858527cfb4e9d5d04565e..dc34a43bdd6c07f17bce6e7044429d51f8bc824a 100644 (file)
@@ -69,7 +69,14 @@ extern struct value *ada_pos_atr (struct type *expect_type,
                                  struct expression *exp,
                                  enum noside noside, enum exp_opcode op,
                                  struct value *arg);
-extern struct value *ada_val_atr (enum noside noside, struct type *type,
+extern struct value *ada_atr_enum_rep (struct expression *exp,
+                                      enum noside noside, struct type *type,
+                                      struct value *arg);
+extern struct value *ada_atr_enum_val (struct expression *exp,
+                                      enum noside noside, struct type *type,
+                                      struct value *arg);
+extern struct value *ada_val_atr (struct expression *exp,
+                                 enum noside noside, struct type *type,
                                  struct value *arg);
 extern struct value *ada_binop_exp (struct type *expect_type,
                                    struct expression *exp,
@@ -424,8 +431,14 @@ protected:
   using operation::do_generate_ax;
 };
 
-/* Implement the Ada 'val attribute.  */
-class ada_atr_val_operation
+typedef struct value *ada_atr_ftype (struct expression *exp,
+                                    enum noside noside,
+                                    struct type *type,
+                                    struct value *arg);
+
+/* Implement several Ada attributes.  */
+template<ada_atr_ftype FUNC>
+class ada_atr_operation
   : public tuple_holding_operation<struct type *, operation_up>
 {
 public:
@@ -434,12 +447,23 @@ public:
 
   value *evaluate (struct type *expect_type,
                   struct expression *exp,
-                  enum noside noside) override;
+                  enum noside noside) override
+  {
+    value *arg = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+    return FUNC (exp, noside, std::get<0> (m_storage), arg);
+  }
 
   enum exp_opcode opcode () const override
-  { return OP_ATR_VAL; }
+  {
+    /* The value here generally doesn't matter.  */
+    return OP_ATR_VAL;
+  }
 };
 
+using ada_atr_val_operation = ada_atr_operation<ada_val_atr>;
+using ada_atr_enum_rep_operation = ada_atr_operation<ada_atr_enum_rep>;
+using ada_atr_enum_val_operation = ada_atr_operation<ada_atr_enum_val>;
+
 /* The indirection operator for Ada.  */
 class ada_unop_ind_operation
   : public unop_ind_base_operation
index 23aebf0e2368614d828cfdaded1554b34b3c4b9f..019ac85211ea4173dfc4a74aa10ced7d7a482c6b 100644 (file)
@@ -474,7 +474,7 @@ make_tick_completer (struct stoken tok)
 %right TICK_ACCESS TICK_ADDRESS TICK_FIRST TICK_LAST TICK_LENGTH
 %right TICK_MAX TICK_MIN TICK_MODULUS
 %right TICK_POS TICK_RANGE TICK_SIZE TICK_TAG TICK_VAL
-%right TICK_COMPLETE
+%right TICK_COMPLETE TICK_ENUM_REP TICK_ENUM_VAL
  /* The following are right-associative only so that reductions at this
     precedence have lower precedence than '.' and '('.  The syntax still
     forces a.b.c, e.g., to be LEFT-associated.  */
@@ -864,6 +864,18 @@ primary :  primary TICK_ACCESS
                          pstate->push_new<ada_atr_val_operation>
                            ($1, std::move (arg));
                        }
+       |       type_prefix TICK_ENUM_REP '(' exp ')'
+                       {
+                         operation_up arg = ada_pop (true, $1);
+                         pstate->push_new<ada_atr_enum_rep_operation>
+                           ($1, std::move (arg));
+                       }
+       |       type_prefix TICK_ENUM_VAL '(' exp ')'
+                       {
+                         operation_up arg = ada_pop (true, $1);
+                         pstate->push_new<ada_atr_enum_val_operation>
+                           ($1, std::move (arg));
+                       }
        |       type_prefix TICK_MODULUS
                        {
                          struct type *type_arg = check_typedef ($1);
index 3d629cc110f69b16166aca24b6462bc307c70ab7..795207589d0726fa01a71737753bf74698c52884 100644 (file)
@@ -8815,7 +8815,8 @@ val_atr (struct type *type, LONGEST val)
 }
 
 struct value *
-ada_val_atr (enum noside noside, struct type *type, struct value *arg)
+ada_val_atr (struct expression *exp, enum noside noside, struct type *type,
+            struct value *arg)
 {
   if (noside == EVAL_AVOID_SIDE_EFFECTS)
     return value::zero (type, not_lval);
@@ -8827,6 +8828,52 @@ ada_val_atr (enum noside noside, struct type *type, struct value *arg)
 
   return val_atr (type, value_as_long (arg));
 }
+
+/* Implementation of the enum_rep attribute.  */
+struct value *
+ada_atr_enum_rep (struct expression *exp, enum noside noside, struct type *type,
+                 struct value *arg)
+{
+  struct type *inttype = builtin_type (exp->gdbarch)->builtin_int;
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value::zero (inttype, not_lval);
+
+  if (type->code () == TYPE_CODE_RANGE)
+    type = type->target_type ();
+  if (type->code () != TYPE_CODE_ENUM)
+    error (_("'Enum_Rep only defined on enum types"));
+  if (!types_equal (type, arg->type ()))
+    error (_("'Enum_Rep requires argument to have same type as enum"));
+
+  return value_cast (inttype, arg);
+}
+
+/* Implementation of the enum_val attribute.  */
+struct value *
+ada_atr_enum_val (struct expression *exp, enum noside noside, struct type *type,
+                 struct value *arg)
+{
+  struct type *original_type = type;
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value::zero (original_type, not_lval);
+
+  if (type->code () == TYPE_CODE_RANGE)
+    type = type->target_type ();
+  if (type->code () != TYPE_CODE_ENUM)
+    error (_("'Enum_Val only defined on enum types"));
+  if (!integer_type_p (arg->type ()))
+    error (_("'Enum_Val requires integral argument"));
+
+  LONGEST value = value_as_long (arg);
+  for (int i = 0; i < type->num_fields (); ++i)
+    {
+      if (type->field (i).loc_enumval () == value)
+       return value_from_longest (original_type, value);
+    }
+
+  error (_("value %s not found in enum"), plongest (value));
+}
+
 \f
 
                                /* Evaluation */
@@ -10919,15 +10966,6 @@ ada_var_value_operation::do_generate_ax (struct expression *exp,
   var_value_operation::do_generate_ax (exp, ax, value, cast_type);
 }
 
-value *
-ada_atr_val_operation::evaluate (struct type *expect_type,
-                                struct expression *exp,
-                                enum noside noside)
-{
-  value *arg = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
-  return ada_val_atr (noside, std::get<0> (m_storage), arg);
-}
-
 value *
 ada_unop_ind_operation::evaluate (struct type *expect_type,
                                  struct expression *exp,
index 8c0e76798325db4ab3915fc4cc2ab0293ec3b82b..0547b704eaf4d59a1b777eef708f2adb3ce3bcde 100644 (file)
@@ -684,6 +684,8 @@ attributes[] = {
   { "size", TICK_SIZE },
   { "tag", TICK_TAG },
   { "val", TICK_VAL },
+  { "enum_rep", TICK_ENUM_REP },
+  { "enum_val", TICK_ENUM_VAL },
 };
 
 /* Return the syntactic code corresponding to the attribute name or
index 502a5ab5fd9d48e3e1d3ce53aba3487ba4f21f39..397189487bbc0494c35ac3c4cb3cdf2fca7c1b79 100644 (file)
@@ -61,3 +61,8 @@ gdb_test "print enum_subrange'val(3)" " = lit3"
 
 gdb_test "print indexed_by_enum(lit2)" "43"
 gdb_test "print s(2)" "101 'e'"
+
+gdb_test "print enum_with_gaps'enum_rep(lit3)" " = 13" \
+    "enum_rep"
+gdb_test "print enum_with_gaps'enum_val(21)" " = lit4" \
+    "enum_val"