diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 47383501082..c770a0dd106 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2021-03-08 Tom Tromey + + * 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. + : New methods. + (class ada_funcall_operation): Derive from ada_resolvable. + : New method. + (class ada_ternop_slice_operation): Derive from ada_resolvable. + : New method. + 2021-03-08 Tom Tromey * ada-lang.c (ada_funcall_operation::evaluate): New method. diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h index 287ed5cc62c..456aa89c67d 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; /* Ada array- or string-slice operation. */ class ada_ternop_slice_operation - : public maybe_constant_operation + : public maybe_constant_operation, + public ada_resolvable { public: @@ -264,6 +283,12 @@ class ada_ternop_slice_operation 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 @@ class ada_unop_atr_operation /* 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 @@ class ada_var_value_operation 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 @@ class ada_structop_operation /* Function calls for Ada. */ class ada_funcall_operation - : public tuple_holding_operation> + : public tuple_holding_operation>, + public ada_resolvable { public: @@ -402,6 +437,12 @@ class ada_funcall_operation 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 2bee8abc94c..261c9176b62 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 (callee_op.get ()); + if (avv == nullptr) + return false; + + symbol *sym = avv->get_symbol (); + if (SYMBOL_DOMAIN (sym) != UNDEF_DOMAIN) + return false; + + const std::vector &args_up = std::get<1> (m_storage); + int nargs = args_up.size (); + std::vector 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 (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