Implement function calls for Ada

This implements function calls for Ada.  This takes a different
approach than that used for other languages, primarily because Ada
requires special treatment generally.  The "ordinary" special case for
just the callee didn't really apply neatly here; there's only one case
in Ada needing special callee treatment.

gdb/ChangeLog
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.
	(class ada_funcall_operation): New.
This commit is contained in:
Tom Tromey
2021-03-08 07:27:57 -07:00
parent ebc06ad8f4
commit efe3af2f9a
3 changed files with 168 additions and 0 deletions

View File

@ -10830,6 +10830,148 @@ ada_structop_operation::evaluate (struct type *expect_type,
}
}
value *
ada_funcall_operation::evaluate (struct type *expect_type,
struct expression *exp,
enum noside noside)
{
const std::vector<operation_up> &args_up = std::get<1> (m_storage);
int nargs = args_up.size ();
std::vector<value *> argvec (nargs);
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
&& SYMBOL_DOMAIN (avv->get_symbol ()) == UNDEF_DOMAIN)
error (_("Unexpected unresolved symbol, %s, during evaluation"),
avv->get_symbol ()->print_name ());
value *callee = callee_op->evaluate (nullptr, exp, noside);
for (int i = 0; i < args_up.size (); ++i)
argvec[i] = args_up[i]->evaluate (nullptr, exp, noside);
if (ada_is_constrained_packed_array_type
(desc_base_type (value_type (callee))))
callee = ada_coerce_to_simple_array (callee);
else if (value_type (callee)->code () == TYPE_CODE_ARRAY
&& TYPE_FIELD_BITSIZE (value_type (callee), 0) != 0)
/* This is a packed array that has already been fixed, and
therefore already coerced to a simple array. Nothing further
to do. */
;
else if (value_type (callee)->code () == TYPE_CODE_REF)
{
/* Make sure we dereference references so that all the code below
feels like it's really handling the referenced value. Wrapping
types (for alignment) may be there, so make sure we strip them as
well. */
callee = ada_to_fixed_value (coerce_ref (callee));
}
else if (value_type (callee)->code () == TYPE_CODE_ARRAY
&& VALUE_LVAL (callee) == lval_memory)
callee = value_addr (callee);
struct type *type = ada_check_typedef (value_type (callee));
/* Ada allows us to implicitly dereference arrays when subscripting
them. So, if this is an array typedef (encoding use for array
access types encoded as fat pointers), strip it now. */
if (type->code () == TYPE_CODE_TYPEDEF)
type = ada_typedef_target_type (type);
if (type->code () == TYPE_CODE_PTR)
{
switch (ada_check_typedef (TYPE_TARGET_TYPE (type))->code ())
{
case TYPE_CODE_FUNC:
type = ada_check_typedef (TYPE_TARGET_TYPE (type));
break;
case TYPE_CODE_ARRAY:
break;
case TYPE_CODE_STRUCT:
if (noside != EVAL_AVOID_SIDE_EFFECTS)
callee = ada_value_ind (callee);
type = ada_check_typedef (TYPE_TARGET_TYPE (type));
break;
default:
error (_("cannot subscript or call something of type `%s'"),
ada_type_name (value_type (callee)));
break;
}
}
switch (type->code ())
{
case TYPE_CODE_FUNC:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
if (TYPE_TARGET_TYPE (type) == NULL)
error_call_unknown_return_type (NULL);
return allocate_value (TYPE_TARGET_TYPE (type));
}
return call_function_by_hand (callee, NULL, argvec);
case TYPE_CODE_INTERNAL_FUNCTION:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
/* We don't know anything about what the internal
function might return, but we have to return
something. */
return value_zero (builtin_type (exp->gdbarch)->builtin_int,
not_lval);
else
return call_internal_function (exp->gdbarch, exp->language_defn,
callee, nargs,
argvec.data ());
case TYPE_CODE_STRUCT:
{
int arity;
arity = ada_array_arity (type);
type = ada_array_element_type (type, nargs);
if (type == NULL)
error (_("cannot subscript or call a record"));
if (arity != nargs)
error (_("wrong number of subscripts; expecting %d"), arity);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (ada_aligned_type (type), lval_memory);
return
unwrap_value (ada_value_subscript
(callee, nargs, argvec.data ()));
}
case TYPE_CODE_ARRAY:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
type = ada_array_element_type (type, nargs);
if (type == NULL)
error (_("element type of array unknown"));
else
return value_zero (ada_aligned_type (type), lval_memory);
}
return
unwrap_value (ada_value_subscript
(ada_coerce_to_simple_array (callee),
nargs, argvec.data ()));
case TYPE_CODE_PTR: /* Pointer to array */
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1);
type = ada_array_element_type (type, nargs);
if (type == NULL)
error (_("element type of array unknown"));
else
return value_zero (ada_aligned_type (type), lval_memory);
}
return
unwrap_value (ada_value_ptr_subscript (callee, nargs,
argvec.data ()));
default:
error (_("Attempt to index or call something other than an "
"array or function"));
}
}
}
/* Implement the evaluate_exp routine in the exp_descriptor structure