[01/12] Introduce and use aggregate_assigner type

Message ID 20240321-ada-iterated-assign-v1-1-925cdd4f1f4a@adacore.com
State New
Headers
Series Ada iterated assignment, plus parser cleanups |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed

Commit Message

Tom Tromey March 21, 2024, 7:03 p.m. UTC
  This patch is a refactoring to add a new aggregate_assigner type.
This type is passed to Ada aggregate assignment operations in place of
passing a number of separate arguments.  This new approach makes it
simpler to change some aspects of aggregate assignment behavior.
---
 gdb/ada-exp.h  |  88 +++++++++++++++++----------------
 gdb/ada-lang.c | 153 +++++++++++++++++++++++++--------------------------------
 2 files changed, 114 insertions(+), 127 deletions(-)
  

Patch

diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h
index 69d4e90e410..6122502dcdc 100644
--- a/gdb/ada-exp.h
+++ b/gdb/ada-exp.h
@@ -588,20 +588,48 @@  class ada_target_operation : public operation
   ada_assign_operation *m_lhs;
 };
 
+/* When constructing an aggregate, an object of this type is created
+   to track the needed state.  */
+
+struct aggregate_assigner
+{
+  /* An lvalue containing LHS (possibly LHS itself).  */
+  value *container;
+
+  /* An lvalue of record or array type; this is the object being
+     assigned to.  */
+  value *lhs;
+
+  /* The expression being evaluated.  */
+  expression *exp;
+
+  /* The bounds of LHS.  This is used by the 'others' component.  */
+  LONGEST low;
+  LONGEST high;
+
+  /* This indicates which sub-components have already been assigned
+     to.  */
+  std::vector<LONGEST> indices;
+
+  /* Assign the result of evaluating ARG to the INDEXth component of
+     LHS (a simple array or a record).  Does not modify the inferior's
+     memory, nor does it modify LHS (unless LHS == CONTAINER).  */
+  void assign (LONGEST index, operation_up &arg);
+
+  /* Add the interval [FROM .. TO] to the sorted set of intervals
+     [ INDICES[0] .. INDICES[1] ],...  The resulting intervals do not
+     overlap.  */
+  void add_interval (LONGEST low, LONGEST high);
+};
+
 /* This abstract class represents a single component in an Ada
    aggregate assignment.  */
 class ada_component
 {
 public:
 
-  /* Assign to LHS, which is part of CONTAINER.  EXP is the expression
-     being evaluated.  INDICES, LOW, and HIGH indicate which
-     sub-components have already been assigned; INDICES should be
-     updated by this call.  */
-  virtual void assign (struct value *container,
-		       struct value *lhs, struct expression *exp,
-		       std::vector<LONGEST> &indices,
-		       LONGEST low, LONGEST high) = 0;
+  /* Assign to ASSIGNER.  */
+  virtual void assign (aggregate_assigner &assigner) = 0;
 
   /* Same as operation::uses_objfile.  */
   virtual bool uses_objfile (struct objfile *objfile) = 0;
@@ -664,10 +692,7 @@  class ada_aggregate_component : public ada_component
   ada_aggregate_component (operation_up &&base,
 			   std::vector<ada_component_up> &&components);
 
-  void assign (struct value *container,
-	       struct value *lhs, struct expression *exp,
-	       std::vector<LONGEST> &indices,
-	       LONGEST low, LONGEST high) override;
+  void assign (aggregate_assigner &assigner) override;
 
   bool uses_objfile (struct objfile *objfile) override;
 
@@ -694,10 +719,7 @@  class ada_positional_component : public ada_component
   {
   }
 
-  void assign (struct value *container,
-	       struct value *lhs, struct expression *exp,
-	       std::vector<LONGEST> &indices,
-	       LONGEST low, LONGEST high) override;
+  void assign (aggregate_assigner &assigner) override;
 
   bool uses_objfile (struct objfile *objfile) override;
 
@@ -719,10 +741,7 @@  class ada_others_component : public ada_component
   {
   }
 
-  void assign (struct value *container,
-	       struct value *lhs, struct expression *exp,
-	       std::vector<LONGEST> &indices,
-	       LONGEST low, LONGEST high) override;
+  void assign (aggregate_assigner &assigner) override;
 
   bool uses_objfile (struct objfile *objfile) override;
 
@@ -740,14 +759,10 @@  class ada_association
 public:
 
   /* Like ada_component::assign, but takes an operation as a
-     parameter.  The operation is evaluated and then assigned into LHS
-     according to the rules of the concrete implementation.  */
-  virtual void assign (struct value *container,
-		       struct value *lhs,
-		       struct expression *exp,
-		       std::vector<LONGEST> &indices,
-		       LONGEST low, LONGEST high,
-		       operation_up &op) = 0;
+     parameter.  The operation is evaluated and then assigned into
+     ASSIGNER according to the rules of the concrete
+     implementation.  */
+  virtual void assign (aggregate_assigner &assigner, operation_up &op) = 0;
 
   /* Same as operation::uses_objfile.  */
   virtual bool uses_objfile (struct objfile *objfile) = 0;
@@ -785,10 +800,7 @@  class ada_choices_component : public ada_component
     m_assocs = std::move (assoc);
   }
 
-  void assign (struct value *container,
-	       struct value *lhs, struct expression *exp,
-	       std::vector<LONGEST> &indices,
-	       LONGEST low, LONGEST high) override;
+  void assign (aggregate_assigner &assigner) override;
 
   bool uses_objfile (struct objfile *objfile) override;
 
@@ -811,11 +823,7 @@  class ada_discrete_range_association : public ada_association
   {
   }
 
-  void assign (struct value *container,
-	       struct value *lhs, struct expression *exp,
-	       std::vector<LONGEST> &indices,
-	       LONGEST low, LONGEST high,
-	       operation_up &op) override;
+  void assign (aggregate_assigner &assigner, operation_up &op) override;
 
   bool uses_objfile (struct objfile *objfile) override;
 
@@ -839,11 +847,7 @@  class ada_name_association : public ada_association
   {
   }
 
-  void assign (struct value *container,
-	       struct value *lhs, struct expression *exp,
-	       std::vector<LONGEST> &indices,
-	       LONGEST low, LONGEST high,
-	       operation_up &op) override;
+  void assign (aggregate_assigner &assigner, operation_up &op) override;
 
   bool uses_objfile (struct objfile *objfile) override;
 
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 493ef3b6c7d..c9cbeca40bc 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -191,9 +191,6 @@  static int ada_is_direct_array_type (struct type *);
 static struct value *ada_index_struct_field (int, struct value *, int,
 					     struct type *);
 
-static void add_component_interval (LONGEST, LONGEST, std::vector<LONGEST> &);
-
-
 static struct type *ada_find_any_type (const char *name);
 
 static symbol_name_matcher_ftype *ada_get_symbol_name_matcher
@@ -9323,13 +9320,10 @@  check_objfile (const std::unique_ptr<ada_component> &comp,
   return comp->uses_objfile (objfile);
 }
 
-/* Assign the result of evaluating ARG to the INDEXth component of LHS
-   (a simple array or a record).  Does not modify the inferior's
-   memory, nor does it modify LHS (unless LHS == CONTAINER).  */
+/* See ada-exp.h.  */
 
-static void
-assign_component (struct value *container, struct value *lhs, LONGEST index,
-		  struct expression *exp, operation_up &arg)
+void
+aggregate_assigner::assign (LONGEST index, operation_up &arg)
 {
   scoped_value_mark mark;
 
@@ -9384,23 +9378,21 @@  ada_aggregate_component::dump (ui_file *stream, int depth)
 }
 
 void
-ada_aggregate_component::assign (struct value *container,
-				 struct value *lhs, struct expression *exp,
-				 std::vector<LONGEST> &indices,
-				 LONGEST low, LONGEST high)
+ada_aggregate_component::assign (aggregate_assigner &assigner)
 {
   if (m_base != nullptr)
     {
-      value *base = m_base->evaluate (nullptr, exp, EVAL_NORMAL);
+      value *base = m_base->evaluate (nullptr, assigner.exp, EVAL_NORMAL);
       if (ada_is_direct_array_type (base->type ()))
 	base = ada_coerce_to_simple_array (base);
-      if (!types_deeply_equal (container->type (), base->type ()))
+      if (!types_deeply_equal (assigner.container->type (), base->type ()))
 	error (_("Type mismatch in delta aggregate"));
-      value_assign_to_component (container, container, base);
+      value_assign_to_component (assigner.container, assigner.container,
+				 base);
     }
 
   for (auto &item : m_components)
-    item->assign (container, lhs, exp, indices, low, high);
+    item->assign (assigner);
 }
 
 /* See ada-exp.h.  */
@@ -9429,7 +9421,7 @@  ada_aggregate_operation::assign_aggregate (struct value *container,
 					   struct expression *exp)
 {
   struct type *lhs_type;
-  LONGEST low_index, high_index;
+  aggregate_assigner assigner;
 
   container = ada_coerce_ref (container);
   if (ada_is_direct_array_type (container->type ()))
@@ -9443,23 +9435,27 @@  ada_aggregate_operation::assign_aggregate (struct value *container,
     {
       lhs = ada_coerce_to_simple_array (lhs);
       lhs_type = check_typedef (lhs->type ());
-      low_index = lhs_type->bounds ()->low.const_val ();
-      high_index = lhs_type->bounds ()->high.const_val ();
+      assigner.low = lhs_type->bounds ()->low.const_val ();
+      assigner.high = lhs_type->bounds ()->high.const_val ();
     }
   else if (lhs_type->code () == TYPE_CODE_STRUCT)
     {
-      low_index = 0;
-      high_index = num_visible_fields (lhs_type) - 1;
+      assigner.low = 0;
+      assigner.high = num_visible_fields (lhs_type) - 1;
     }
   else
     error (_("Left-hand side must be array or record."));
 
-  std::vector<LONGEST> indices (4);
-  indices[0] = indices[1] = low_index - 1;
-  indices[2] = indices[3] = high_index + 1;
+  assigner.indices.push_back (assigner.low - 1);
+  assigner.indices.push_back (assigner.low - 1);
+  assigner.indices.push_back (assigner.high + 1);
+  assigner.indices.push_back (assigner.high + 1);
+
+  assigner.container = container;
+  assigner.lhs = lhs;
+  assigner.exp = exp;
 
-  std::get<0> (m_storage)->assign (container, lhs, exp, indices,
-				   low_index, high_index);
+  std::get<0> (m_storage)->assign (assigner);
 
   return container;
 }
@@ -9483,19 +9479,16 @@  ada_positional_component::dump (ui_file *stream, int depth)
    LOW, where HIGH is the upper bound.  Record the position in
    INDICES.  CONTAINER is as for assign_aggregate.  */
 void
-ada_positional_component::assign (struct value *container,
-				  struct value *lhs, struct expression *exp,
-				  std::vector<LONGEST> &indices,
-				  LONGEST low, LONGEST high)
+ada_positional_component::assign (aggregate_assigner &assigner)
 {
-  LONGEST ind = m_index + low;
+  LONGEST ind = m_index + assigner.low;
 
-  if (ind - 1 == high)
+  if (ind - 1 == assigner.high)
     warning (_("Extra components in aggregate ignored."));
-  if (ind <= high)
+  if (ind <= assigner.high)
     {
-      add_component_interval (ind, ind, indices);
-      assign_component (container, lhs, ind, exp, m_op);
+      assigner.add_interval (ind, ind);
+      assigner.assign (ind, m_op);
     }
 }
 
@@ -9514,23 +9507,21 @@  ada_discrete_range_association::dump (ui_file *stream, int depth)
 }
 
 void
-ada_discrete_range_association::assign (struct value *container,
-					struct value *lhs,
-					struct expression *exp,
-					std::vector<LONGEST> &indices,
-					LONGEST low, LONGEST high,
+ada_discrete_range_association::assign (aggregate_assigner &assigner,
 					operation_up &op)
 {
-  LONGEST lower = value_as_long (m_low->evaluate (nullptr, exp, EVAL_NORMAL));
-  LONGEST upper = value_as_long (m_high->evaluate (nullptr, exp, EVAL_NORMAL));
+  LONGEST lower = value_as_long (m_low->evaluate (nullptr, assigner.exp,
+						  EVAL_NORMAL));
+  LONGEST upper = value_as_long (m_high->evaluate (nullptr, assigner.exp,
+						   EVAL_NORMAL));
 
-  if (lower <= upper && (lower < low || upper > high))
+  if (lower <= upper && (lower < assigner.low || upper > assigner.high))
     error (_("Index in component association out of bounds."));
 
-  add_component_interval (lower, upper, indices);
+  assigner.add_interval (lower, upper);
   while (lower <= upper)
     {
-      assign_component (container, lhs, lower, exp, op);
+      assigner.assign (lower, op);
       lower += 1;
     }
 }
@@ -9549,18 +9540,16 @@  ada_name_association::dump (ui_file *stream, int depth)
 }
 
 void
-ada_name_association::assign (struct value *container,
-			      struct value *lhs,
-			      struct expression *exp,
-			      std::vector<LONGEST> &indices,
-			      LONGEST low, LONGEST high,
+ada_name_association::assign (aggregate_assigner &assigner,
 			      operation_up &op)
 {
   int index;
 
-  if (ada_is_direct_array_type (lhs->type ()))
-    index = longest_to_int (value_as_long (m_val->evaluate (nullptr, exp,
-							    EVAL_NORMAL)));
+  if (ada_is_direct_array_type (assigner.lhs->type ()))
+    {
+      value *tem = m_val->evaluate (nullptr, assigner.exp, EVAL_NORMAL);
+      index = longest_to_int (value_as_long (tem));
+    }
   else
     {
       ada_string_operation *strop
@@ -9586,13 +9575,13 @@  ada_name_association::assign (struct value *container,
 	}
 
       index = 0;
-      if (! find_struct_field (name, lhs->type (), 0,
+      if (! find_struct_field (name, assigner.lhs->type (), 0,
 			       NULL, NULL, NULL, NULL, &index))
 	error (_("Unknown component name: %s."), name);
     }
 
-  add_component_interval (index, index, indices);
-  assign_component (container, lhs, index, exp, op);
+  assigner.add_interval (index, index);
+  assigner.assign (index, op);
 }
 
 bool
@@ -9620,13 +9609,10 @@  ada_choices_component::dump (ui_file *stream, int depth)
    the allowable indices are LOW..HIGH.  Record the indices assigned
    to in INDICES.  CONTAINER is as for assign_aggregate.  */
 void
-ada_choices_component::assign (struct value *container,
-			       struct value *lhs, struct expression *exp,
-			       std::vector<LONGEST> &indices,
-			       LONGEST low, LONGEST high)
+ada_choices_component::assign (aggregate_assigner &assigner)
 {
   for (auto &item : m_assocs)
-    item->assign (container, lhs, exp, indices, low, high, m_op);
+    item->assign (assigner, m_op);
 }
 
 bool
@@ -9647,16 +9633,15 @@  ada_others_component::dump (ui_file *stream, int depth)
    have not been previously assigned.  The index intervals already assigned
    are in INDICES.  CONTAINER is as for assign_aggregate.  */
 void
-ada_others_component::assign (struct value *container,
-			      struct value *lhs, struct expression *exp,
-			      std::vector<LONGEST> &indices,
-			      LONGEST low, LONGEST high)
+ada_others_component::assign (aggregate_assigner &assigner)
 {
-  int num_indices = indices.size ();
+  int num_indices = assigner.indices.size ();
   for (int i = 0; i < num_indices - 2; i += 2)
     {
-      for (LONGEST ind = indices[i + 1] + 1; ind < indices[i + 2]; ind += 1)
-	assign_component (container, lhs, ind, exp, m_op);
+      for (LONGEST ind = assigner.indices[i + 1] + 1;
+	   ind < assigner.indices[i + 2];
+	   ind += 1)
+	assigner.assign (ind, m_op);
     }
 }
 
@@ -9697,46 +9682,44 @@  ada_assign_operation::evaluate (struct type *expect_type,
   return ada_value_assign (arg1, arg2);
 }
 
-} /* namespace expr */
+/* See ada-exp.h.  */
 
-/* Add the interval [LOW .. HIGH] to the sorted set of intervals
-   [ INDICES[0] .. INDICES[1] ],...  The resulting intervals do not
-   overlap.  */
-static void
-add_component_interval (LONGEST low, LONGEST high, 
-			std::vector<LONGEST> &indices)
+void
+aggregate_assigner::add_interval (LONGEST from, LONGEST to)
 {
   int i, j;
 
   int size = indices.size ();
   for (i = 0; i < size; i += 2) {
-    if (high >= indices[i] && low <= indices[i + 1])
+    if (to >= indices[i] && from <= indices[i + 1])
       {
 	int kh;
 
 	for (kh = i + 2; kh < size; kh += 2)
-	  if (high < indices[kh])
+	  if (to < indices[kh])
 	    break;
-	if (low < indices[i])
-	  indices[i] = low;
+	if (from < indices[i])
+	  indices[i] = from;
 	indices[i + 1] = indices[kh - 1];
-	if (high > indices[i + 1])
-	  indices[i + 1] = high;
+	if (to > indices[i + 1])
+	  indices[i + 1] = to;
 	memcpy (indices.data () + i + 2, indices.data () + kh, size - kh);
 	indices.resize (kh - i - 2);
 	return;
       }
-    else if (high < indices[i])
+    else if (to < indices[i])
       break;
   }
 	
   indices.resize (indices.size () + 2);
   for (j = indices.size () - 1; j >= i + 2; j -= 1)
     indices[j] = indices[j - 2];
-  indices[i] = low;
-  indices[i + 1] = high;
+  indices[i] = from;
+  indices[i + 1] = to;
 }
 
+} /* namespace expr */
+
 /* Perform and Ada cast of ARG2 to type TYPE if the type of ARG2
    is different.  */