* [PATCH 00/12] Ada iterated assignment, plus parser cleanups
@ 2024-03-21 19:03 Tom Tromey
2024-03-21 19:03 ` [PATCH 01/12] Introduce and use aggregate_assigner type Tom Tromey
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This series implements the Ada 2022 iterated assignment feature. An
earlier version of the patch failed to clear a new global in the
parser, so I also ended up tacking on a series to make sure this
problem can't happen again -- all parser state is moved into a new
object. (All the parsers should do this, or go further and follow
Rust into recursive descent, IMNSHO.)
Tested on x86-64 Fedora 38. This has also been running inside AdaCore
for a while now.
---
Tom Tromey (12):
Introduce and use aggregate_assigner type
Implement Ada 2022 iterated assignment
Introduce ada_parse_state
Move "int_storage" global into ada_parse_state
Move "components" and "associations" into ada_parse_state
Move "assignments" global into ada_parse_state
Move "iterated_associations" into ada_parse_state
Move "temp_parse_space" into ada_parse_state
Move "paren_depth" into ada_parse_state
Move "returned_complete" into ada_parse_state
Remove "numbuf" global
Constify ada-lex.l:attributes
gdb/ada-exp.h | 165 ++++++++++++++-----
gdb/ada-exp.y | 212 ++++++++++++++++---------
gdb/ada-lang.c | 202 +++++++++++++----------
gdb/ada-lex.l | 48 +++---
gdb/testsuite/gdb.ada/iterated-assign.exp | 37 +++++
gdb/testsuite/gdb.ada/iterated-assign/main.adb | 24 +++
gdb/testsuite/gdb.ada/iterated-assign/pck.adb | 23 +++
gdb/testsuite/gdb.ada/iterated-assign/pck.ads | 26 +++
8 files changed, 509 insertions(+), 228 deletions(-)
---
base-commit: 7e949f08700b077b78e955c653eb4e9455027101
change-id: 20240321-ada-iterated-assign-da4127ab3d6d
Best regards,
--
Tom Tromey <tromey@adacore.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/12] Introduce and use aggregate_assigner type
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 02/12] Implement Ada 2022 iterated assignment Tom Tromey
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
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(-)
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. */
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 02/12] Implement Ada 2022 iterated assignment
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
2024-03-21 19:03 ` [PATCH 01/12] Introduce and use aggregate_assigner type Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 03/12] Introduce ada_parse_state Tom Tromey
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
Ada 2022 includes iterated assignment for array initialization. This
patch implements a subset of this for gdb. In particular, only arrays
with integer index types really work -- currently there's no decent
way to get the index type in EVAL_AVOID_SIDE_EFFECTS mode during
parsing. Fixing this probably requires the Ada parser to take a
somewhat more sophisticated approach to type resolution; and while
this would help fix another bug in this area, this patch is already
useful without it.
---
gdb/ada-exp.h | 77 ++++++++++++++++++++++++++
gdb/ada-exp.y | 52 +++++++++++++++--
gdb/ada-lang.c | 49 +++++++++++++++-
gdb/ada-lex.l | 1 +
gdb/testsuite/gdb.ada/iterated-assign.exp | 37 +++++++++++++
gdb/testsuite/gdb.ada/iterated-assign/main.adb | 24 ++++++++
gdb/testsuite/gdb.ada/iterated-assign/pck.adb | 23 ++++++++
gdb/testsuite/gdb.ada/iterated-assign/pck.ads | 26 +++++++++
8 files changed, 284 insertions(+), 5 deletions(-)
diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h
index 6122502dcdc..94e4ea0f47e 100644
--- a/gdb/ada-exp.h
+++ b/gdb/ada-exp.h
@@ -611,6 +611,15 @@ struct aggregate_assigner
to. */
std::vector<LONGEST> indices;
+private:
+
+ /* The current index value. This is only valid during the 'assign'
+ operation and is part of the implementation of iterated component
+ association. */
+ LONGEST m_current_index = 0;
+
+public:
+
/* 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). */
@@ -620,6 +629,10 @@ struct aggregate_assigner
[ INDICES[0] .. INDICES[1] ],... The resulting intervals do not
overlap. */
void add_interval (LONGEST low, LONGEST high);
+
+ /* Return the current index as a value, using the index type of
+ LHS. */
+ value *current_value () const;
};
/* This abstract class represents a single component in an Ada
@@ -800,16 +813,80 @@ class ada_choices_component : public ada_component
m_assocs = std::move (assoc);
}
+ /* Set the underlying operation */
+ void set_operation (operation_up op)
+ { m_op = std::move (op); }
+
+ /* Set the index variable name for an iterated association. */
+ void set_name (std::string &&name)
+ { m_name = std::move (name); }
+
+ /* The name of this choice component. This is empty unless this is
+ an iterated association. */
+ const std::string &name () const
+ { return m_name; }
+
void assign (aggregate_assigner &assigner) override;
bool uses_objfile (struct objfile *objfile) override;
void dump (ui_file *stream, int depth) override;
+ /* Return the current value of the index variable. This may only be
+ called underneath a call to 'assign'. */
+ value *current_value () const
+ { return m_assigner->current_value (); }
+
private:
std::vector<ada_association_up> m_assocs;
operation_up m_op;
+
+ /* Name of the variable used for iteration. This isn't needed for
+ evaluation, only for debug dumping. This is the empty string for
+ ordinary (non-iterated) choices. */
+ std::string m_name;
+
+ /* A pointer to the current assignment operation; only valid when in
+ a call to the 'assign' method. This is used to find the index
+ variable value during the evaluation of the RHS of the =>, via
+ ada_index_var_operation. */
+ const aggregate_assigner *m_assigner = nullptr;
+};
+
+/* Implement the index variable for iterated component
+ association. */
+class ada_index_var_operation : public operation
+{
+public:
+
+ ada_index_var_operation ()
+ { }
+
+ /* Link this variable to the choices object. May only be called
+ once. */
+ void set_choices (ada_choices_component *var)
+ {
+ gdb_assert (m_var == nullptr && var != nullptr);
+ m_var = var;
+ }
+
+ value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) override;
+
+ enum exp_opcode opcode () const override
+ {
+ /* It doesn't really matter. */
+ return OP_VAR_VALUE;
+ }
+
+ void dump (struct ui_file *stream, int depth) const override;
+
+private:
+
+ /* The choices component that introduced the index variable. */
+ ada_choices_component *m_var = nullptr;
};
/* An association that uses a discrete range. */
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 2b205714d7a..c0a5b0534a6 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -422,6 +422,10 @@ typedef std::unique_ptr<ada_assign_operation> ada_assign_up;
to implement '@', the target name symbol. */
static std::vector<ada_assign_up> assignments;
+/* Track currently active iterated assignment names. */
+static std::unordered_map<std::string, std::vector<ada_index_var_operation *>>
+ iterated_associations;
+
%}
%union
@@ -488,7 +492,7 @@ static std::vector<ada_assign_up> assignments;
forces a.b.c, e.g., to be LEFT-associated. */
%right '.' '(' '[' DOT_ID DOT_COMPLETE
-%token NEW OTHERS
+%token NEW OTHERS FOR
\f
%%
@@ -1098,6 +1102,33 @@ component_group :
ada_choices_component *choices = choice_component ();
choices->set_associations (pop_associations ($1));
}
+ | FOR NAME IN
+ {
+ std::string name = copy_name ($2);
+
+ auto iter = iterated_associations.find (name);
+ if (iter != iterated_associations.end ())
+ error (_("Nested use of index parameter '%s'"),
+ name.c_str ());
+
+ iterated_associations[name] = {};
+ }
+ component_associations
+ {
+ std::string name = copy_name ($2);
+
+ ada_choices_component *choices = choice_component ();
+ choices->set_associations (pop_associations ($5));
+
+ auto iter = iterated_associations.find (name);
+ gdb_assert (iter != iterated_associations.end ());
+ for (ada_index_var_operation *var : iter->second)
+ var->set_choices (choices);
+
+ iterated_associations.erase (name);
+
+ choices->set_name (std::move (name));
+ }
;
/* We use this somewhat obscure definition in order to handle NAME => and
@@ -1207,6 +1238,7 @@ ada_parse (struct parser_state *par_state)
associations.clear ();
int_storage.clear ();
assignments.clear ();
+ iterated_associations.clear ();
int result = yyparse ();
if (!result)
@@ -1652,10 +1684,22 @@ write_var_or_type (struct parser_state *par_state,
char *encoded_name;
int name_len;
- if (block == NULL)
- block = par_state->expression_context_block;
-
std::string name_storage = ada_encode (name0.ptr);
+
+ if (block == nullptr)
+ {
+ auto iter = iterated_associations.find (name_storage);
+ if (iter != iterated_associations.end ())
+ {
+ auto op = std::make_unique<ada_index_var_operation> ();
+ iter->second.push_back (op.get ());
+ par_state->push (std::move (op));
+ return nullptr;
+ }
+
+ block = par_state->expression_context_block;
+ }
+
name_len = name_storage.size ();
encoded_name = obstack_strndup (&temp_parse_space, name_storage.c_str (),
name_len);
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index c9cbeca40bc..d65ac70f251 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -9343,6 +9343,8 @@ aggregate_assigner::assign (LONGEST index, operation_up &arg)
elt = ada_to_fixed_value (elt);
}
+ scoped_restore save_index = make_scoped_restore (&m_current_index, index);
+
ada_aggregate_operation *ag_op
= dynamic_cast<ada_aggregate_operation *> (arg.get ());
if (ag_op != nullptr)
@@ -9353,6 +9355,18 @@ aggregate_assigner::assign (LONGEST index, operation_up &arg)
EVAL_NORMAL));
}
+/* See ada-exp.h. */
+
+value *
+aggregate_assigner::current_value () const
+{
+ /* Note that using an integer type here is incorrect -- the type
+ should be the array's index type. Unfortunately, though, this
+ isn't currently available during parsing and type resolution. */
+ struct type *index_type = builtin_type (exp->gdbarch)->builtin_int;
+ return value_from_longest (index_type, m_current_index);
+}
+
bool
ada_aggregate_component::uses_objfile (struct objfile *objfile)
{
@@ -9598,8 +9612,15 @@ ada_choices_component::uses_objfile (struct objfile *objfile)
void
ada_choices_component::dump (ui_file *stream, int depth)
{
- gdb_printf (stream, _("%*sChoices:\n"), depth, "");
+ if (m_name.empty ())
+ gdb_printf (stream, _("%*sChoices:\n"), depth, "");
+ else
+ {
+ gdb_printf (stream, _("%*sIterated choices:\n"), depth, "");
+ gdb_printf (stream, _("%*sName: %s\n"), depth + 1, "", m_name.c_str ());
+ }
m_op->dump (stream, depth + 1);
+
for (const auto &item : m_assocs)
item->dump (stream, depth + 1);
}
@@ -9611,10 +9632,36 @@ ada_choices_component::dump (ui_file *stream, int depth)
void
ada_choices_component::assign (aggregate_assigner &assigner)
{
+ scoped_restore save_index = make_scoped_restore (&m_assigner, &assigner);
for (auto &item : m_assocs)
item->assign (assigner, m_op);
}
+void
+ada_index_var_operation::dump (struct ui_file *stream, int depth) const
+{
+ gdb_printf (stream, _("%*sIndex variable: %s\n"), depth, "",
+ m_var->name ().c_str ());
+}
+
+value *
+ada_index_var_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* Note that using an integer type here is incorrect -- the type
+ should be the array's index type. Unfortunately, though,
+ this isn't currently available during parsing and type
+ resolution. */
+ struct type *index_type = builtin_type (exp->gdbarch)->builtin_int;
+ return value::zero (index_type, not_lval);
+ }
+
+ return m_var->current_value ();
+}
+
bool
ada_others_component::uses_objfile (struct objfile *objfile)
{
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index c54cd5e452a..e1abf9adc25 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -227,6 +227,7 @@ abs { return ABS; }
and { return _AND_; }
delta { return DELTA; }
else { return ELSE; }
+for { return FOR; }
in { return IN; }
mod { return MOD; }
new { return NEW; }
diff --git a/gdb/testsuite/gdb.ada/iterated-assign.exp b/gdb/testsuite/gdb.ada/iterated-assign.exp
new file mode 100644
index 00000000000..76b038fb45c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/iterated-assign.exp
@@ -0,0 +1,37 @@
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile main
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/main.adb]
+runto "main.adb:$bp_location"
+
+gdb_test "print a1 := (for i in 1..4 => 2 * i + 1)" \
+ " = \\(3, 5, 7, 9\\)" \
+ "simple iterated assignment"
+
+gdb_test "print a2 := (for i in 1..2 => (for j in 1..2 => 3 * i + j))" \
+ " = \\(\\(4, 5\\), \\(7, 8\\)\\)" \
+ "nested iterated assignment"
diff --git a/gdb/testsuite/gdb.ada/iterated-assign/main.adb b/gdb/testsuite/gdb.ada/iterated-assign/main.adb
new file mode 100644
index 00000000000..239c22cd8a8
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/iterated-assign/main.adb
@@ -0,0 +1,24 @@
+-- Copyright 2024 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+with pck; use pck;
+
+procedure Main is
+ A1 : Other_Array_Type := (2, 4, 6, 8);
+ A2 : MD_Array_Type := ((1, 2), (3, 4));
+begin
+ Do_Nothing (A1'Address); -- STOP
+ Do_Nothing (A2'Address);
+end Main;
diff --git a/gdb/testsuite/gdb.ada/iterated-assign/pck.adb b/gdb/testsuite/gdb.ada/iterated-assign/pck.adb
new file mode 100644
index 00000000000..14580e66be1
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/iterated-assign/pck.adb
@@ -0,0 +1,23 @@
+-- Copyright 2024 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package body Pck is
+
+ procedure Do_Nothing (A : System.Address) is
+ begin
+ null;
+ end Do_Nothing;
+
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/iterated-assign/pck.ads b/gdb/testsuite/gdb.ada/iterated-assign/pck.ads
new file mode 100644
index 00000000000..b77af7264c4
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/iterated-assign/pck.ads
@@ -0,0 +1,26 @@
+-- Copyright 2024 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+with System;
+
+package Pck is
+
+ type Other_Array_Type is array (1 .. 4) of Integer;
+
+ type MD_Array_Type is array (1 .. 2, 1 .. 2) of Integer;
+
+ procedure Do_Nothing (A : System.Address);
+
+end Pck;
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 03/12] Introduce ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
2024-03-21 19:03 ` [PATCH 01/12] Introduce and use aggregate_assigner type Tom Tromey
2024-03-21 19:03 ` [PATCH 02/12] Implement Ada 2022 iterated assignment Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 04/12] Move "int_storage" global into ada_parse_state Tom Tromey
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This patch introduces the ada_parse_state class and the ada_parser
global. It also changes find_completion_bounds to be a method of this
new type.
Note that find_completion_bounds never used its parameter; and because
it is generally fine to use the 'pstate' global throughout the parser,
this patch removes the parameter entirely.
---
gdb/ada-exp.y | 51 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 34 insertions(+), 17 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index c0a5b0534a6..9452e63ab60 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -65,8 +65,26 @@ struct name_info {
static struct parser_state *pstate = NULL;
-/* The original expression string. */
-static const char *original_expr;
+/* Data that must be held for the duration of a parse. */
+
+struct ada_parse_state
+{
+ explicit ada_parse_state (const char *expr)
+ : m_original_expr (expr)
+ {
+ }
+
+ std::string find_completion_bounds ();
+
+private:
+
+ /* The original expression string. */
+ const char *m_original_expr;
+};
+
+/* The current Ada parser object. */
+
+static ada_parse_state *ada_parser;
/* We don't have a good way to manage non-POD data in Yacc, so store
values here. The storage here is only valid for the duration of
@@ -102,8 +120,6 @@ static struct type *type_for_char (struct parser_state *, ULONGEST);
static struct type *type_system_address (struct parser_state *);
-static std::string find_completion_bounds (struct parser_state *);
-
using namespace expr;
/* Handle Ada type resolution for OP. DEPROCEDURE_P and CONTEXT_TYPE
@@ -549,7 +565,7 @@ primary : primary DOT_COMPLETE
ada_structop_operation *str_op
= (new ada_structop_operation
(std::move (arg), copy_name ($2)));
- str_op->set_prefix (find_completion_bounds (pstate));
+ str_op->set_prefix (ada_parser->find_completion_bounds ());
pstate->push (operation_up (str_op));
pstate->mark_struct_expression (str_op);
}
@@ -1223,10 +1239,11 @@ int
ada_parse (struct parser_state *par_state)
{
/* Setting up the parser state. */
- scoped_restore pstate_restore = make_scoped_restore (&pstate);
+ scoped_restore pstate_restore = make_scoped_restore (&pstate, par_state);
gdb_assert (par_state != NULL);
- pstate = par_state;
- original_expr = par_state->lexptr;
+
+ ada_parse_state parser (par_state->lexptr);
+ scoped_restore parser_restore = make_scoped_restore (&ada_parser, &parser);
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
par_state->debug);
@@ -1849,13 +1866,13 @@ write_var_or_type (struct parser_state *par_state,
Without this, an attempt like "complete print abc.d" will give a
result like "print def" rather than "print abc.def". */
-static std::string
-find_completion_bounds (struct parser_state *par_state)
+std::string
+ada_parse_state::find_completion_bounds ()
{
const char *end = pstate->lexptr;
/* First the end of the prefix. Here we stop at the token start or
at '.' or space. */
- for (; end > original_expr && end[-1] != '.' && !isspace (end[-1]); --end)
+ for (; end > m_original_expr && end[-1] != '.' && !isspace (end[-1]); --end)
{
/* Nothing. */
}
@@ -1863,11 +1880,11 @@ find_completion_bounds (struct parser_state *par_state)
const char *ptr = end;
/* Here we allow '.'. */
for (;
- ptr > original_expr && (ptr[-1] == '.'
- || ptr[-1] == '_'
- || (ptr[-1] >= 'a' && ptr[-1] <= 'z')
- || (ptr[-1] >= 'A' && ptr[-1] <= 'Z')
- || (ptr[-1] & 0xff) >= 0x80);
+ ptr > m_original_expr && (ptr[-1] == '.'
+ || ptr[-1] == '_'
+ || (ptr[-1] >= 'a' && ptr[-1] <= 'z')
+ || (ptr[-1] >= 'A' && ptr[-1] <= 'Z')
+ || (ptr[-1] & 0xff) >= 0x80);
--ptr)
{
/* Nothing. */
@@ -1903,7 +1920,7 @@ write_var_or_type_completion (struct parser_state *par_state,
ada_structop_operation *op = write_selectors (par_state,
name0.ptr + tail_index);
- op->set_prefix (find_completion_bounds (par_state));
+ op->set_prefix (ada_parser->find_completion_bounds ());
par_state->mark_struct_expression (op);
return nullptr;
}
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 04/12] Move "int_storage" global into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (2 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 03/12] Introduce ada_parse_state Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 05/12] Move "components" and "associations" " Tom Tromey
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This patch moves the "int_storage" global into ada_parse_state.
---
gdb/ada-exp.y | 17 +++++++++++------
gdb/ada-lex.l | 3 +--
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 9452e63ab60..a8066414468 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -76,8 +76,19 @@ struct ada_parse_state
std::string find_completion_bounds ();
+ const gdb_mpz *push_integer (gdb_mpz &&val)
+ {
+ auto &result = m_int_storage.emplace_back (new gdb_mpz (std::move (val)));
+ return result.get ();
+ }
+
private:
+ /* We don't have a good way to manage non-POD data in Yacc, so store
+ values here. The storage here is only valid for the duration of
+ the parse. */
+ std::vector<std::unique_ptr<gdb_mpz>> m_int_storage;
+
/* The original expression string. */
const char *m_original_expr;
};
@@ -86,11 +97,6 @@ private:
static ada_parse_state *ada_parser;
-/* We don't have a good way to manage non-POD data in Yacc, so store
- values here. The storage here is only valid for the duration of
- the parse. */
-static std::vector<std::unique_ptr<gdb_mpz>> int_storage;
-
int yyparse (void);
static int yylex (void);
@@ -1253,7 +1259,6 @@ ada_parse (struct parser_state *par_state)
obstack_init (&temp_parse_space);
components.clear ();
associations.clear ();
- int_storage.clear ();
assignments.clear ();
iterated_associations.clear ();
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index e1abf9adc25..109b95ccc35 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -465,8 +465,7 @@ processInt (struct parser_state *par_state, const char *base0,
return FLOAT;
}
- const gdb_mpz *value
- = int_storage.emplace_back (new gdb_mpz (std::move (result))).get ();
+ const gdb_mpz *value = ada_parser->push_integer (std::move (result));
int int_bits = gdbarch_int_bit (par_state->gdbarch ());
int long_bits = gdbarch_long_bit (par_state->gdbarch ());
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 05/12] Move "components" and "associations" into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (3 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 04/12] Move "int_storage" global into ada_parse_state Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 06/12] Move "assignments" global " Tom Tromey
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This patch moves the "components" and "associations" globals into
ada_parse_state.
---
gdb/ada-exp.y | 32 +++++++++++++++-----------------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index a8066414468..25809b6aa24 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -65,6 +65,8 @@ struct name_info {
static struct parser_state *pstate = NULL;
+using namespace expr;
+
/* Data that must be held for the duration of a parse. */
struct ada_parse_state
@@ -82,6 +84,12 @@ struct ada_parse_state
return result.get ();
}
+ /* The components being constructed during this parse. */
+ std::vector<ada_component_up> components;
+
+ /* The associations being constructed during this parse. */
+ std::vector<ada_association_up> associations;
+
private:
/* We don't have a good way to manage non-POD data in Yacc, so store
@@ -126,8 +134,6 @@ static struct type *type_for_char (struct parser_state *, ULONGEST);
static struct type *type_system_address (struct parser_state *);
-using namespace expr;
-
/* Handle Ada type resolution for OP. DEPROCEDURE_P and CONTEXT_TYPE
are passed to the resolve method, if called. */
static operation_up
@@ -336,16 +342,13 @@ ada_funcall (int nargs)
pstate->push (std::move (funcall));
}
-/* The components being constructed during this parse. */
-static std::vector<ada_component_up> components;
-
/* Create a new ada_component_up of the indicated type and arguments,
and push it on the global 'components' vector. */
template<typename T, typename... Arg>
void
push_component (Arg... args)
{
- components.emplace_back (new T (std::forward<Arg> (args)...));
+ ada_parser->components.emplace_back (new T (std::forward<Arg> (args)...));
}
/* Examine the final element of the 'components' vector, and return it
@@ -355,7 +358,7 @@ push_component (Arg... args)
static ada_choices_component *
choice_component ()
{
- ada_component *last = components.back ().get ();
+ ada_component *last = ada_parser->components.back ().get ();
return gdb::checked_static_cast<ada_choices_component *> (last);
}
@@ -364,8 +367,8 @@ choice_component ()
static ada_component_up
pop_component ()
{
- ada_component_up result = std::move (components.back ());
- components.pop_back ();
+ ada_component_up result = std::move (ada_parser->components.back ());
+ ada_parser->components.pop_back ();
return result;
}
@@ -380,16 +383,13 @@ pop_components (int n)
return result;
}
-/* The associations being constructed during this parse. */
-static std::vector<ada_association_up> associations;
-
/* Create a new ada_association_up of the indicated type and
arguments, and push it on the global 'associations' vector. */
template<typename T, typename... Arg>
void
push_association (Arg... args)
{
- associations.emplace_back (new T (std::forward<Arg> (args)...));
+ ada_parser->associations.emplace_back (new T (std::forward<Arg> (args)...));
}
/* Pop the most recent association from the global stack, and return
@@ -397,8 +397,8 @@ push_association (Arg... args)
static ada_association_up
pop_association ()
{
- ada_association_up result = std::move (associations.back ());
- associations.pop_back ();
+ ada_association_up result = std::move (ada_parser->associations.back ());
+ ada_parser->associations.pop_back ();
return result;
}
@@ -1257,8 +1257,6 @@ ada_parse (struct parser_state *par_state)
lexer_init (yyin); /* (Re-)initialize lexer. */
obstack_free (&temp_parse_space, NULL);
obstack_init (&temp_parse_space);
- components.clear ();
- associations.clear ();
assignments.clear ();
iterated_associations.clear ();
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 06/12] Move "assignments" global into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (4 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 05/12] Move "components" and "associations" " Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 07/12] Move "iterated_associations" " Tom Tromey
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This patch moves the "assignments" global into ada_parse_state.
---
gdb/ada-exp.y | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 25809b6aa24..1c5ffff3290 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -67,6 +67,9 @@ static struct parser_state *pstate = NULL;
using namespace expr;
+/* A convenience typedef. */
+typedef std::unique_ptr<ada_assign_operation> ada_assign_up;
+
/* Data that must be held for the duration of a parse. */
struct ada_parse_state
@@ -90,6 +93,10 @@ struct ada_parse_state
/* The associations being constructed during this parse. */
std::vector<ada_association_up> associations;
+ /* The stack of currently active assignment expressions. This is used
+ to implement '@', the target name symbol. */
+ std::vector<ada_assign_up> assignments;
+
private:
/* We don't have a good way to manage non-POD data in Yacc, so store
@@ -437,13 +444,6 @@ make_tick_completer (struct stoken tok)
(new ada_tick_completer (std::string (tok.ptr, tok.length))));
}
-/* A convenience typedef. */
-typedef std::unique_ptr<ada_assign_operation> ada_assign_up;
-
-/* The stack of currently active assignment expressions. This is used
- to implement '@', the target name symbol. */
-static std::vector<ada_assign_up> assignments;
-
/* Track currently active iterated assignment names. */
static std::unordered_map<std::string, std::vector<ada_index_var_operation *>>
iterated_associations;
@@ -528,14 +528,14 @@ exp1 : exp
{ ada_wrap2<comma_operation> (BINOP_COMMA); }
| primary ASSIGN
{
- assignments.emplace_back
+ ada_parser->assignments.emplace_back
(new ada_assign_operation (ada_pop (), nullptr));
}
exp /* Extension for convenience */
{
ada_assign_up assign
- = std::move (assignments.back ());
- assignments.pop_back ();
+ = std::move (ada_parser->assignments.back ());
+ ada_parser->assignments.pop_back ();
value *lhs_val = (assign->eval_for_resolution
(pstate->expout.get ()));
@@ -646,11 +646,11 @@ primary : aggregate
primary : '@'
{
- if (assignments.empty ())
+ if (ada_parser->assignments.empty ())
error (_("the target name symbol ('@') may only "
"appear in an assignment context"));
ada_assign_operation *current
- = assignments.back ().get ();
+ = ada_parser->assignments.back ().get ();
pstate->push_new<ada_target_operation> (current);
}
;
@@ -1257,7 +1257,6 @@ ada_parse (struct parser_state *par_state)
lexer_init (yyin); /* (Re-)initialize lexer. */
obstack_free (&temp_parse_space, NULL);
obstack_init (&temp_parse_space);
- assignments.clear ();
iterated_associations.clear ();
int result = yyparse ();
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 07/12] Move "iterated_associations" into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (5 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 06/12] Move "assignments" global " Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 08/12] Move "temp_parse_space" " Tom Tromey
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This patch moves the "iterated_associations" global into
ada_parse_state.
---
gdb/ada-exp.y | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 1c5ffff3290..615b74d14d8 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -97,6 +97,10 @@ struct ada_parse_state
to implement '@', the target name symbol. */
std::vector<ada_assign_up> assignments;
+ /* Track currently active iterated assignment names. */
+ std::unordered_map<std::string, std::vector<ada_index_var_operation *>>
+ iterated_associations;
+
private:
/* We don't have a good way to manage non-POD data in Yacc, so store
@@ -444,10 +448,6 @@ make_tick_completer (struct stoken tok)
(new ada_tick_completer (std::string (tok.ptr, tok.length))));
}
-/* Track currently active iterated assignment names. */
-static std::unordered_map<std::string, std::vector<ada_index_var_operation *>>
- iterated_associations;
-
%}
%union
@@ -1128,12 +1128,12 @@ component_group :
{
std::string name = copy_name ($2);
- auto iter = iterated_associations.find (name);
- if (iter != iterated_associations.end ())
+ auto iter = ada_parser->iterated_associations.find (name);
+ if (iter != ada_parser->iterated_associations.end ())
error (_("Nested use of index parameter '%s'"),
name.c_str ());
- iterated_associations[name] = {};
+ ada_parser->iterated_associations[name] = {};
}
component_associations
{
@@ -1142,12 +1142,12 @@ component_group :
ada_choices_component *choices = choice_component ();
choices->set_associations (pop_associations ($5));
- auto iter = iterated_associations.find (name);
- gdb_assert (iter != iterated_associations.end ());
+ auto iter = ada_parser->iterated_associations.find (name);
+ gdb_assert (iter != ada_parser->iterated_associations.end ());
for (ada_index_var_operation *var : iter->second)
var->set_choices (choices);
- iterated_associations.erase (name);
+ ada_parser->iterated_associations.erase (name);
choices->set_name (std::move (name));
}
@@ -1257,7 +1257,6 @@ ada_parse (struct parser_state *par_state)
lexer_init (yyin); /* (Re-)initialize lexer. */
obstack_free (&temp_parse_space, NULL);
obstack_init (&temp_parse_space);
- iterated_associations.clear ();
int result = yyparse ();
if (!result)
@@ -1707,8 +1706,8 @@ write_var_or_type (struct parser_state *par_state,
if (block == nullptr)
{
- auto iter = iterated_associations.find (name_storage);
- if (iter != iterated_associations.end ())
+ auto iter = ada_parser->iterated_associations.find (name_storage);
+ if (iter != ada_parser->iterated_associations.end ())
{
auto op = std::make_unique<ada_index_var_operation> ();
iter->second.push_back (op.get ());
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 08/12] Move "temp_parse_space" into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (6 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 07/12] Move "iterated_associations" " Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 09/12] Move "paren_depth" " Tom Tromey
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This patch moves the "temp_parse_space" global into ada_parse_state.
It is also renamed to remove the redundant "parse". Finally, it is
changed to an auto_obstack to avoid the need for any manual
management.
---
gdb/ada-exp.y | 28 +++++++++++-----------------
gdb/ada-lex.l | 7 ++++---
2 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 615b74d14d8..73178a58a0c 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -101,6 +101,8 @@ struct ada_parse_state
std::unordered_map<std::string, std::vector<ada_index_var_operation *>>
iterated_associations;
+ auto_obstack temp_space;
+
private:
/* We don't have a good way to manage non-POD data in Yacc, so store
@@ -1234,8 +1236,6 @@ primary : '*' primary %prec '.'
#define yyrestart ada_yyrestart
#define yytext ada_yytext
-static struct obstack temp_parse_space;
-
/* The following kludge was found necessary to prevent conflicts between */
/* defs.h and non-standard stdlib.h files. */
#define qsort __qsort__dummy
@@ -1255,8 +1255,6 @@ ada_parse (struct parser_state *par_state)
par_state->debug);
lexer_init (yyin); /* (Re-)initialize lexer. */
- obstack_free (&temp_parse_space, NULL);
- obstack_init (&temp_parse_space);
int result = yyparse ();
if (!result)
@@ -1323,7 +1321,7 @@ write_object_renaming (struct parser_state *par_state,
if (orig_left_context == NULL)
orig_left_context = get_selected_block (NULL);
- name = obstack_strndup (&temp_parse_space, renamed_entity,
+ name = obstack_strndup (&ada_parser->temp_space, renamed_entity,
renamed_entity_len);
ada_lookup_encoded_symbol (name, orig_left_context, SEARCH_VFT, &sym_info);
if (sym_info.symbol == NULL)
@@ -1389,7 +1387,8 @@ write_object_renaming (struct parser_state *par_state,
if (end == NULL)
end = renaming_expr + strlen (renaming_expr);
- index_name = obstack_strndup (&temp_parse_space, renaming_expr,
+ index_name = obstack_strndup (&ada_parser->temp_space,
+ renaming_expr,
end - renaming_expr);
renaming_expr = end;
@@ -1608,10 +1607,10 @@ static void
write_ambiguous_var (struct parser_state *par_state,
const struct block *block, const char *name, int len)
{
- struct symbol *sym = new (&temp_parse_space) symbol ();
+ struct symbol *sym = new (&ada_parser->temp_space) symbol ();
sym->set_domain (UNDEF_DOMAIN);
- sym->set_linkage_name (obstack_strndup (&temp_parse_space, name, len));
+ sym->set_linkage_name (obstack_strndup (&ada_parser->temp_space, name, len));
sym->set_language (language_ada, nullptr);
block_symbol bsym { sym, block };
@@ -1719,7 +1718,8 @@ write_var_or_type (struct parser_state *par_state,
}
name_len = name_storage.size ();
- encoded_name = obstack_strndup (&temp_parse_space, name_storage.c_str (),
+ encoded_name = obstack_strndup (&ada_parser->temp_space,
+ name_storage.c_str (),
name_len);
for (depth = 0; depth < MAX_RENAMING_CHAIN_LENGTH; depth += 1)
{
@@ -1765,7 +1765,8 @@ write_var_or_type (struct parser_state *par_state,
{
int alloc_len = renaming_len + name_len - tail_index + 1;
char *new_name
- = (char *) obstack_alloc (&temp_parse_space, alloc_len);
+ = (char *) obstack_alloc (&ada_parser->temp_space,
+ alloc_len);
strncpy (new_name, renaming, renaming_len);
strcpy (new_name + renaming_len, encoded_name + tail_index);
encoded_name = new_name;
@@ -1987,10 +1988,3 @@ type_system_address (struct parser_state *par_state)
"system__address");
return type != NULL ? type : parse_type (par_state)->builtin_data_ptr;
}
-
-void _initialize_ada_exp ();
-void
-_initialize_ada_exp ()
-{
- obstack_init (&temp_parse_space);
-}
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 109b95ccc35..90cb5ba1b8a 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -531,7 +531,7 @@ processReal (struct parser_state *par_state, const char *num0)
static struct stoken
processId (const char *name0, int len)
{
- char *name = (char *) obstack_alloc (&temp_parse_space, len + 11);
+ char *name = (char *) obstack_alloc (&ada_parser->temp_space, len + 11);
int i0, i;
struct stoken result;
@@ -593,7 +593,7 @@ processString (const char *text, int len)
const char *lim = text + len;
struct stoken result;
- q = (char *) obstack_alloc (&temp_parse_space, len);
+ q = (char *) obstack_alloc (&ada_parser->temp_space, len);
result.ptr = q;
p = text;
while (p < lim)
@@ -706,7 +706,8 @@ processAttribute (const char *str)
{
/* This is enforced by YY_INPUT. */
gdb_assert (pstate->parse_completion);
- yylval.sval.ptr = obstack_strndup (&temp_parse_space, str, len - 1);
+ yylval.sval.ptr = obstack_strndup (&ada_parser->temp_space,
+ str, len - 1);
yylval.sval.length = len - 1;
return TICK_COMPLETE;
}
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 09/12] Move "paren_depth" into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (7 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 08/12] Move "temp_parse_space" " Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 10/12] Move "returned_complete" " Tom Tromey
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This moves the "paren_depth" global into ada_parse_state.
---
gdb/ada-exp.y | 3 +++
gdb/ada-lex.l | 12 ++++--------
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 73178a58a0c..2b058571492 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -103,6 +103,9 @@ struct ada_parse_state
auto_obstack temp_space;
+ /* Depth of parentheses, used by the lexer. */
+ int paren_depth = 0;
+
private:
/* We don't have a good way to manage non-POD data in Yacc, so store
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 90cb5ba1b8a..9161c4377c0 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -108,9 +108,6 @@ static bool returned_complete = false;
pstate->lexptr += 1; \
}
-/* Depth of parentheses. */
-static int paren_depth;
-
%}
%option case-insensitive interactive nodefault noyywrap
@@ -268,7 +265,7 @@ false { return FALSEKEYWORD; }
[-&*+{}@/:<>=|;\[\]] { return yytext[0]; }
-"," { if (paren_depth == 0 && pstate->comma_terminates)
+"," { if (ada_parser->paren_depth == 0 && pstate->comma_terminates)
{
rewind_to_char (',');
return 0;
@@ -277,15 +274,15 @@ false { return FALSEKEYWORD; }
return ',';
}
-"(" { paren_depth += 1; return '('; }
-")" { if (paren_depth == 0)
+"(" { ada_parser->paren_depth += 1; return '('; }
+")" { if (ada_parser->paren_depth == 0)
{
rewind_to_char (')');
return 0;
}
else
{
- paren_depth -= 1;
+ ada_parser->paren_depth -= 1;
return ')';
}
}
@@ -349,7 +346,6 @@ static void
lexer_init (FILE *inp)
{
BEGIN INITIAL;
- paren_depth = 0;
returned_complete = false;
yyrestart (inp);
}
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 10/12] Move "returned_complete" into ada_parse_state
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (8 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 09/12] Move "paren_depth" " Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 11/12] Remove "numbuf" global Tom Tromey
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
This moves the "returned_complete" global into ada_parse_state.
---
gdb/ada-exp.y | 7 +++++++
gdb/ada-lex.l | 12 ++----------
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 2b058571492..12f676b75de 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -106,6 +106,13 @@ struct ada_parse_state
/* Depth of parentheses, used by the lexer. */
int paren_depth = 0;
+ /* When completing, we'll return a special character at the end of the
+ input, to signal the completion position to the lexer. This is
+ done because flex does not have a generally useful way to detect
+ EOF in a pattern. This variable records whether the special
+ character has been emitted. */
+ bool returned_complete = false;
+
private:
/* We don't have a good way to manage non-POD data in Yacc, so store
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 9161c4377c0..11221723eb3 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -78,13 +78,6 @@ static void rewind_to_char (int);
Defining YY_NO_INPUT comments it out. */
#define YY_NO_INPUT
-/* When completing, we'll return a special character at the end of the
- input, to signal the completion position to the lexer. This is
- done because flex does not have a generally useful way to detect
- EOF in a pattern. This variable records whether the special
- character has been emitted. */
-static bool returned_complete = false;
-
/* The character we use to represent the completion point. */
#define COMPLETE_CHAR '\001'
@@ -92,9 +85,9 @@ static bool returned_complete = false;
#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
if ( *pstate->lexptr == '\000' ) \
{ \
- if (pstate->parse_completion && !returned_complete) \
+ if (pstate->parse_completion && !ada_parser->returned_complete) \
{ \
- returned_complete = true; \
+ ada_parser->returned_complete = true; \
*(BUF) = COMPLETE_CHAR; \
(RESULT) = 1; \
} \
@@ -346,7 +339,6 @@ static void
lexer_init (FILE *inp)
{
BEGIN INITIAL;
- returned_complete = false;
yyrestart (inp);
}
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 11/12] Remove "numbuf" global
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (9 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 10/12] Move "returned_complete" " Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-03-21 19:03 ` [PATCH 12/12] Constify ada-lex.l:attributes Tom Tromey
2024-04-02 17:35 ` [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
The lexer has a "numbuf" global that is only used for temporary
storage. This patch removes the global and redeclares it at the
points of use.
---
gdb/ada-lex.l | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 11221723eb3..4e99eaab036 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -59,9 +59,7 @@ DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
#define NUMERAL_WIDTH 256
#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
-/* Temporary staging for numeric literals. */
-static char numbuf[NUMERAL_WIDTH];
- static void canonicalizeNumeral (char *s1, const char *);
+static void canonicalizeNumeral (char *s1, const char *);
static struct stoken processString (const char*, int);
static int processInt (struct parser_state *, const char *, const char *,
const char *);
@@ -114,6 +112,7 @@ static void rewind_to_char (int);
"--".* { yyterminate(); }
{NUM10}{POSEXP} {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext);
char *e_ptr = strrchr (numbuf, 'e');
*e_ptr = '\0';
@@ -121,11 +120,13 @@ static void rewind_to_char (int);
}
{NUM10} {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext);
return processInt (pstate, NULL, numbuf, NULL);
}
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext);
char *e_ptr = strrchr (numbuf, 'e');
*e_ptr = '\0';
@@ -139,23 +140,27 @@ static void rewind_to_char (int);
floating-point number is formed by reinterpreting the
bytes, allowing direct control over the bits. */
{NUM10}(l{0,2}f)?"#"{HEXDIG}({HEXDIG}|_)*"#" {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext);
return processInt (pstate, numbuf, strchr (numbuf, '#') + 1,
NULL);
}
"0x"{HEXDIG}+ {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext+2);
return processInt (pstate, "16#", numbuf, NULL);
}
{NUM10}"."{NUM10}{EXP} {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext);
return processReal (pstate, numbuf);
}
{NUM10}"."{NUM10} {
+ char numbuf[NUMERAL_WIDTH];
canonicalizeNumeral (numbuf, yytext);
return processReal (pstate, numbuf);
}
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 12/12] Constify ada-lex.l:attributes
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (10 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 11/12] Remove "numbuf" global Tom Tromey
@ 2024-03-21 19:03 ` Tom Tromey
2024-04-02 17:35 ` [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-03-21 19:03 UTC (permalink / raw)
To: gdb-patches
While examining the Ada parser globals with 'nm', I noticed that the
lexer's "attributes" array should be const. This change moves it into
read-only storage.
---
gdb/ada-lex.l | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 4e99eaab036..1b1aaf89005 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -662,7 +662,7 @@ subseqMatch (const char *subseq, const char *str)
}
-static struct { const char *name; int code; }
+static const struct { const char *name; int code; }
attributes[] = {
{ "address", TICK_ADDRESS },
{ "unchecked_access", TICK_ACCESS },
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 00/12] Ada iterated assignment, plus parser cleanups
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
` (11 preceding siblings ...)
2024-03-21 19:03 ` [PATCH 12/12] Constify ada-lex.l:attributes Tom Tromey
@ 2024-04-02 17:35 ` Tom Tromey
12 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-04-02 17:35 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:
Tom> This series implements the Ada 2022 iterated assignment feature. An
Tom> earlier version of the patch failed to clear a new global in the
Tom> parser, so I also ended up tacking on a series to make sure this
Tom> problem can't happen again -- all parser state is moved into a new
Tom> object. (All the parsers should do this, or go further and follow
Tom> Rust into recursive descent, IMNSHO.)
Tom> Tested on x86-64 Fedora 38. This has also been running inside AdaCore
Tom> for a while now.
I'm checking this in now.
Tom
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2024-04-02 17:35 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-21 19:03 [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
2024-03-21 19:03 ` [PATCH 01/12] Introduce and use aggregate_assigner type Tom Tromey
2024-03-21 19:03 ` [PATCH 02/12] Implement Ada 2022 iterated assignment Tom Tromey
2024-03-21 19:03 ` [PATCH 03/12] Introduce ada_parse_state Tom Tromey
2024-03-21 19:03 ` [PATCH 04/12] Move "int_storage" global into ada_parse_state Tom Tromey
2024-03-21 19:03 ` [PATCH 05/12] Move "components" and "associations" " Tom Tromey
2024-03-21 19:03 ` [PATCH 06/12] Move "assignments" global " Tom Tromey
2024-03-21 19:03 ` [PATCH 07/12] Move "iterated_associations" " Tom Tromey
2024-03-21 19:03 ` [PATCH 08/12] Move "temp_parse_space" " Tom Tromey
2024-03-21 19:03 ` [PATCH 09/12] Move "paren_depth" " Tom Tromey
2024-03-21 19:03 ` [PATCH 10/12] Move "returned_complete" " Tom Tromey
2024-03-21 19:03 ` [PATCH 11/12] Remove "numbuf" global Tom Tromey
2024-03-21 19:03 ` [PATCH 12/12] Constify ada-lex.l:attributes Tom Tromey
2024-04-02 17:35 ` [PATCH 00/12] Ada iterated assignment, plus parser cleanups Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox