diff options
-rw-r--r-- | gdb/ChangeLog | 13 | ||||
-rw-r--r-- | gdb/ada-exp.h | 47 | ||||
-rw-r--r-- | gdb/ada-lang.c | 79 |
3 files changed, 136 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4738350..c770a0d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2021-03-08 Tom Tromey <tom@tromey.com> + * ada-lang.c (ada_var_value_operation::resolve) + (ada_funcall_operation::resolve) + (ada_ternop_slice_operation::resolve): New methods. + * ada-exp.h (struct ada_resolvable): New. + (class ada_var_value_operation): Derive from ada_resolvable. + <get_block, resolve>: New methods. + (class ada_funcall_operation): Derive from ada_resolvable. + <resolve>: New method. + (class ada_ternop_slice_operation): Derive from ada_resolvable. + <resolve>: New method. + +2021-03-08 Tom Tromey <tom@tromey.com> + * ada-lang.c (ada_funcall_operation::evaluate): New method. * ada-exp.h (class ada_var_msym_value_operation) <get_symbol>: New method. diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h index 287ed5c..456aa89 100644 --- a/gdb/ada-exp.h +++ b/gdb/ada-exp.h @@ -79,6 +79,24 @@ extern struct value *ada_binop_exp (struct type *expect_type, 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 @@ -246,7 +264,8 @@ 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 maybe_constant_operation<operation_up, operation_up, operation_up>, + public ada_resolvable { public: @@ -264,6 +283,12 @@ public: 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. */ @@ -306,7 +331,7 @@ public: /* Variant of var_value_operation for Ada. */ class ada_var_value_operation - : public var_value_operation + : public var_value_operation, public ada_resolvable { public: @@ -323,6 +348,15 @@ public: symbol *get_symbol () const { return std::get<0> (m_storage); } + 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; @@ -392,7 +426,8 @@ public: /* Function calls for Ada. */ class ada_funcall_operation - : public tuple_holding_operation<operation_up, std::vector<operation_up>> + : public tuple_holding_operation<operation_up, std::vector<operation_up>>, + public ada_resolvable { public: @@ -402,6 +437,12 @@ public: 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; } }; diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 2bee8ab..261c917 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -10694,6 +10694,31 @@ ada_var_value_operation::evaluate (struct type *expect_type, return ada_to_fixed_value (arg1); } +bool +ada_var_value_operation::resolve (struct expression *exp, + bool deprocedure_p, + bool parse_completion, + innermost_block_tracker *tracker, + struct type *context_type) +{ + symbol *sym = std::get<0> (m_storage); + if (SYMBOL_DOMAIN (sym) == UNDEF_DOMAIN) + { + block_symbol resolved + = ada_resolve_variable (sym, std::get<1> (m_storage), + context_type, parse_completion, + deprocedure_p, tracker); + std::get<0> (m_storage) = resolved.symbol; + std::get<1> (m_storage) = resolved.block; + } + + if (deprocedure_p + && SYMBOL_TYPE (std::get<0> (m_storage))->code () == TYPE_CODE_FUNC) + return true; + + return false; +} + value * ada_atr_val_operation::evaluate (struct type *expect_type, struct expression *exp, @@ -10972,6 +10997,60 @@ ada_funcall_operation::evaluate (struct type *expect_type, } } +bool +ada_funcall_operation::resolve (struct expression *exp, + bool deprocedure_p, + bool parse_completion, + innermost_block_tracker *tracker, + struct type *context_type) +{ + operation_up &callee_op = std::get<0> (m_storage); + + ada_var_value_operation *avv + = dynamic_cast<ada_var_value_operation *> (callee_op.get ()); + if (avv == nullptr) + return false; + + symbol *sym = avv->get_symbol (); + if (SYMBOL_DOMAIN (sym) != UNDEF_DOMAIN) + return false; + + const std::vector<operation_up> &args_up = std::get<1> (m_storage); + int nargs = args_up.size (); + std::vector<value *> argvec (nargs); + + for (int i = 0; i < args_up.size (); ++i) + argvec[i] = args_up[i]->evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS); + + const block *block = avv->get_block (); + block_symbol resolved + = ada_resolve_funcall (sym, block, + context_type, parse_completion, + nargs, argvec.data (), + tracker); + + std::get<0> (m_storage) + = make_operation<ada_var_value_operation> (resolved.symbol, + resolved.block); + return false; +} + +bool +ada_ternop_slice_operation::resolve (struct expression *exp, + bool deprocedure_p, + bool parse_completion, + innermost_block_tracker *tracker, + struct type *context_type) +{ + /* Historically this check was done during resolution, so we + continue that here. */ + value *v = std::get<0> (m_storage)->evaluate (context_type, exp, + EVAL_AVOID_SIDE_EFFECTS); + if (ada_is_any_packed_array_type (value_type (v))) + error (_("cannot slice a packed array")); + return false; +} + } /* Implement the evaluate_exp routine in the exp_descriptor structure |