aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2021-03-08 07:27:57 -0700
committerTom Tromey <tom@tromey.com>2021-03-08 07:28:36 -0700
commitd8a4ed8ad1b5d93b78efbd635d41f706902e2379 (patch)
treebba8f223a7390235a5cfe7abdad40deb36219f0e
parentefe3af2f9a6da088a00961d579318213eeb266d4 (diff)
downloadgdb-d8a4ed8ad1b5d93b78efbd635d41f706902e2379.zip
gdb-d8a4ed8ad1b5d93b78efbd635d41f706902e2379.tar.gz
gdb-d8a4ed8ad1b5d93b78efbd635d41f706902e2379.tar.bz2
Implement Ada resolution
Ada has a parser post-pass that implements "resolution". This process replaces some opcodes with function calls. For example, a "+" operation might be replaced with a call to the appropriate overloaded function. This differs from the approach taken for the same problem in C++. However, in this series I chose not to try to make changes outside of rewrite the expression data structure. So, resolution remains. The new approach to resolution is to introduce an interface class, that some concrete operations implement. Then, the Ada code will use this to resolve the expression tree. Because new-style expressions are built as ordinary objects, and don't require rewriting the data structure in place, in the new code this processing will be done in the parser. By the end of the series, some special cases in this area that exist only for Ada will be removed. gdb/ChangeLog 2021-03-08 Tom Tromey <tom@tromey.com> * ada-lang.c (ada_var_value_operation::resolve) (ada_funcall_operation::resolve) (ada_ternop_slice_operation::resolve): New methods. * ada-exp.h (struct ada_resolvable): New. (class ada_var_value_operation): Derive from ada_resolvable. <get_block, resolve>: New methods. (class ada_funcall_operation): Derive from ada_resolvable. <resolve>: New method. (class ada_ternop_slice_operation): Derive from ada_resolvable. <resolve>: New method.
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/ada-exp.h47
-rw-r--r--gdb/ada-lang.c79
3 files changed, 136 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4738350..c770a0d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,18 @@
2021-03-08 Tom Tromey <tom@tromey.com>
+ * ada-lang.c (ada_var_value_operation::resolve)
+ (ada_funcall_operation::resolve)
+ (ada_ternop_slice_operation::resolve): New methods.
+ * ada-exp.h (struct ada_resolvable): New.
+ (class ada_var_value_operation): Derive from ada_resolvable.
+ <get_block, resolve>: New methods.
+ (class ada_funcall_operation): Derive from ada_resolvable.
+ <resolve>: New method.
+ (class ada_ternop_slice_operation): Derive from ada_resolvable.
+ <resolve>: New method.
+
+2021-03-08 Tom Tromey <tom@tromey.com>
+
* ada-lang.c (ada_funcall_operation::evaluate): New method.
* ada-exp.h (class ada_var_msym_value_operation) <get_symbol>: New
method.
diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h
index 287ed5c..456aa89 100644
--- a/gdb/ada-exp.h
+++ b/gdb/ada-exp.h
@@ -79,6 +79,24 @@ extern struct value *ada_binop_exp (struct type *expect_type,
namespace expr
{
+/* The base class for Ada type resolution. Ada operations that want
+ to participate in resolution implement this interface. */
+struct ada_resolvable
+{
+ /* Resolve this object. EXP is the expression being resolved.
+ DEPROCEDURE_P is true if a symbol that refers to a zero-argument
+ function may be turned into a function call. PARSE_COMPLETION
+ and TRACKER are passed in from the parser context. CONTEXT_TYPE
+ is the expected type of the expression, or nullptr if none is
+ known. This method should return true if the operation should be
+ replaced by a function call with this object as the callee. */
+ virtual bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) = 0;
+};
+
/* In Ada, some generic operations must be wrapped with a handler that
handles some Ada-specific type conversions. */
class ada_wrapped_operation
@@ -246,7 +264,8 @@ using ada_bitwise_xor_operation = ada_bitwise_operation<BINOP_BITWISE_XOR>;
/* Ada array- or string-slice operation. */
class ada_ternop_slice_operation
- : public maybe_constant_operation<operation_up, operation_up, operation_up>
+ : public maybe_constant_operation<operation_up, operation_up, operation_up>,
+ public ada_resolvable
{
public:
@@ -264,6 +283,12 @@ public:
enum exp_opcode opcode () const override
{ return TERNOP_SLICE; }
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
};
/* Implement BINOP_IN_BOUNDS for Ada. */
@@ -306,7 +331,7 @@ public:
/* Variant of var_value_operation for Ada. */
class ada_var_value_operation
- : public var_value_operation
+ : public var_value_operation, public ada_resolvable
{
public:
@@ -323,6 +348,15 @@ public:
symbol *get_symbol () const
{ return std::get<0> (m_storage); }
+ const block *get_block () const
+ { return std::get<1> (m_storage); }
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+
protected:
using operation::do_generate_ax;
@@ -392,7 +426,8 @@ public:
/* Function calls for Ada. */
class ada_funcall_operation
- : public tuple_holding_operation<operation_up, std::vector<operation_up>>
+ : public tuple_holding_operation<operation_up, std::vector<operation_up>>,
+ public ada_resolvable
{
public:
@@ -402,6 +437,12 @@ public:
struct expression *exp,
enum noside noside) override;
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+
enum exp_opcode opcode () const override
{ return OP_FUNCALL; }
};
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 2bee8ab..261c917 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -10694,6 +10694,31 @@ ada_var_value_operation::evaluate (struct type *expect_type,
return ada_to_fixed_value (arg1);
}
+bool
+ada_var_value_operation::resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type)
+{
+ symbol *sym = std::get<0> (m_storage);
+ if (SYMBOL_DOMAIN (sym) == UNDEF_DOMAIN)
+ {
+ block_symbol resolved
+ = ada_resolve_variable (sym, std::get<1> (m_storage),
+ context_type, parse_completion,
+ deprocedure_p, tracker);
+ std::get<0> (m_storage) = resolved.symbol;
+ std::get<1> (m_storage) = resolved.block;
+ }
+
+ if (deprocedure_p
+ && SYMBOL_TYPE (std::get<0> (m_storage))->code () == TYPE_CODE_FUNC)
+ return true;
+
+ return false;
+}
+
value *
ada_atr_val_operation::evaluate (struct type *expect_type,
struct expression *exp,
@@ -10972,6 +10997,60 @@ ada_funcall_operation::evaluate (struct type *expect_type,
}
}
+bool
+ada_funcall_operation::resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type)
+{
+ operation_up &callee_op = std::get<0> (m_storage);
+
+ ada_var_value_operation *avv
+ = dynamic_cast<ada_var_value_operation *> (callee_op.get ());
+ if (avv == nullptr)
+ return false;
+
+ symbol *sym = avv->get_symbol ();
+ if (SYMBOL_DOMAIN (sym) != UNDEF_DOMAIN)
+ return false;
+
+ const std::vector<operation_up> &args_up = std::get<1> (m_storage);
+ int nargs = args_up.size ();
+ std::vector<value *> argvec (nargs);
+
+ for (int i = 0; i < args_up.size (); ++i)
+ argvec[i] = args_up[i]->evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS);
+
+ const block *block = avv->get_block ();
+ block_symbol resolved
+ = ada_resolve_funcall (sym, block,
+ context_type, parse_completion,
+ nargs, argvec.data (),
+ tracker);
+
+ std::get<0> (m_storage)
+ = make_operation<ada_var_value_operation> (resolved.symbol,
+ resolved.block);
+ return false;
+}
+
+bool
+ada_ternop_slice_operation::resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type)
+{
+ /* Historically this check was done during resolution, so we
+ continue that here. */
+ value *v = std::get<0> (m_storage)->evaluate (context_type, exp,
+ EVAL_AVOID_SIDE_EFFECTS);
+ if (ada_is_any_packed_array_type (value_type (v)))
+ error (_("cannot slice a packed array"));
+ return false;
+}
+
}
/* Implement the evaluate_exp routine in the exp_descriptor structure