mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-01 13:26:47 +08:00
Add an expr::operation_up to struct expression
This adds an expr::operation_up to struct expression, and then modifies various parts of GDB to use this member when it is non-null. The list of such spots was a bit surprising to me, and found only after writing most of the code and then noticing what no longer compiled. In a few spots, new accessor methods are added to operation subclasses, so that code that dissects an expression will work with the new scheme. After this change, code that constructs an expression can be switched to the new form without breaking. gdb/ChangeLog 2021-03-08 Tom Tromey <tom@tromey.com> * ada-exp.h (class ada_var_value_operation) <get_symbol>: Remove; now in superclass. * value.h (fetch_subexp_value): Add "op" parameter. * value.c (init_if_undefined_command): Update. * tracepoint.c (validate_actionline, encode_actions_1): Update. * stap-probe.c (stap_probe::compile_to_ax): Update. * printcmd.c (set_command): Update. * ppc-linux-nat.c (ppc_linux_nat_target::check_condition): Update. * parser-defs.h (struct expr_builder) <set_operation>: New method. * parse.c (parse_exp_in_context, exp_uses_objfile): Update. * expression.h (struct expression) <first_opcode>: Update. <op>: New member. * expprint.c (dump_raw_expression, dump_prefix_expression): Update. * expop.h (class var_value_operation) <get_symbol>: New method. (class register_operation) <get_name>: New method. (class equal_operation): No longer a typedef, now a subclass. (class unop_memval_operation) <get_type>: New method. (class assign_operation) <get_lhs>: New method. (class unop_cast_operation) <get_type>: New method. * eval.c (evaluate_expression, evaluate_type) (evaluate_subexpression_type): Update. (fetch_subexp_value): Add "op" parameter. (parse_and_eval_type): Update. * dtrace-probe.c (dtrace_probe::compile_to_ax): Update. * breakpoint.c (update_watchpoint, watchpoint_check) (watchpoint_exp_is_const, watch_command_1): Update. * ax-gdb.c (gen_trace_for_expr, gen_eval_for_expr, gen_printf): Update.
This commit is contained in:
parent
b0f9164cc6
commit
413403fc34
@ -1,3 +1,37 @@
|
||||
2021-03-08 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* ada-exp.h (class ada_var_value_operation) <get_symbol>: Remove;
|
||||
now in superclass.
|
||||
* value.h (fetch_subexp_value): Add "op" parameter.
|
||||
* value.c (init_if_undefined_command): Update.
|
||||
* tracepoint.c (validate_actionline, encode_actions_1): Update.
|
||||
* stap-probe.c (stap_probe::compile_to_ax): Update.
|
||||
* printcmd.c (set_command): Update.
|
||||
* ppc-linux-nat.c (ppc_linux_nat_target::check_condition):
|
||||
Update.
|
||||
* parser-defs.h (struct expr_builder) <set_operation>: New
|
||||
method.
|
||||
* parse.c (parse_exp_in_context, exp_uses_objfile): Update.
|
||||
* expression.h (struct expression) <first_opcode>: Update.
|
||||
<op>: New member.
|
||||
* expprint.c (dump_raw_expression, dump_prefix_expression):
|
||||
Update.
|
||||
* expop.h (class var_value_operation) <get_symbol>: New method.
|
||||
(class register_operation) <get_name>: New method.
|
||||
(class equal_operation): No longer a typedef, now a subclass.
|
||||
(class unop_memval_operation) <get_type>: New method.
|
||||
(class assign_operation) <get_lhs>: New method.
|
||||
(class unop_cast_operation) <get_type>: New method.
|
||||
* eval.c (evaluate_expression, evaluate_type)
|
||||
(evaluate_subexpression_type): Update.
|
||||
(fetch_subexp_value): Add "op" parameter.
|
||||
(parse_and_eval_type): Update.
|
||||
* dtrace-probe.c (dtrace_probe::compile_to_ax): Update.
|
||||
* breakpoint.c (update_watchpoint, watchpoint_check)
|
||||
(watchpoint_exp_is_const, watch_command_1): Update.
|
||||
* ax-gdb.c (gen_trace_for_expr, gen_eval_for_expr, gen_printf):
|
||||
Update.
|
||||
|
||||
2021-03-08 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* ada-lang.c (ada_value_binop): Do not use op_string.
|
||||
|
@ -351,9 +351,6 @@ class ada_var_value_operation
|
||||
struct expression *exp,
|
||||
enum noside noside) override;
|
||||
|
||||
symbol *get_symbol () const
|
||||
{ return std::get<0> (m_storage); }
|
||||
|
||||
const block *get_block () const
|
||||
{ return std::get<1> (m_storage); }
|
||||
|
||||
|
19
gdb/ax-gdb.c
19
gdb/ax-gdb.c
@ -3064,7 +3064,10 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr,
|
||||
ax->tracing = 1;
|
||||
ax->trace_string = trace_string;
|
||||
value.optimized_out = 0;
|
||||
gen_expr (expr, &pc, ax.get (), &value);
|
||||
if (expr->op != nullptr)
|
||||
expr->op->generate_ax (expr, ax.get (), &value);
|
||||
else
|
||||
gen_expr (expr, &pc, ax.get (), &value);
|
||||
|
||||
/* Make sure we record the final object, and get rid of it. */
|
||||
gen_traced_pop (ax.get (), &value);
|
||||
@ -3092,7 +3095,10 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||
pc = expr->elts;
|
||||
ax->tracing = 0;
|
||||
value.optimized_out = 0;
|
||||
gen_expr (expr, &pc, ax.get (), &value);
|
||||
if (expr->op != nullptr)
|
||||
expr->op->generate_ax (expr, ax.get (), &value);
|
||||
else
|
||||
gen_expr (expr, &pc, ax.get (), &value);
|
||||
|
||||
require_rvalue (ax.get (), &value);
|
||||
|
||||
@ -3145,9 +3151,14 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
|
||||
for simplicity of collecting them on the target side. */
|
||||
for (tem = nargs - 1; tem >= 0; --tem)
|
||||
{
|
||||
pc = exprs[tem]->elts;
|
||||
value.optimized_out = 0;
|
||||
gen_expr (exprs[tem], &pc, ax.get (), &value);
|
||||
if (exprs[tem]->op != nullptr)
|
||||
exprs[tem]->op->generate_ax (exprs[tem], ax.get (), &value);
|
||||
else
|
||||
{
|
||||
pc = exprs[tem]->elts;
|
||||
gen_expr (exprs[tem], &pc, ax.get (), &value);
|
||||
}
|
||||
require_rvalue (ax.get (), &value);
|
||||
}
|
||||
|
||||
|
@ -1903,7 +1903,8 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
||||
struct value *v, *result;
|
||||
struct program_space *frame_pspace;
|
||||
|
||||
fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, false);
|
||||
fetch_subexp_value (b->exp.get (), &pc, b->exp->op.get (), &v, &result,
|
||||
&val_chain, false);
|
||||
|
||||
/* Avoid setting b->val if it's already set. The meaning of
|
||||
b->val is 'the last value' user saw, and we should update
|
||||
@ -5022,7 +5023,8 @@ watchpoint_check (bpstat bs)
|
||||
return WP_VALUE_CHANGED;
|
||||
|
||||
mark = value_mark ();
|
||||
fetch_subexp_value (b->exp.get (), &pc, &new_val, NULL, NULL, false);
|
||||
fetch_subexp_value (b->exp.get (), &pc, b->exp->op.get (), &new_val,
|
||||
NULL, NULL, false);
|
||||
|
||||
if (b->val_bitsize != 0)
|
||||
new_val = extract_bitfield_from_watchpoint_value (b, new_val);
|
||||
@ -10122,6 +10124,9 @@ break_range_command (const char *arg, int from_tty)
|
||||
static bool
|
||||
watchpoint_exp_is_const (const struct expression *exp)
|
||||
{
|
||||
if (exp->op != nullptr)
|
||||
return exp->op->constant_p ();
|
||||
|
||||
int i = exp->nelts;
|
||||
|
||||
while (i > 0)
|
||||
@ -10842,8 +10847,8 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
|
||||
exp_valid_block = tracker.block ();
|
||||
struct value *mark = value_mark ();
|
||||
struct value *val_as_value = nullptr;
|
||||
fetch_subexp_value (exp.get (), &pc, &val_as_value, &result, NULL,
|
||||
just_location);
|
||||
fetch_subexp_value (exp.get (), &pc, exp->op.get (), &val_as_value, &result,
|
||||
NULL, just_location);
|
||||
|
||||
if (val_as_value != NULL && just_location)
|
||||
{
|
||||
|
@ -730,8 +730,13 @@ dtrace_probe::compile_to_ax (struct agent_expr *expr, struct axs_value *value,
|
||||
|
||||
arg = this->get_arg_by_number (n, expr->gdbarch);
|
||||
|
||||
pc = arg->expr->elts;
|
||||
gen_expr (arg->expr.get (), &pc, expr, value);
|
||||
if (arg->expr->op != nullptr)
|
||||
arg->expr->op->generate_ax (arg->expr.get (), expr, value);
|
||||
else
|
||||
{
|
||||
pc = arg->expr->elts;
|
||||
gen_expr (arg->expr.get (), &pc, expr, value);
|
||||
}
|
||||
|
||||
require_rvalue (expr, value);
|
||||
value->type = arg->type;
|
||||
|
30
gdb/eval.c
30
gdb/eval.c
@ -120,8 +120,14 @@ expression::evaluate (struct type *expect_type, enum noside noside)
|
||||
&& !thread_stack_temporaries_enabled_p (inferior_thread ()))
|
||||
stack_temporaries.emplace (inferior_thread ());
|
||||
|
||||
int pos = 0;
|
||||
struct value *retval = evaluate_subexp (expect_type, this, &pos, noside);
|
||||
struct value *retval;
|
||||
if (op != nullptr)
|
||||
retval = op->evaluate (expect_type, this, noside);
|
||||
else
|
||||
{
|
||||
int pos = 0;
|
||||
retval = evaluate_subexp (expect_type, this, &pos, noside);
|
||||
}
|
||||
|
||||
if (stack_temporaries.has_value ()
|
||||
&& value_in_thread_stack_temporaries (retval, inferior_thread ()))
|
||||
@ -153,6 +159,8 @@ evaluate_type (struct expression *exp)
|
||||
struct value *
|
||||
evaluate_subexpression_type (struct expression *exp, int subexp)
|
||||
{
|
||||
if (exp->op != nullptr)
|
||||
return exp->op->evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS);
|
||||
return evaluate_subexp (nullptr, exp, &subexp, EVAL_AVOID_SIDE_EFFECTS);
|
||||
}
|
||||
|
||||
@ -179,8 +187,9 @@ evaluate_subexpression_type (struct expression *exp, int subexp)
|
||||
values will be left on the value chain. */
|
||||
|
||||
void
|
||||
fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
|
||||
struct value **resultp,
|
||||
fetch_subexp_value (struct expression *exp, int *pc,
|
||||
expr::operation *op,
|
||||
struct value **valp, struct value **resultp,
|
||||
std::vector<value_ref_ptr> *val_chain,
|
||||
bool preserve_errors)
|
||||
{
|
||||
@ -198,7 +207,10 @@ fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
|
||||
|
||||
try
|
||||
{
|
||||
result = evaluate_subexp (nullptr, exp, pc, EVAL_NORMAL);
|
||||
if (op == nullptr)
|
||||
result = evaluate_subexp (nullptr, exp, pc, EVAL_NORMAL);
|
||||
else
|
||||
result = op->evaluate (nullptr, exp, EVAL_NORMAL);
|
||||
}
|
||||
catch (const gdb_exception &ex)
|
||||
{
|
||||
@ -4491,5 +4503,13 @@ parse_and_eval_type (const char *p, int length)
|
||||
expression_up expr = parse_expression (tmp);
|
||||
if (expr->first_opcode () != UNOP_CAST)
|
||||
error (_("Internal error in eval_type."));
|
||||
|
||||
if (expr->op != nullptr)
|
||||
{
|
||||
expr::unop_cast_operation *op
|
||||
= dynamic_cast<expr::unop_cast_operation *> (expr->op.get ());
|
||||
return op->get_type ();
|
||||
}
|
||||
|
||||
return expr->elts[1].type;
|
||||
}
|
||||
|
49
gdb/expop.h
49
gdb/expop.h
@ -654,6 +654,12 @@ class var_value_operation
|
||||
enum exp_opcode opcode () const override
|
||||
{ return OP_VAR_VALUE; }
|
||||
|
||||
/* Return the symbol referenced by this object. */
|
||||
symbol *get_symbol () const
|
||||
{
|
||||
return std::get<0> (m_storage);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void do_generate_ax (struct expression *exp,
|
||||
@ -823,6 +829,12 @@ class register_operation
|
||||
enum exp_opcode opcode () const override
|
||||
{ return OP_REGISTER; }
|
||||
|
||||
/* Return the name of the register. */
|
||||
const char *get_name () const
|
||||
{
|
||||
return std::get<0> (m_storage).c_str ();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void do_generate_ax (struct expression *exp,
|
||||
@ -1329,7 +1341,24 @@ class comparison_operation
|
||||
}
|
||||
};
|
||||
|
||||
using equal_operation = comparison_operation<BINOP_EQUAL, eval_op_equal>;
|
||||
class equal_operation
|
||||
: public comparison_operation<BINOP_EQUAL, eval_op_equal>
|
||||
{
|
||||
public:
|
||||
|
||||
using comparison_operation::comparison_operation;
|
||||
|
||||
operation *get_lhs () const
|
||||
{
|
||||
return std::get<0> (m_storage).get ();
|
||||
}
|
||||
|
||||
operation *get_rhs () const
|
||||
{
|
||||
return std::get<1> (m_storage).get ();
|
||||
}
|
||||
};
|
||||
|
||||
using notequal_operation
|
||||
= comparison_operation<BINOP_NOTEQUAL, eval_op_notequal>;
|
||||
using less_operation = comparison_operation<BINOP_LESS, eval_op_less>;
|
||||
@ -1759,6 +1788,12 @@ class unop_memval_operation
|
||||
enum exp_opcode opcode () const override
|
||||
{ return UNOP_MEMVAL; }
|
||||
|
||||
/* Return the type referenced by this object. */
|
||||
struct type *get_type () const
|
||||
{
|
||||
return std::get<1> (m_storage);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void do_generate_ax (struct expression *exp,
|
||||
@ -1884,6 +1919,12 @@ class assign_operation
|
||||
enum exp_opcode opcode () const override
|
||||
{ return BINOP_ASSIGN; }
|
||||
|
||||
/* Return the left-hand-side of the assignment. */
|
||||
operation *get_lhs () const
|
||||
{
|
||||
return std::get<0> (m_storage).get ();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void do_generate_ax (struct expression *exp,
|
||||
@ -1942,6 +1983,12 @@ class unop_cast_operation
|
||||
enum exp_opcode opcode () const override
|
||||
{ return UNOP_CAST; }
|
||||
|
||||
/* Return the type referenced by this object. */
|
||||
struct type *get_type () const
|
||||
{
|
||||
return std::get<1> (m_storage);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void do_generate_ax (struct expression *exp,
|
||||
|
@ -725,6 +725,9 @@ dump_raw_expression (struct expression *exp, struct ui_file *stream,
|
||||
char *eltscan;
|
||||
int eltsize;
|
||||
|
||||
if (exp->op != nullptr)
|
||||
return;
|
||||
|
||||
fprintf_filtered (stream, "Dump of expression @ ");
|
||||
gdb_print_host_address (exp, stream);
|
||||
if (note)
|
||||
@ -1150,9 +1153,22 @@ dump_prefix_expression (struct expression *exp, struct ui_file *stream)
|
||||
{
|
||||
int elt;
|
||||
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
exp->op->dump (stream, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, "Dump of expression @ ");
|
||||
gdb_print_host_address (exp, stream);
|
||||
fputs_filtered (", after conversion to prefix form:\nExpression: `", stream);
|
||||
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
exp->op->dump (stream, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
print_expression (exp, stream);
|
||||
fprintf_filtered (stream, "'\n\tLanguage %s, %d elements, %ld bytes each.\n",
|
||||
exp->language_defn->name (), exp->nelts,
|
||||
|
@ -240,7 +240,9 @@ struct expression
|
||||
expression. */
|
||||
enum exp_opcode first_opcode () const
|
||||
{
|
||||
return elts[0].opcode;
|
||||
if (op != nullptr)
|
||||
return op->opcode ();
|
||||
return elts[0].opcode;
|
||||
}
|
||||
|
||||
/* Evaluate the expression. EXPECT_TYPE is the context type of the
|
||||
@ -252,6 +254,7 @@ struct expression
|
||||
const struct language_defn *language_defn;
|
||||
/* Architecture it was parsed in. */
|
||||
struct gdbarch *gdbarch;
|
||||
expr::operation_up op;
|
||||
int nelts = 0;
|
||||
union exp_element *elts;
|
||||
};
|
||||
|
23
gdb/parse.c
23
gdb/parse.c
@ -50,6 +50,7 @@
|
||||
#include "user-regs.h"
|
||||
#include <algorithm>
|
||||
#include "gdbsupport/gdb_optional.h"
|
||||
#include "c-exp.h"
|
||||
|
||||
/* Standard set of definitions for printing, dumping, prefixifying,
|
||||
* and evaluating expressions. */
|
||||
@ -1073,7 +1074,6 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
|
||||
expr_completion_state *cstate)
|
||||
{
|
||||
const struct language_defn *lang = NULL;
|
||||
int subexp;
|
||||
|
||||
if (*stringptr == 0 || **stringptr == 0)
|
||||
error_no_arg (_("expression to compute"));
|
||||
@ -1153,7 +1153,8 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
|
||||
/* If parsing for completion, allow this to succeed; but if no
|
||||
expression elements have been written, then there's nothing
|
||||
to do, so fail. */
|
||||
if (! ps.parse_completion || ps.expout_ptr == 0)
|
||||
if (! ps.parse_completion
|
||||
|| (ps.expout->op == nullptr && ps.expout_ptr == 0))
|
||||
throw;
|
||||
}
|
||||
|
||||
@ -1168,12 +1169,17 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
|
||||
dump_raw_expression (result.get (), gdb_stdlog,
|
||||
"before conversion to prefix form");
|
||||
|
||||
subexp = prefixify_expression (result.get (),
|
||||
ps.m_completion_state.expout_last_struct);
|
||||
if (out_subexp)
|
||||
*out_subexp = subexp;
|
||||
if (result->op == nullptr)
|
||||
{
|
||||
int subexp = prefixify_expression (result.get (),
|
||||
ps.m_completion_state.expout_last_struct);
|
||||
if (out_subexp)
|
||||
*out_subexp = subexp;
|
||||
|
||||
lang->post_parser (&result, &ps);
|
||||
lang->post_parser (&result, &ps);
|
||||
}
|
||||
else
|
||||
result->op->set_outermost ();
|
||||
|
||||
if (expressiondebug)
|
||||
dump_prefix_expression (result.get (), gdb_stdlog);
|
||||
@ -1441,6 +1447,9 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile)
|
||||
{
|
||||
gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
|
||||
|
||||
if (exp->op != nullptr)
|
||||
return exp->op->uses_objfile (objfile);
|
||||
|
||||
return exp_iterate (exp, exp_uses_objfile_iter, objfile);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,13 @@ struct expr_builder
|
||||
return expout->language_defn;
|
||||
}
|
||||
|
||||
/* Set the root operation of the expression that is currently being
|
||||
built. */
|
||||
void set_operation (expr::operation_up &&op)
|
||||
{
|
||||
expout->op = std::move (op);
|
||||
}
|
||||
|
||||
/* The size of the expression above. */
|
||||
|
||||
size_t expout_size;
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "arch/ppc-linux-tdesc.h"
|
||||
#include "nat/ppc-linux.h"
|
||||
#include "linux-tdep.h"
|
||||
#include "expop.h"
|
||||
|
||||
/* Similarly for the hardware watchpoint support. These requests are used
|
||||
when the PowerPC HWDEBUG ptrace interface is not available. */
|
||||
@ -2491,16 +2492,29 @@ ppc_linux_nat_target::check_condition (CORE_ADDR watch_addr,
|
||||
struct value *left_val, *right_val;
|
||||
std::vector<value_ref_ptr> left_chain, right_chain;
|
||||
|
||||
if (cond->elts[0].opcode != BINOP_EQUAL)
|
||||
if (cond->first_opcode () != BINOP_EQUAL)
|
||||
return 0;
|
||||
|
||||
fetch_subexp_value (cond, &pc, &left_val, NULL, &left_chain, false);
|
||||
expr::operation *lhs = nullptr;
|
||||
expr::operation *rhs = nullptr;
|
||||
if (cond->op != nullptr)
|
||||
{
|
||||
expr::equal_operation *eqop
|
||||
= dynamic_cast<expr::equal_operation *> (cond->op.get ());
|
||||
if (eqop != nullptr)
|
||||
{
|
||||
lhs = eqop->get_lhs ();
|
||||
rhs = eqop->get_rhs ();
|
||||
}
|
||||
}
|
||||
|
||||
fetch_subexp_value (cond, &pc, lhs, &left_val, NULL, &left_chain, false);
|
||||
num_accesses_left = num_memory_accesses (left_chain);
|
||||
|
||||
if (left_val == NULL || num_accesses_left < 0)
|
||||
return 0;
|
||||
|
||||
fetch_subexp_value (cond, &pc, &right_val, NULL, &right_chain, false);
|
||||
fetch_subexp_value (cond, &pc, rhs, &right_val, NULL, &right_chain, false);
|
||||
num_accesses_right = num_memory_accesses (right_chain);
|
||||
|
||||
if (right_val == NULL || num_accesses_right < 0)
|
||||
|
@ -1375,8 +1375,14 @@ set_command (const char *exp, int from_tty)
|
||||
{
|
||||
expression_up expr = parse_expression (exp);
|
||||
|
||||
if (expr->nelts >= 1)
|
||||
switch (expr->elts[0].opcode)
|
||||
enum exp_opcode opcode = OP_NULL;
|
||||
if (expr->op != nullptr)
|
||||
opcode = expr->op->opcode ();
|
||||
else if (expr->nelts >= 1)
|
||||
opcode = expr->elts[0].opcode;
|
||||
|
||||
if (opcode != OP_NULL)
|
||||
switch (opcode)
|
||||
{
|
||||
case UNOP_PREINCREMENT:
|
||||
case UNOP_POSTINCREMENT:
|
||||
|
@ -1429,7 +1429,10 @@ stap_probe::compile_to_ax (struct agent_expr *expr, struct axs_value *value,
|
||||
arg = this->get_arg_by_number (n, expr->gdbarch);
|
||||
|
||||
pc = arg->aexpr->elts;
|
||||
gen_expr (arg->aexpr.get (), &pc, expr, value);
|
||||
if (arg->aexpr->op != nullptr)
|
||||
arg->aexpr->op->generate_ax (arg->aexpr.get (), expr, value);
|
||||
else
|
||||
gen_expr (arg->aexpr.get (), &pc, expr, value);
|
||||
|
||||
require_rvalue (expr, value);
|
||||
value->type = arg->atype;
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "location.h"
|
||||
#include <algorithm>
|
||||
#include "cli/cli-style.h"
|
||||
#include "expop.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@ -689,19 +690,29 @@ validate_actionline (const char *line, struct breakpoint *b)
|
||||
|
||||
if (exp->first_opcode () == OP_VAR_VALUE)
|
||||
{
|
||||
if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
|
||||
symbol *sym;
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::var_value_operation *vvop
|
||||
= (dynamic_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
sym = vvop->get_symbol ();
|
||||
}
|
||||
else
|
||||
sym = exp->elts[2].symbol;
|
||||
|
||||
if (SYMBOL_CLASS (sym) == LOC_CONST)
|
||||
{
|
||||
error (_("constant `%s' (value %s) "
|
||||
"will not be collected."),
|
||||
exp->elts[2].symbol->print_name (),
|
||||
plongest (SYMBOL_VALUE (exp->elts[2].symbol)));
|
||||
sym->print_name (),
|
||||
plongest (SYMBOL_VALUE (sym)));
|
||||
}
|
||||
else if (SYMBOL_CLASS (exp->elts[2].symbol)
|
||||
== LOC_OPTIMIZED_OUT)
|
||||
else if (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT)
|
||||
{
|
||||
error (_("`%s' is optimized away "
|
||||
"and cannot be collected."),
|
||||
exp->elts[2].symbol->print_name ());
|
||||
sym->print_name ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1384,7 +1395,16 @@ encode_actions_1 (struct command_line *action,
|
||||
{
|
||||
case OP_REGISTER:
|
||||
{
|
||||
const char *name = &exp->elts[2].string;
|
||||
const char *name;
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::register_operation *regop
|
||||
= (dynamic_cast<expr::register_operation *>
|
||||
(exp->op.get ()));
|
||||
name = regop->get_name ();
|
||||
}
|
||||
else
|
||||
name = &exp->elts[2].string;
|
||||
|
||||
i = user_reg_map_name_to_regnum (target_gdbarch (),
|
||||
name, strlen (name));
|
||||
@ -1400,25 +1420,47 @@ encode_actions_1 (struct command_line *action,
|
||||
}
|
||||
|
||||
case UNOP_MEMVAL:
|
||||
/* Safe because we know it's a simple expression. */
|
||||
tempval = evaluate_expression (exp.get ());
|
||||
addr = value_address (tempval);
|
||||
/* Initialize the TYPE_LENGTH if it is a typedef. */
|
||||
check_typedef (exp->elts[1].type);
|
||||
collect->add_memrange (target_gdbarch (),
|
||||
memrange_absolute, addr,
|
||||
TYPE_LENGTH (exp->elts[1].type),
|
||||
tloc->address);
|
||||
collect->append_exp (std::string (exp_start,
|
||||
action_exp));
|
||||
{
|
||||
/* Safe because we know it's a simple expression. */
|
||||
tempval = evaluate_expression (exp.get ());
|
||||
addr = value_address (tempval);
|
||||
struct type *type;
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::unop_memval_operation *memop
|
||||
= (dynamic_cast<expr::unop_memval_operation *>
|
||||
(exp->op.get ()));
|
||||
type = memop->get_type ();
|
||||
}
|
||||
else
|
||||
type = exp->elts[1].type;
|
||||
/* Initialize the TYPE_LENGTH if it is a typedef. */
|
||||
check_typedef (type);
|
||||
collect->add_memrange (target_gdbarch (),
|
||||
memrange_absolute, addr,
|
||||
TYPE_LENGTH (type),
|
||||
tloc->address);
|
||||
collect->append_exp (std::string (exp_start,
|
||||
action_exp));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_VAR_VALUE:
|
||||
{
|
||||
struct symbol *sym = exp->elts[2].symbol;
|
||||
struct symbol *sym;
|
||||
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::var_value_operation *vvo
|
||||
= (dynamic_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
sym = vvo->get_symbol ();
|
||||
}
|
||||
else
|
||||
sym = exp->elts[2].symbol;
|
||||
const char *name = sym->natural_name ();
|
||||
|
||||
collect->collect_symbol (exp->elts[2].symbol,
|
||||
collect->collect_symbol (sym,
|
||||
target_gdbarch (),
|
||||
frame_reg,
|
||||
frame_offset,
|
||||
|
28
gdb/value.c
28
gdb/value.c
@ -44,6 +44,7 @@
|
||||
#include "gdbsupport/selftest.h"
|
||||
#include "gdbsupport/array-view.h"
|
||||
#include "cli/cli-style.h"
|
||||
#include "expop.h"
|
||||
|
||||
/* Definition of a user function. */
|
||||
struct internal_function
|
||||
@ -2006,7 +2007,7 @@ static struct internalvar *internalvars;
|
||||
static void
|
||||
init_if_undefined_command (const char* args, int from_tty)
|
||||
{
|
||||
struct internalvar* intvar;
|
||||
struct internalvar *intvar = nullptr;
|
||||
|
||||
/* Parse the expression - this is taken from set_command(). */
|
||||
expression_up expr = parse_expression (args);
|
||||
@ -2014,15 +2015,34 @@ init_if_undefined_command (const char* args, int from_tty)
|
||||
/* Validate the expression.
|
||||
Was the expression an assignment?
|
||||
Or even an expression at all? */
|
||||
if (expr->nelts == 0 || expr->first_opcode () != BINOP_ASSIGN)
|
||||
if ((expr->nelts == 0 && expr->op == nullptr)
|
||||
|| expr->first_opcode () != BINOP_ASSIGN)
|
||||
error (_("Init-if-undefined requires an assignment expression."));
|
||||
|
||||
/* Extract the variable from the parsed expression.
|
||||
In the case of an assign the lvalue will be in elts[1] and elts[2]. */
|
||||
if (expr->elts[1].opcode != OP_INTERNALVAR)
|
||||
if (expr->op == nullptr)
|
||||
{
|
||||
if (expr->elts[1].opcode == OP_INTERNALVAR)
|
||||
intvar = expr->elts[2].internalvar;
|
||||
}
|
||||
else
|
||||
{
|
||||
expr::assign_operation *assign
|
||||
= dynamic_cast<expr::assign_operation *> (expr->op.get ());
|
||||
if (assign != nullptr)
|
||||
{
|
||||
expr::operation *lhs = assign->get_lhs ();
|
||||
expr::internalvar_operation *ivarop
|
||||
= dynamic_cast<expr::internalvar_operation *> (lhs);
|
||||
if (ivarop != nullptr)
|
||||
intvar = ivarop->get_internalvar ();
|
||||
}
|
||||
}
|
||||
|
||||
if (intvar == nullptr)
|
||||
error (_("The first parameter to init-if-undefined "
|
||||
"should be a GDB variable."));
|
||||
intvar = expr->elts[2].internalvar;
|
||||
|
||||
/* Only evaluate the expression if the lvalue is void.
|
||||
This may still fail if the expression is invalid. */
|
||||
|
@ -930,7 +930,9 @@ extern value *evaluate_var_msym_value (enum noside noside,
|
||||
|
||||
extern value *eval_skip_value (expression *exp);
|
||||
|
||||
namespace expr { class operation; };
|
||||
extern void fetch_subexp_value (struct expression *exp, int *pc,
|
||||
expr::operation *op,
|
||||
struct value **valp, struct value **resultp,
|
||||
std::vector<value_ref_ptr> *val_chain,
|
||||
bool preserve_errors);
|
||||
|
Loading…
Reference in New Issue
Block a user