Split out some Ada type resolution code
[deliverable/binutils-gdb.git] / gdb / ada-lang.c
index 910eec87a6a49aa79ee7a96c9549a2fad0fd25f4..098a5a6858f71cb99a9c3caa3dc237ccf6da436b 100644 (file)
@@ -57,6 +57,7 @@
 #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).
@@ -3413,6 +3414,126 @@ See set/show multiple-symbol."));
   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
@@ -3617,68 +3738,13 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
     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
@@ -3697,27 +3763,14 @@ resolve_subexp (expression_up *expp, int *pos, int 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;
@@ -3742,23 +3795,16 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
     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:
@@ -9963,7 +10009,7 @@ eval_ternop_in_range (struct type *expect_type, struct expression *exp,
 
 /* 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,
@@ -9977,7 +10023,7 @@ ada_unop_neg (struct type *expect_type,
 
 /* 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,
@@ -10014,7 +10060,7 @@ ada_unop_in_range (struct type *expect_type,
 
 /* 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,
@@ -10028,7 +10074,7 @@ ada_atr_tag (struct type *expect_type,
 
 /* 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,
@@ -10053,7 +10099,7 @@ ada_atr_size (struct type *expect_type,
 
 /* 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,
@@ -10364,6 +10410,90 @@ ada_binop_minmax (struct type *expect_type,
     }
 }
 
+/* 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.  */
 
@@ -10926,19 +11056,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       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);
This page took 0.036028 seconds and 4 git commands to generate.