aboutsummaryrefslogtreecommitdiff
path: root/gdb/expression.h
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:13 -0700
commite2803273a078950d0895de245cdc5375f362a8c5 (patch)
tree5831732b28dc39d8afa6d009089f501fe6b0c57c /gdb/expression.h
parente18c58f290609dcfe8d7df450bb88b1adf44337a (diff)
downloadgdb-e2803273a078950d0895de245cdc5375f362a8c5.zip
gdb-e2803273a078950d0895de245cdc5375f362a8c5.tar.gz
gdb-e2803273a078950d0895de245cdc5375f362a8c5.tar.bz2
Introduce class operation
This patch introduces class operation, the new base class for all expression operations. In the new approach, an operation is simply a class that presents a certain interface. Operations own their operands, and management is done via unique_ptr. The operation interface is largely ad hoc, based on the evolution of expression handling in GDB. Parts (for example, evaluate_with_coercion) are probably redundant; however I took this approach to try to avoid mixing different kinds of refactorings. In some specific situations, rather than add a generic method across the entire operation class hierarchy, I chose instead to use dynamic_cast and specialized methods on certain concrete subclasses. This will appear in some subsequent patches. One goal of this work is to avoid the kinds of easy-to-make errors that affected the old implementation. To this end, some helper subclasses are also added here. These helpers automate the implementation of the 'dump', 'uses_objfile', and 'constant_p' methods. Nearly every concrete operation that is subsequently added will use these facilities. (Note that the 'dump' implementation is only outlined here, the body appears in the next patch.) gdb/ChangeLog 2021-03-08 Tom Tromey <tom@tromey.com> * expression.h (expr::operation): New class. (expr::make_operation): New function. (expr::operation_up): New typedef. * expop.h: New file. * eval.c (operation::evaluate_for_cast) (operation::evaluate_for_address, operation::evaluate_for_sizeof): New methods. * ax-gdb.c (operation::generate_ax): New method.
Diffstat (limited to 'gdb/expression.h')
-rw-r--r--gdb/expression.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/gdb/expression.h b/gdb/expression.h
index 397a0af..24a0eb3 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -89,6 +89,105 @@ enum noside
does in many situations. */
};
+struct expression;
+struct agent_expr;
+struct axs_value;
+struct type;
+struct ui_file;
+
+namespace expr
+{
+
+class operation;
+typedef std::unique_ptr<operation> operation_up;
+
+/* Base class for an operation. An operation is a single component of
+ an expression. */
+
+class operation
+{
+protected:
+
+ operation () = default;
+ DISABLE_COPY_AND_ASSIGN (operation);
+
+public:
+
+ virtual ~operation () = default;
+
+ /* Evaluate this operation. */
+ virtual value *evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside) = 0;
+
+ /* Evaluate this operation in a context where C-like coercion is
+ needed. */
+ virtual value *evaluate_with_coercion (struct expression *exp,
+ enum noside noside)
+ {
+ return evaluate (nullptr, exp, noside);
+ }
+
+ /* Evaluate this expression in the context of a cast to
+ EXPECT_TYPE. */
+ virtual value *evaluate_for_cast (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside);
+
+ /* Evaluate this expression in the context of a sizeof
+ operation. */
+ virtual value *evaluate_for_sizeof (struct expression *exp,
+ enum noside noside);
+
+ /* Evaluate this expression in the context of an address-of
+ operation. Must return the address. */
+ virtual value *evaluate_for_address (struct expression *exp,
+ enum noside noside);
+
+ /* True if this is a constant expression. */
+ virtual bool constant_p () const
+ { return false; }
+
+ /* Return true if this operation uses OBJFILE (and will become
+ dangling when OBJFILE is unloaded), otherwise return false.
+ OBJFILE must not be a separate debug info file. */
+ virtual bool uses_objfile (struct objfile *objfile) const
+ { return false; }
+
+ /* Generate agent expression bytecodes for this operation. */
+ void generate_ax (struct expression *exp, struct agent_expr *ax,
+ struct axs_value *value,
+ struct type *cast_type = nullptr);
+
+ /* Return the opcode that is implemented by this operation. */
+ virtual enum exp_opcode opcode () const = 0;
+
+ /* Print this operation to STREAM. */
+ virtual void dump (struct ui_file *stream, int depth) const = 0;
+
+protected:
+
+ /* Called by generate_ax to do the work for this particular
+ operation. */
+ virtual void do_generate_ax (struct expression *exp,
+ struct agent_expr *ax,
+ struct axs_value *value,
+ struct type *cast_type)
+ {
+ error (_("Cannot translate to agent expression"));
+ }
+};
+
+/* A helper function for creating an operation_up, given a type. */
+template<typename T, typename... Arg>
+operation_up
+make_operation (Arg... args)
+{
+ return operation_up (new T (std::forward<Arg> (args)...));
+}
+
+}
+
union exp_element
{
enum exp_opcode opcode;