diff options
-rw-r--r-- | gdb/ChangeLog | 34 | ||||
-rw-r--r-- | gdb/ada-exp.h | 3 | ||||
-rw-r--r-- | gdb/ax-gdb.c | 19 | ||||
-rw-r--r-- | gdb/breakpoint.c | 13 | ||||
-rw-r--r-- | gdb/dtrace-probe.c | 9 | ||||
-rw-r--r-- | gdb/eval.c | 30 | ||||
-rw-r--r-- | gdb/expop.h | 49 | ||||
-rw-r--r-- | gdb/expprint.c | 16 | ||||
-rw-r--r-- | gdb/expression.h | 5 | ||||
-rw-r--r-- | gdb/parse.c | 23 | ||||
-rw-r--r-- | gdb/parser-defs.h | 7 | ||||
-rw-r--r-- | gdb/ppc-linux-nat.c | 20 | ||||
-rw-r--r-- | gdb/printcmd.c | 10 | ||||
-rw-r--r-- | gdb/stap-probe.c | 5 | ||||
-rw-r--r-- | gdb/tracepoint.c | 82 | ||||
-rw-r--r-- | gdb/value.c | 28 | ||||
-rw-r--r-- | gdb/value.h | 2 |
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; @@ -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); |