Implement 'Enum_Val and 'Enum_Rep

This patch implements the Ada 2022 attributes 'Enum_Val and 'Enum_Rep.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This commit is contained in:
Tom Tromey
2023-06-23 09:59:38 -06:00
parent 1e5ae3d17f
commit 22f6f7979c
6 changed files with 99 additions and 16 deletions

View File

@@ -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 ]

View 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

View 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);

View 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));
}
/* 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,

View 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

View 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"