struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1);
+extern struct value *ada_unop_in_range (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct type *type);
+extern struct value *ada_mult_binop (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2);
+extern struct value *ada_equal_binop (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2);
+extern struct value *ada_ternop_slice (struct expression *exp,
+ enum noside noside,
+ struct value *array,
+ struct value *low_bound_val,
+ struct value *high_bound_val);
+extern struct value *ada_binop_in_bounds (struct expression *exp,
+ enum noside noside,
+ struct value *arg1,
+ struct value *arg2,
+ int n);
+extern struct value *ada_binop_minmax (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1,
+ struct value *arg2);
+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,
+ struct value *arg);
+extern struct value *ada_binop_exp (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2);
namespace expr
{
+/* The base class for Ada type resolution. Ada operations that want
+ to participate in resolution implement this interface. */
+struct ada_resolvable
+{
+ /* Resolve this object. EXP is the expression being resolved.
+ DEPROCEDURE_P is true if a symbol that refers to a zero-argument
+ function may be turned into a function call. PARSE_COMPLETION
+ and TRACKER are passed in from the parser context. CONTEXT_TYPE
+ is the expected type of the expression, or nullptr if none is
+ known. This method should return true if the operation should be
+ replaced by a function call with this object as the callee. */
+ virtual bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) = 0;
+};
+
/* In Ada, some generic operations must be wrapped with a handler that
handles some Ada-specific type conversions. */
class ada_wrapped_operation
using string_operation::string_operation;
+ /* Return the underlying string. */
+ const char *get_name () const
+ {
+ return std::get<0> (m_storage).c_str ();
+ }
+
value *evaluate (struct type *expect_type,
struct expression *exp,
enum noside noside) override;
using ada_atr_tag_operation = unop_operation<OP_ATR_TAG, ada_atr_tag>;
using ada_atr_size_operation = unop_operation<OP_ATR_SIZE, ada_atr_size>;
using ada_abs_operation = unop_operation<UNOP_ABS, ada_abs>;
+using ada_pos_operation = unop_operation<OP_ATR_POS, ada_pos_atr>;
+
+/* The in-range operation, given a type. */
+class ada_unop_range_operation
+ : public tuple_holding_operation<operation_up, struct type *>
+{
+public:
+
+ using tuple_holding_operation::tuple_holding_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override
+ {
+ value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ return ada_unop_in_range (expect_type, exp, noside, UNOP_IN_RANGE,
+ val, std::get<1> (m_storage));
+ }
+
+ enum exp_opcode opcode () const override
+ { return UNOP_IN_RANGE; }
+};
+
+/* The Ada + and - operators. */
+class ada_binop_addsub_operation
+ : public tuple_holding_operation<enum exp_opcode, operation_up, operation_up>
+{
+public:
+
+ using tuple_holding_operation::tuple_holding_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ enum exp_opcode opcode () const override
+ { return std::get<0> (m_storage); }
+};
+
+using ada_binop_mul_operation = binop_operation<BINOP_MUL, ada_mult_binop>;
+using ada_binop_div_operation = binop_operation<BINOP_DIV, ada_mult_binop>;
+using ada_binop_rem_operation = binop_operation<BINOP_REM, ada_mult_binop>;
+using ada_binop_mod_operation = binop_operation<BINOP_MOD, ada_mult_binop>;
+
+using ada_binop_min_operation = binop_operation<BINOP_MIN, ada_binop_minmax>;
+using ada_binop_max_operation = binop_operation<BINOP_MAX, ada_binop_minmax>;
+
+using ada_binop_exp_operation = binop_operation<BINOP_EXP, ada_binop_exp>;
+
+/* Implement the equal and not-equal operations for Ada. */
+class ada_binop_equal_operation
+ : public tuple_holding_operation<enum exp_opcode, operation_up, operation_up>
+{
+public:
+
+ using tuple_holding_operation::tuple_holding_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override
+ {
+ value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *arg2 = std::get<2> (m_storage)->evaluate (value_type (arg1),
+ exp, noside);
+ return ada_equal_binop (expect_type, exp, noside, std::get<0> (m_storage),
+ arg1, arg2);
+ }
+
+ enum exp_opcode opcode () const override
+ { return std::get<0> (m_storage); }
+};
+
+/* Bitwise operators for Ada. */
+template<enum exp_opcode OP>
+class ada_bitwise_operation
+ : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+ using maybe_constant_operation::maybe_constant_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override
+ {
+ value *lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *rhs = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *result = eval_op_binary (expect_type, exp, noside, OP, lhs, rhs);
+ return value_cast (value_type (lhs), result);
+ }
+
+ enum exp_opcode opcode () const override
+ { return OP; }
+};
+
+using ada_bitwise_and_operation = ada_bitwise_operation<BINOP_BITWISE_AND>;
+using ada_bitwise_ior_operation = ada_bitwise_operation<BINOP_BITWISE_IOR>;
+using ada_bitwise_xor_operation = ada_bitwise_operation<BINOP_BITWISE_XOR>;
+
+/* Ada array- or string-slice operation. */
+class ada_ternop_slice_operation
+ : public maybe_constant_operation<operation_up, operation_up, operation_up>,
+ public ada_resolvable
+{
+public:
+
+ using maybe_constant_operation::maybe_constant_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override
+ {
+ value *array = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *low = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *high = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
+ return ada_ternop_slice (exp, noside, array, low, high);
+ }
+
+ enum exp_opcode opcode () const override
+ { return TERNOP_SLICE; }
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+};
+
+/* Implement BINOP_IN_BOUNDS for Ada. */
+class ada_binop_in_bounds_operation
+ : public maybe_constant_operation<operation_up, operation_up, int>
+{
+public:
+
+ using maybe_constant_operation::maybe_constant_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override
+ {
+ value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ return ada_binop_in_bounds (exp, noside, arg1, arg2,
+ std::get<2> (m_storage));
+ }
+
+ enum exp_opcode opcode () const override
+ { return BINOP_IN_BOUNDS; }
+};
+
+/* Implement several unary Ada OP_ATR_* operations. */
+class ada_unop_atr_operation
+ : public maybe_constant_operation<operation_up, enum exp_opcode, int>
+{
+public:
+
+ using maybe_constant_operation::maybe_constant_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ enum exp_opcode opcode () const override
+ { return std::get<1> (m_storage); }
+};
+
+/* Variant of var_value_operation for Ada. */
+class ada_var_value_operation
+ : public var_value_operation, public ada_resolvable
+{
+public:
+
+ using var_value_operation::var_value_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ value *evaluate_for_cast (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ const block *get_block () const
+ { return std::get<1> (m_storage); }
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+
+protected:
+
+ using operation::do_generate_ax;
+};
+
+/* Variant of var_msym_value_operation for Ada. */
+class ada_var_msym_value_operation
+ : public var_msym_value_operation
+{
+public:
+
+ using var_msym_value_operation::var_msym_value_operation;
+
+ value *evaluate_for_cast (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+protected:
+
+ using operation::do_generate_ax;
+};
+
+/* Implement the Ada 'val attribute. */
+class ada_atr_val_operation
+ : public tuple_holding_operation<struct type *, operation_up>
+{
+public:
+
+ using tuple_holding_operation::tuple_holding_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ enum exp_opcode opcode () const override
+ { return OP_ATR_VAL; }
+};
+
+/* The indirection operator for Ada. */
+class ada_unop_ind_operation
+ : public unop_ind_base_operation
+{
+public:
+
+ using unop_ind_base_operation::unop_ind_base_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+};
+
+/* Implement STRUCTOP_STRUCT for Ada. */
+class ada_structop_operation
+ : public structop_base_operation
+{
+public:
+
+ using structop_base_operation::structop_base_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ enum exp_opcode opcode () const override
+ { return STRUCTOP_STRUCT; }
+};
+
+/* Function calls for Ada. */
+class ada_funcall_operation
+ : public tuple_holding_operation<operation_up, std::vector<operation_up>>,
+ public ada_resolvable
+{
+public:
+
+ using tuple_holding_operation::tuple_holding_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+
+ enum exp_opcode opcode () const override
+ { return OP_FUNCALL; }
+};
+
+/* An Ada assignment operation. */
+class ada_assign_operation
+ : public assign_operation
+{
+public:
+
+ using assign_operation::assign_operation;
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ enum exp_opcode opcode () const override
+ { return BINOP_ASSIGN; }
+};
+
+/* This abstract class represents a single component in an Ada
+ aggregate assignment. */
+class ada_component
+{
+public:
+
+ /* Assign to LHS, which is part of CONTAINER. EXP is the expression
+ being evaluated. INDICES, LOW, and HIGH indicate which
+ sub-components have already been assigned; INDICES should be
+ updated by this call. */
+ virtual void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high) = 0;
+
+ /* Same as operation::uses_objfile. */
+ virtual bool uses_objfile (struct objfile *objfile) = 0;
+
+ /* Same as operation::dump. */
+ virtual void dump (ui_file *stream, int depth) = 0;
+
+ virtual ~ada_component () = default;
+
+protected:
+
+ ada_component () = default;
+ DISABLE_COPY_AND_ASSIGN (ada_component);
+};
+
+/* Unique pointer specialization for Ada assignment components. */
+typedef std::unique_ptr<ada_component> ada_component_up;
+
+/* An operation that holds a single component. */
+class ada_aggregate_operation
+ : public tuple_holding_operation<ada_component_up>
+{
+public:
+
+ using tuple_holding_operation::tuple_holding_operation;
+
+ /* Assuming that LHS represents an lvalue having a record or array
+ type, evaluate an assignment of this aggregate's value to LHS.
+ CONTAINER is an lvalue containing LHS (possibly LHS itself).
+ Does not modify the inferior's memory, nor does it modify the
+ contents of LHS (unless == CONTAINER). Returns the modified
+ CONTAINER. */
+
+ value *assign_aggregate (struct value *container,
+ struct value *lhs,
+ struct expression *exp);
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override
+ {
+ error (_("Aggregates only allowed on the right of an assignment"));
+ }
+
+ enum exp_opcode opcode () const override
+ { return OP_AGGREGATE; }
+};
+
+/* A component holding a vector of other components to assign. */
+class ada_aggregate_component : public ada_component
+{
+public:
+
+ explicit ada_aggregate_component (std::vector<ada_component_up> &&components)
+ : m_components (std::move (components))
+ {
+ }
+
+ void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high) override;
+
+ bool uses_objfile (struct objfile *objfile) override;
+
+ void dump (ui_file *stream, int depth) override;
+
+private:
+
+ std::vector<ada_component_up> m_components;
+};
+
+/* A component that assigns according to a provided index (which is
+ relative to the "low" value). */
+class ada_positional_component : public ada_component
+{
+public:
+
+ ada_positional_component (int index, operation_up &&op)
+ : m_index (index),
+ m_op (std::move (op))
+ {
+ }
+
+ void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high) override;
+
+ bool uses_objfile (struct objfile *objfile) override;
+
+ void dump (ui_file *stream, int depth) override;
+
+private:
+
+ int m_index;
+ operation_up m_op;
+};
+
+/* A component which handles an "others" clause. */
+class ada_others_component : public ada_component
+{
+public:
+
+ explicit ada_others_component (operation_up &&op)
+ : m_op (std::move (op))
+ {
+ }
+
+ void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high) override;
+
+ bool uses_objfile (struct objfile *objfile) override;
+
+ void dump (ui_file *stream, int depth) override;
+
+private:
+
+ operation_up m_op;
+};
+
+/* An interface that represents an association that is used in
+ aggregate assignment. */
+class ada_association
+{
+public:
+
+ /* Like ada_component::assign, but takes an operation as a
+ parameter. The operation is evaluated and then assigned into LHS
+ according to the rules of the concrete implementation. */
+ virtual void assign (struct value *container,
+ struct value *lhs,
+ struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high,
+ operation_up &op) = 0;
+
+ /* Same as operation::uses_objfile. */
+ virtual bool uses_objfile (struct objfile *objfile) = 0;
+
+ /* Same as operation::dump. */
+ virtual void dump (ui_file *stream, int depth) = 0;
+
+ virtual ~ada_association () = default;
+
+protected:
+
+ ada_association () = default;
+ DISABLE_COPY_AND_ASSIGN (ada_association);
+};
+
+/* Unique pointer specialization for Ada assignment associations. */
+typedef std::unique_ptr<ada_association> ada_association_up;
+
+/* A component that holds a vector of associations and an operation.
+ The operation is re-evaluated for each choice. */
+class ada_choices_component : public ada_component
+{
+public:
+
+ explicit ada_choices_component (operation_up &&op)
+ : m_op (std::move (op))
+ {
+ }
+
+ /* Set the vector of associations. This is done separately from the
+ constructor because it was simpler for the implementation of the
+ parser. */
+ void set_associations (std::vector<ada_association_up> &&assoc)
+ {
+ m_assocs = std::move (assoc);
+ }
+
+ void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high) override;
+
+ bool uses_objfile (struct objfile *objfile) override;
+
+ void dump (ui_file *stream, int depth) override;
+
+private:
+
+ std::vector<ada_association_up> m_assocs;
+ operation_up m_op;
+};
+
+/* An association that uses a discrete range. */
+class ada_discrete_range_association : public ada_association
+{
+public:
+
+ ada_discrete_range_association (operation_up &&low, operation_up &&high)
+ : m_low (std::move (low)),
+ m_high (std::move (high))
+ {
+ }
+
+ void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high,
+ operation_up &op) override;
+
+ bool uses_objfile (struct objfile *objfile) override;
+
+ void dump (ui_file *stream, int depth) override;
+
+private:
+
+ operation_up m_low;
+ operation_up m_high;
+};
+
+/* An association that uses a name. The name may be an expression
+ that evaluates to an integer (for arrays), or an Ada string or
+ variable value operation. */
+class ada_name_association : public ada_association
+{
+public:
+
+ explicit ada_name_association (operation_up val)
+ : m_val (std::move (val))
+ {
+ }
+
+ void assign (struct value *container,
+ struct value *lhs, struct expression *exp,
+ std::vector<LONGEST> &indices,
+ LONGEST low, LONGEST high,
+ operation_up &op) override;
+
+ bool uses_objfile (struct objfile *objfile) override;
+
+ void dump (ui_file *stream, int depth) override;
+
+private:
+
+ operation_up m_val;
+};
} /* namespace expr */