[PATCH 2/2] Implement 'Enum_Val and 'Enum_Rep
Tom Tromey
tromey@adacore.com
Thu Jun 29 19:44:31 GMT 2023
This patch implements the Ada 2022 attributes 'Enum_Val and 'Enum_Rep.
---
gdb/NEWS | 2 +
gdb/ada-exp.h | 34 ++++++++++++++---
gdb/ada-exp.y | 14 ++++++-
gdb/ada-lang.c | 58 ++++++++++++++++++++++++-----
gdb/ada-lex.l | 2 +
gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp | 5 +++
6 files changed, 99 insertions(+), 16 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index fd42864c692..5b56a86da6f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -78,6 +78,8 @@
functionality is also available for dprintf when dprintf-style is
'gdb'.
+* The Ada 2022 'Enum_Rep and 'Enum_Val attributes are now supported.
+
* New commands
maintenance print record-instruction [ N ]
diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h
index 54ae4529def..dc34a43bdd6 100644
--- a/gdb/ada-exp.h
+++ b/gdb/ada-exp.h
@@ -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 @@ class ada_var_msym_value_operation
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 @@ class ada_atr_val_operation
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
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 23aebf0e236..019ac85211e 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -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);
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3d629cc110f..795207589d0 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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));
+}
+
/* 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,
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 8c0e7679832..0547b704eaf 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -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
diff --git a/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp b/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
index 502a5ab5fd9..397189487bb 100644
--- a/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
+++ b/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
@@ -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"
--
2.40.1
More information about the Gdb-patches
mailing list