aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog34
-rw-r--r--gdb/ada-exp.h3
-rw-r--r--gdb/ax-gdb.c19
-rw-r--r--gdb/breakpoint.c13
-rw-r--r--gdb/dtrace-probe.c9
-rw-r--r--gdb/eval.c30
-rw-r--r--gdb/expop.h49
-rw-r--r--gdb/expprint.c16
-rw-r--r--gdb/expression.h5
-rw-r--r--gdb/parse.c23
-rw-r--r--gdb/parser-defs.h7
-rw-r--r--gdb/ppc-linux-nat.c20
-rw-r--r--gdb/printcmd.c10
-rw-r--r--gdb/stap-probe.c5
-rw-r--r--gdb/tracepoint.c82
-rw-r--r--gdb/value.c28
-rw-r--r--gdb/value.h2
17 files changed, 298 insertions, 57 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fe4f560..5fd0967 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,39 @@
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.
2021-03-08 Tom Tromey <tom@tromey.com>
diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h
index ab910e8..1ae0cbc 100644
--- a/gdb/ada-exp.h
+++ b/gdb/ada-exp.h
@@ -351,9 +351,6 @@ public:
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); }
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 8ec3dd7..d2f50bb 100644
--- a/gdb/ax-gdb.c
+++ b/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);
}
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e9aba79..aa2abce 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -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)
{
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
index 6c01f87..f4b6bec 100644
--- a/gdb/dtrace-probe.c
+++ b/gdb/dtrace-probe.c
@@ -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;
diff --git a/gdb/eval.c b/gdb/eval.c
index f1302ef..142d4ae 100644
--- a/gdb/eval.c
+++ b/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;
}
diff --git a/gdb/expop.h b/gdb/expop.h
index 9a9c6bc..a719b0d 100644
--- a/gdb/expop.h
+++ b/gdb/expop.h
@@ -654,6 +654,12 @@ public:
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 @@ public:
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 @@ public:
}
};
-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 @@ public:
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 @@ public:
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 @@ public:
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,
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 92a3ab8..6c65ec0 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -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,
diff --git a/gdb/expression.h b/gdb/expression.h
index d20857b..3abaf6e 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -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;
};
diff --git a/gdb/parse.c b/gdb/parse.c
index 884a008..68386f1 100644
--- a/gdb/parse.c
+++ b/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);
}
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 466230e..a9ae198 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -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;
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 4da15f9..72f0283 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -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)
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 58e39c7..235f2de 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -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:
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index bbdfbcd..476cbec 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -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;
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 0cbd2c6..101c526 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -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,
diff --git a/gdb/value.c b/gdb/value.c
index bddf9a4..89b612e 100644
--- a/gdb/value.c
+++ b/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. */
diff --git a/gdb/value.h b/gdb/value.h
index 60a831c..7f72938 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -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);