#include "gdbsupport/function-view.h"
#include "gdbsupport/byte-vector.h"
#include <algorithm>
+#include "ada-exp.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
return n_chosen;
}
+/* See ada-lang.h. */
+
+block_symbol
+ada_find_operator_symbol (enum exp_opcode op, int parse_completion,
+ int nargs, value *argvec[])
+{
+ if (possible_user_operator_p (op, argvec))
+ {
+ std::vector<struct block_symbol> candidates
+ = ada_lookup_symbol_list (ada_decoded_op_name (op),
+ NULL, VAR_DOMAIN);
+
+ int i = ada_resolve_function (candidates, argvec,
+ nargs, ada_decoded_op_name (op), NULL,
+ parse_completion);
+ if (i >= 0)
+ return candidates[i];
+ }
+ return {};
+}
+
+/* See ada-lang.h. */
+
+block_symbol
+ada_resolve_funcall (struct symbol *sym, const struct block *block,
+ struct type *context_type,
+ int parse_completion,
+ int nargs, value *argvec[],
+ innermost_block_tracker *tracker)
+{
+ std::vector<struct block_symbol> candidates
+ = ada_lookup_symbol_list (sym->linkage_name (), block, VAR_DOMAIN);
+
+ int i;
+ if (candidates.size () == 1)
+ i = 0;
+ else
+ {
+ i = ada_resolve_function
+ (candidates,
+ argvec, nargs,
+ sym->linkage_name (),
+ context_type, parse_completion);
+ if (i < 0)
+ error (_("Could not find a match for %s"), sym->print_name ());
+ }
+
+ tracker->update (candidates[i]);
+ return candidates[i];
+}
+
+/* See ada-lang.h. */
+
+block_symbol
+ada_resolve_variable (struct symbol *sym, const struct block *block,
+ struct type *context_type,
+ int parse_completion,
+ int deprocedure_p,
+ innermost_block_tracker *tracker)
+{
+ std::vector<struct block_symbol> candidates
+ = ada_lookup_symbol_list (sym->linkage_name (), block, VAR_DOMAIN);
+
+ if (std::any_of (candidates.begin (),
+ candidates.end (),
+ [] (block_symbol &bsym)
+ {
+ switch (SYMBOL_CLASS (bsym.symbol))
+ {
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_COMPUTED:
+ return true;
+ default:
+ return false;
+ }
+ }))
+ {
+ /* Types tend to get re-introduced locally, so if there
+ are any local symbols that are not types, first filter
+ out all types. */
+ candidates.erase
+ (std::remove_if
+ (candidates.begin (),
+ candidates.end (),
+ [] (block_symbol &bsym)
+ {
+ return SYMBOL_CLASS (bsym.symbol) == LOC_TYPEDEF;
+ }),
+ candidates.end ());
+ }
+
+ int i;
+ if (candidates.empty ())
+ error (_("No definition found for %s"), sym->print_name ());
+ else if (candidates.size () == 1)
+ i = 0;
+ else if (deprocedure_p && !is_nonfunction (candidates))
+ {
+ i = ada_resolve_function
+ (candidates, NULL, 0,
+ sym->linkage_name (),
+ context_type, parse_completion);
+ if (i < 0)
+ error (_("Could not find a match for %s"), sym->print_name ());
+ }
+ else
+ {
+ printf_filtered (_("Multiple matches for %s\n"), sym->print_name ());
+ user_select_syms (candidates.data (), candidates.size (), 1);
+ i = 0;
+ }
+
+ tracker->update (candidates[i]);
+ return candidates[i];
+}
+
/* Resolve the operator of the subexpression beginning at
position *POS of *EXPP. "Resolving" consists of replacing
the symbols that have undefined namespaces in OP_VAR_VALUE nodes
case OP_VAR_VALUE:
if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
{
- std::vector<struct block_symbol> candidates
- = ada_lookup_symbol_list (exp->elts[pc + 2].symbol->linkage_name (),
- exp->elts[pc + 1].block, VAR_DOMAIN);
-
- if (std::any_of (candidates.begin (),
- candidates.end (),
- [] (block_symbol &sym)
- {
- switch (SYMBOL_CLASS (sym.symbol))
- {
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM_ADDR:
- case LOC_LOCAL:
- case LOC_COMPUTED:
- return true;
- default:
- return false;
- }
- }))
- {
- /* Types tend to get re-introduced locally, so if there
- are any local symbols that are not types, first filter
- out all types. */
- candidates.erase
- (std::remove_if
- (candidates.begin (),
- candidates.end (),
- [] (block_symbol &sym)
- {
- return SYMBOL_CLASS (sym.symbol) == LOC_TYPEDEF;
- }),
- candidates.end ());
- }
-
- if (candidates.empty ())
- error (_("No definition found for %s"),
- exp->elts[pc + 2].symbol->print_name ());
- else if (candidates.size () == 1)
- i = 0;
- else if (deprocedure_p && !is_nonfunction (candidates))
- {
- i = ada_resolve_function
- (candidates, NULL, 0,
- exp->elts[pc + 2].symbol->linkage_name (),
- context_type, parse_completion);
- if (i < 0)
- error (_("Could not find a match for %s"),
- exp->elts[pc + 2].symbol->print_name ());
- }
- else
- {
- printf_filtered (_("Multiple matches for %s\n"),
- exp->elts[pc + 2].symbol->print_name ());
- user_select_syms (candidates.data (), candidates.size (), 1);
- i = 0;
- }
-
- exp->elts[pc + 1].block = candidates[i].block;
- exp->elts[pc + 2].symbol = candidates[i].symbol;
- tracker->update (candidates[i]);
+ block_symbol resolved
+ = ada_resolve_variable (exp->elts[pc + 2].symbol,
+ exp->elts[pc + 1].block,
+ context_type, parse_completion,
+ deprocedure_p, tracker);
+ exp->elts[pc + 1].block = resolved.block;
+ exp->elts[pc + 2].symbol = resolved.symbol;
}
if (deprocedure_p
if (exp->elts[pc + 3].opcode == OP_VAR_VALUE
&& SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN)
{
- std::vector<struct block_symbol> candidates
- = ada_lookup_symbol_list (exp->elts[pc + 5].symbol->linkage_name (),
- exp->elts[pc + 4].block, VAR_DOMAIN);
-
- if (candidates.size () == 1)
- i = 0;
- else
- {
- i = ada_resolve_function
- (candidates,
- argvec, nargs,
- exp->elts[pc + 5].symbol->linkage_name (),
- context_type, parse_completion);
- if (i < 0)
- error (_("Could not find a match for %s"),
- exp->elts[pc + 5].symbol->print_name ());
- }
-
- exp->elts[pc + 4].block = candidates[i].block;
- exp->elts[pc + 5].symbol = candidates[i].symbol;
- tracker->update (candidates[i]);
+ block_symbol resolved
+ = ada_resolve_funcall (exp->elts[pc + 5].symbol,
+ exp->elts[pc + 4].block,
+ context_type, parse_completion,
+ nargs, argvec,
+ tracker);
+ exp->elts[pc + 4].block = resolved.block;
+ exp->elts[pc + 5].symbol = resolved.symbol;
}
}
break;
case UNOP_PLUS:
case UNOP_LOGICAL_NOT:
case UNOP_ABS:
- if (possible_user_operator_p (op, argvec))
- {
- std::vector<struct block_symbol> candidates
- = ada_lookup_symbol_list (ada_decoded_op_name (op),
- NULL, VAR_DOMAIN);
-
- i = ada_resolve_function (candidates, argvec,
- nargs, ada_decoded_op_name (op), NULL,
- parse_completion);
- if (i < 0)
- break;
+ {
+ block_symbol found = ada_find_operator_symbol (op, parse_completion,
+ nargs, argvec);
+ if (found.symbol == nullptr)
+ break;
- replace_operator_with_call (expp, pc, nargs, 1,
- candidates[i].symbol,
- candidates[i].block);
- exp = expp->get ();
- }
+ replace_operator_with_call (expp, pc, nargs, 1,
+ found.symbol, found.block);
+ exp = expp->get ();
+ }
break;
case OP_TYPE:
/* A helper function for UNOP_NEG. */
-static value *
+value *
ada_unop_neg (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
/* A helper function for UNOP_IN_RANGE. */
-static value *
+value *
ada_unop_in_range (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
/* A helper function for OP_ATR_TAG. */
-static value *
+value *
ada_atr_tag (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
/* A helper function for OP_ATR_SIZE. */
-static value *
+value *
ada_atr_size (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
/* A helper function for UNOP_ABS. */
-static value *
+value *
ada_abs (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
}
}
+/* A helper function for BINOP_EXP. */
+
+static 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)
+{
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (value_type (arg1), not_lval);
+ else
+ {
+ /* For integer exponentiation operations,
+ only promote the first argument. */
+ if (is_integral_type (value_type (arg2)))
+ unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+ else
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+
+ return value_binop (arg1, arg2, op);
+ }
+}
+
+namespace expr
+{
+
+value *
+ada_wrapped_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ value *result = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
+ if (noside == EVAL_NORMAL)
+ result = unwrap_value (result);
+
+ /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
+ then we need to perform the conversion manually, because
+ evaluate_subexp_standard doesn't do it. This conversion is
+ necessary in Ada because the different kinds of float/fixed
+ types in Ada have different representations.
+
+ Similarly, we need to perform the conversion from OP_LONG
+ ourselves. */
+ if ((opcode () == OP_FLOAT || opcode () == OP_LONG) && expect_type != NULL)
+ result = ada_value_cast (expect_type, result);
+
+ return result;
+}
+
+value *
+ada_string_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ value *result = string_operation::evaluate (expect_type, exp, noside);
+ /* The result type will have code OP_STRING, bashed there from
+ OP_ARRAY. Bash it back. */
+ if (value_type (result)->code () == TYPE_CODE_STRING)
+ value_type (result)->set_code (TYPE_CODE_ARRAY);
+ return result;
+}
+
+value *
+ada_qual_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ struct type *type = std::get<1> (m_storage);
+ return std::get<0> (m_storage)->evaluate (type, exp, noside);
+}
+
+value *
+ada_ternop_range_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ value *arg0 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
+ return eval_ternop_in_range (expect_type, exp, noside, arg0, arg1, arg2);
+}
+
+}
+
/* Implement the evaluate_exp routine in the exp_descriptor structure
for the Ada language. */
arg2 = evaluate_subexp (nullptr, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
- else if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value_zero (value_type (arg1), not_lval);
- else
- {
- /* For integer exponentiation operations,
- only promote the first argument. */
- if (is_integral_type (value_type (arg2)))
- unop_promote (exp->language_defn, exp->gdbarch, &arg1);
- else
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-
- return value_binop (arg1, arg2, op);
- }
+ return ada_binop_exp (expect_type, exp, noside, op, arg1, arg2);
case UNOP_PLUS:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);