Split out ada_ternop_slice

This splits TERNOP_SLICE into a new function for future use.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_ternop_slice): New function.
	(ada_evaluate_subexp): Use it.
This commit is contained in:
Tom Tromey
2021-03-08 07:27:57 -07:00
parent 214b13ac3b
commit 5ce19db80f
2 changed files with 88 additions and 70 deletions

View File

@ -10107,6 +10107,87 @@ ada_equal_binop (struct type *expect_type,
return value_from_longest (type, (LONGEST) tem);
}
/* A helper function for TERNOP_SLICE. */
static value *
ada_ternop_slice (struct expression *exp,
enum noside noside,
struct value *array, struct value *low_bound_val,
struct value *high_bound_val)
{
LONGEST low_bound;
LONGEST high_bound;
low_bound_val = coerce_ref (low_bound_val);
high_bound_val = coerce_ref (high_bound_val);
low_bound = value_as_long (low_bound_val);
high_bound = value_as_long (high_bound_val);
/* If this is a reference to an aligner type, then remove all
the aligners. */
if (value_type (array)->code () == TYPE_CODE_REF
&& ada_is_aligner_type (TYPE_TARGET_TYPE (value_type (array))))
TYPE_TARGET_TYPE (value_type (array)) =
ada_aligned_type (TYPE_TARGET_TYPE (value_type (array)));
if (ada_is_any_packed_array_type (value_type (array)))
error (_("cannot slice a packed array"));
/* If this is a reference to an array or an array lvalue,
convert to a pointer. */
if (value_type (array)->code () == TYPE_CODE_REF
|| (value_type (array)->code () == TYPE_CODE_ARRAY
&& VALUE_LVAL (array) == lval_memory))
array = value_addr (array);
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& ada_is_array_descriptor_type (ada_check_typedef
(value_type (array))))
return empty_array (ada_type_of_array (array, 0), low_bound,
high_bound);
array = ada_coerce_to_simple_array_ptr (array);
/* If we have more than one level of pointer indirection,
dereference the value until we get only one level. */
while (value_type (array)->code () == TYPE_CODE_PTR
&& (TYPE_TARGET_TYPE (value_type (array))->code ()
== TYPE_CODE_PTR))
array = value_ind (array);
/* Make sure we really do have an array type before going further,
to avoid a SEGV when trying to get the index type or the target
type later down the road if the debug info generated by
the compiler is incorrect or incomplete. */
if (!ada_is_simple_array_type (value_type (array)))
error (_("cannot take slice of non-array"));
if (ada_check_typedef (value_type (array))->code ()
== TYPE_CODE_PTR)
{
struct type *type0 = ada_check_typedef (value_type (array));
if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS)
return empty_array (TYPE_TARGET_TYPE (type0), low_bound, high_bound);
else
{
struct type *arr_type0 =
to_fixed_array_type (TYPE_TARGET_TYPE (type0), NULL, 1);
return ada_value_slice_from_ptr (array, arr_type0,
longest_to_int (low_bound),
longest_to_int (high_bound));
}
}
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
return array;
else if (high_bound < low_bound)
return empty_array (value_type (array), low_bound, high_bound);
else
return ada_value_slice (array, longest_to_int (low_bound),
longest_to_int (high_bound));
}
/* Implement the evaluate_exp routine in the exp_descriptor structure
for the Ada language. */
@ -10548,80 +10629,12 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
= evaluate_subexp (nullptr, exp, pos, noside);
struct value *high_bound_val
= evaluate_subexp (nullptr, exp, pos, noside);
LONGEST low_bound;
LONGEST high_bound;
low_bound_val = coerce_ref (low_bound_val);
high_bound_val = coerce_ref (high_bound_val);
low_bound = value_as_long (low_bound_val);
high_bound = value_as_long (high_bound_val);
if (noside == EVAL_SKIP)
goto nosideret;
/* If this is a reference to an aligner type, then remove all
the aligners. */
if (value_type (array)->code () == TYPE_CODE_REF
&& ada_is_aligner_type (TYPE_TARGET_TYPE (value_type (array))))
TYPE_TARGET_TYPE (value_type (array)) =
ada_aligned_type (TYPE_TARGET_TYPE (value_type (array)));
if (ada_is_any_packed_array_type (value_type (array)))
error (_("cannot slice a packed array"));
/* If this is a reference to an array or an array lvalue,
convert to a pointer. */
if (value_type (array)->code () == TYPE_CODE_REF
|| (value_type (array)->code () == TYPE_CODE_ARRAY
&& VALUE_LVAL (array) == lval_memory))
array = value_addr (array);
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& ada_is_array_descriptor_type (ada_check_typedef
(value_type (array))))
return empty_array (ada_type_of_array (array, 0), low_bound,
high_bound);
array = ada_coerce_to_simple_array_ptr (array);
/* If we have more than one level of pointer indirection,
dereference the value until we get only one level. */
while (value_type (array)->code () == TYPE_CODE_PTR
&& (TYPE_TARGET_TYPE (value_type (array))->code ()
== TYPE_CODE_PTR))
array = value_ind (array);
/* Make sure we really do have an array type before going further,
to avoid a SEGV when trying to get the index type or the target
type later down the road if the debug info generated by
the compiler is incorrect or incomplete. */
if (!ada_is_simple_array_type (value_type (array)))
error (_("cannot take slice of non-array"));
if (ada_check_typedef (value_type (array))->code ()
== TYPE_CODE_PTR)
{
struct type *type0 = ada_check_typedef (value_type (array));
if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS)
return empty_array (TYPE_TARGET_TYPE (type0), low_bound, high_bound);
else
{
struct type *arr_type0 =
to_fixed_array_type (TYPE_TARGET_TYPE (type0), NULL, 1);
return ada_value_slice_from_ptr (array, arr_type0,
longest_to_int (low_bound),
longest_to_int (high_bound));
}
}
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
return array;
else if (high_bound < low_bound)
return empty_array (value_type (array), low_bound, high_bound);
else
return ada_value_slice (array, longest_to_int (low_bound),
longest_to_int (high_bound));
return ada_ternop_slice (exp, noside, array, low_bound_val,
high_bound_val);
}
case UNOP_IN_RANGE: