[v3,154/206] Split out some Ada type resolution code

Message ID 20210220201609.838264-155-tom@tromey.com
State New
Headers show
Series
  • Refactor expressions
Related show

Commit Message

Tom Tromey Feb. 20, 2021, 8:15 p.m.
This splits some Ada type resolution code out of resolve_subexp into
new functions that can be reused.

gdb/ChangeLog
2021-02-20  Tom Tromey  <tom@tromey.com>

	* ada-lang.h (ada_find_operator_symbol, ada_resolve_funcall)
	(ada_resolve_variable): Declare.
	* ada-lang.c (ada_find_operator_symbol, ada_resolve_funcall)
	(ada_resolve_variable): New functions.
	(resolve_subexp): Update.
---
 gdb/ChangeLog  |   8 ++
 gdb/ada-lang.c | 266 ++++++++++++++++++++++++++++---------------------
 gdb/ada-lang.h |  38 +++++++
 3 files changed, 196 insertions(+), 116 deletions(-)

-- 
2.26.2

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 8dfbe18c5b8..06762749a70 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -3456,6 +3456,132 @@  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;
+      int n_candidates = ada_lookup_symbol_list (ada_decoded_op_name (op),
+						 NULL, VAR_DOMAIN,
+						 &candidates);
+      int i = ada_resolve_function (candidates.data (), n_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;
+  int n_candidates = ada_lookup_symbol_list (sym->linkage_name (), block,
+					     VAR_DOMAIN, &candidates);
+
+  int i;
+  if (n_candidates == 1)
+    i = 0;
+  else
+    {
+      i = ada_resolve_function (candidates.data (), n_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;
+  int n_candidates = ada_lookup_symbol_list (sym->linkage_name (),
+					     block, VAR_DOMAIN,
+					     &candidates);
+
+  if (n_candidates > 1)
+    {
+      /* Types tend to get re-introduced locally, so if there are any
+	 local symbols that are not types, first filter out all
+	 types.  */
+      int j;
+      for (j = 0; j < n_candidates; j += 1)
+	switch (SYMBOL_CLASS (candidates[j].symbol))
+	  {
+	  case LOC_REGISTER:
+	  case LOC_ARG:
+	  case LOC_REF_ARG:
+	  case LOC_REGPARM_ADDR:
+	  case LOC_LOCAL:
+	  case LOC_COMPUTED:
+	    goto FoundNonType;
+	  default:
+	    break;
+	  }
+    FoundNonType:
+      if (j < n_candidates)
+	{
+	  j = 0;
+	  while (j < n_candidates)
+	    {
+	      if (SYMBOL_CLASS (candidates[j].symbol) == LOC_TYPEDEF)
+		{
+		  candidates[j] = candidates[n_candidates - 1];
+		  n_candidates -= 1;
+		}
+	      else
+		j += 1;
+	    }
+	}
+    }
+
+  int i;
+  if (n_candidates == 0)
+    error (_("No definition found for %s"), sym->print_name ());
+  else if (n_candidates == 1)
+    i = 0;
+  else if (deprocedure_p
+	   && !is_nonfunction (candidates.data (), n_candidates))
+    {
+      i = ada_resolve_function (candidates.data (), n_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 (), n_candidates, 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
@@ -3660,77 +3786,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;
-	  int n_candidates;
-
-	  n_candidates =
-	    ada_lookup_symbol_list (exp->elts[pc + 2].symbol->linkage_name (),
-				    exp->elts[pc + 1].block, VAR_DOMAIN,
-				    &candidates);
-
-	  if (n_candidates > 1)
-	    {
-	      /* Types tend to get re-introduced locally, so if there
-		 are any local symbols that are not types, first filter
-		 out all types.  */
-	      int j;
-	      for (j = 0; j < n_candidates; j += 1)
-		switch (SYMBOL_CLASS (candidates[j].symbol))
-		  {
-		  case LOC_REGISTER:
-		  case LOC_ARG:
-		  case LOC_REF_ARG:
-		  case LOC_REGPARM_ADDR:
-		  case LOC_LOCAL:
-		  case LOC_COMPUTED:
-		    goto FoundNonType;
-		  default:
-		    break;
-		  }
-	    FoundNonType:
-	      if (j < n_candidates)
-		{
-		  j = 0;
-		  while (j < n_candidates)
-		    {
-		      if (SYMBOL_CLASS (candidates[j].symbol) == LOC_TYPEDEF)
-			{
-			  candidates[j] = candidates[n_candidates - 1];
-			  n_candidates -= 1;
-			}
-		      else
-			j += 1;
-		    }
-		}
-	    }
-
-	  if (n_candidates == 0)
-	    error (_("No definition found for %s"),
-		   exp->elts[pc + 2].symbol->print_name ());
-	  else if (n_candidates == 1)
-	    i = 0;
-	  else if (deprocedure_p
-		   && !is_nonfunction (candidates.data (), n_candidates))
-	    {
-	      i = ada_resolve_function
-		(candidates.data (), n_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 (), n_candidates, 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
@@ -3749,31 +3811,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;
-	    int n_candidates;
-
-	    n_candidates =
-	      ada_lookup_symbol_list (exp->elts[pc + 5].symbol->linkage_name (),
-				      exp->elts[pc + 4].block, VAR_DOMAIN,
-				      &candidates);
-
-	    if (n_candidates == 1)
-	      i = 0;
-	    else
-	      {
-		i = ada_resolve_function
-		  (candidates.data (), n_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;
@@ -3798,27 +3843,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;
-	  int n_candidates;
-
-	  n_candidates =
-	    ada_lookup_symbol_list (ada_decoded_op_name (op),
-				    NULL, VAR_DOMAIN,
-				    &candidates);
-
-	  i = ada_resolve_function (candidates.data (), n_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:
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index dbf45a84928..2473fe92e4b 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -386,4 +386,42 @@  extern void print_ada_task_info (struct ui_out *uiout,
 				 const char *taskno_str,
 				 struct inferior *inf);
 
+/* Look for a symbol for an overloaded operator for the operation OP.
+   PARSE_COMPLETION is nonzero if currently parsing for completion.
+   NARGS and ARGVEC describe the arguments to the call.  Returns a
+   "null" block_symbol if no such operator is found.  */
+
+extern block_symbol ada_find_operator_symbol (enum exp_opcode op,
+					      int parse_completion,
+					      int nargs, value *argvec[]);
+
+/* Resolve a function call, selecting among possible function symbols.
+   SYM and BLOCK are passed to ada_lookup_symbol_list.  CONTEXT_TYPE
+   describes the calling context.  PARSE_COMPLETION is nonzero if
+   currently parsing for completion.  NARGS and ARGVEC describe the
+   arguments to the call.  This returns the chosen symbol and will
+   update TRACKER accordingly.  */
+
+extern 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);
+
+/* Resolve a symbol reference, selecting among possible values.  SYM
+   and BLOCK are passed to ada_lookup_symbol_list.  CONTEXT_TYPE
+   describes the calling context.  PARSE_COMPLETION is nonzero if
+   currently parsing for completion.  If DEPROCEDURE_P is nonzero,
+   then a symbol that names a zero-argument function will be passed
+   through ada_resolve_function.  This returns the chosen symbol and
+   will update TRACKER accordingly.  */
+
+extern 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);
+
 #endif