+2021-03-08 Tom Tromey <tom@tromey.com>
+
+ * value.h (evaluate_subexp_with_coercion): Don't declare.
+ * parse.c (exp_descriptor_standard): Remove.
+ (expr_builder::expr_builder, expr_builder::release): Update.
+ (expression::expression): Remove size_t parameter.
+ (expression::~expression): Simplify.
+ (expression::resize): Remove.
+ (write_exp_elt, write_exp_elt_opcode, write_exp_elt_sym)
+ (write_exp_elt_msym, write_exp_elt_block, write_exp_elt_objfile)
+ (write_exp_elt_longcst, write_exp_elt_floatcst)
+ (write_exp_elt_type, write_exp_elt_intern, write_exp_string)
+ (write_exp_string_vector, write_exp_bitstring): Remove.
+ * p-lang.h (class pascal_language) <opcode_print_table,
+ op_print_tab>: Remove.
+ * p-lang.c (pascal_language::op_print_tab): Remove.
+ * opencl-lang.c (class opencl_language) <opcode_print_table>:
+ Remove.
+ * objc-lang.c (objc_op_print_tab): Remove.
+ (class objc_language) <opcode_print_table>: Remove.
+ * m2-lang.h (class m2_language) <opcode_print_table,
+ op_print_tab>: Remove.
+ * m2-lang.c (m2_language::op_print_tab): Remove.
+ * language.h (struct language_defn) <post_parser, expression_ops,
+ opcode_print_table>: Remove.
+ * language.c (language_defn::expression_ops)
+ (auto_or_unknown_language::opcode_print_table): Remove.
+ * go-lang.h (class go_language) <opcode_print_table,
+ op_print_tab>: Remove.
+ * go-lang.c (go_language::op_print_tab): Remove.
+ * f-lang.h (class f_language) <opcode_print_table>: Remove
+ <op_print_tab>: Remove.
+ * f-lang.c (f_language::op_print_tab): Remove.
+ * expression.h (union exp_element): Remove.
+ (struct expression): Remove size_t parameter from constructor.
+ <resize>: Remove.
+ <first_opcode>: Update.
+ <nelts, elts>: Remove.
+ (EXP_ELEM_TO_BYTES, BYTES_TO_EXP_ELEM): Remove.
+ (evaluate_subexp_standard, print_expression, op_string)
+ (dump_raw_expression): Don't declare.
+ * expprint.c (print_expression, print_subexp)
+ (print_subexp_funcall, print_subexp_standard, op_string)
+ (dump_raw_expression, dump_subexp, dump_subexp_body)
+ (dump_subexp_body_funcall, dump_subexp_body_standard): Remove.
+ (dump_prefix_expression): Update.
+ * eval.c (evaluate_subexp): Remove.
+ (evaluate_expression, evaluate_type): Update.
+ (evaluate_subexpression_type): Remove.
+ (fetch_subexp_value): Remove "pc" parameter. Update.
+ (extract_field_op, evaluate_struct_tuple, evaluate_funcall)
+ (evaluate_subexp_standard, evaluate_subexp_for_address)
+ (evaluate_subexp_with_coercion, evaluate_subexp_for_sizeof)
+ (evaluate_subexp_for_cast): Remove.
+ (parse_and_eval_type): Update.
+ * dtrace-probe.c (dtrace_probe::compile_to_ax): Update.
+ * d-lang.c (d_op_print_tab): Remove.
+ (class d_language) <opcode_print_table>: Remove.
+ * c-lang.h (c_op_print_tab): Don't declare.
+ * c-lang.c (c_op_print_tab): Remove.
+ (class c_language, class cplus_language, class asm_language, class
+ minimal_language) <opcode_print_table>: Remove.
+ * breakpoint.c (update_watchpoint, watchpoint_check)
+ (watchpoint_exp_is_const, watch_command_1): Update.
+ * ax-gdb.h (union exp_element): Don't declare.
+ * ax-gdb.c (const_var_ref, const_expr, maybe_const_expr)
+ (gen_repeat, gen_sizeof, gen_expr_for_cast, gen_expr)
+ (gen_expr_binop_rest): Remove.
+ (gen_trace_for_expr, gen_eval_for_expr, gen_printf): Update.
+ * ada-lang.c (ada_op_print_tab): Remove.
+ (class ada_language) <post_parser, opcode_print_table>: Remove.
+
2021-03-08 Tom Tromey <tom@tromey.com>
* go-lang.c (go_language::expression_ops): Don't declare.
printf_filtered ("%s: %s\n", info.name, paddress (gdbarch, info.addr));
}
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-
-static const struct op_print ada_op_print_tab[] = {
- {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"or else", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"and then", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"or", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"xor", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"and", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"=", BINOP_EQUAL, PREC_EQUAL, 0},
- {"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {">>", BINOP_RSH, PREC_SHIFT, 0},
- {"<<", BINOP_LSH, PREC_SHIFT, 0},
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"&", BINOP_CONCAT, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"rem", BINOP_REM, PREC_MUL, 0},
- {"mod", BINOP_MOD, PREC_MUL, 0},
- {"**", BINOP_EXP, PREC_REPEAT, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"+", UNOP_PLUS, PREC_PREFIX, 0},
- {"not ", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"not ", UNOP_COMPLEMENT, PREC_PREFIX, 0},
- {"abs ", UNOP_ABS, PREC_PREFIX, 0},
- {".all", UNOP_IND, PREC_SUFFIX, 1},
- {"'access", UNOP_ADDR, PREC_SUFFIX, 1},
- {"'size", OP_ATR_SIZE, PREC_SUFFIX, 1},
- {NULL, OP_NULL, PREC_SUFFIX, 0}
-};
\f
/* Language vector */
return ada_parse (ps);
}
- /* See language.h.
-
- Same as evaluate_type (*EXP), but resolves ambiguous symbol references
- (marked by OP_VAR_VALUE nodes in which the symbol has an undefined
- namespace) and converts operators that are user-defined into
- appropriate function calls. If CONTEXT_TYPE is non-null, it provides
- a preferred result type [at the moment, only type void has any
- effect---causing procedures to be preferred over functions in calls].
- A null CONTEXT_TYPE indicates that a non-void return type is
- preferred. May change (expand) *EXP. */
-
- void post_parser (expression_up *expp, struct parser_state *ps)
- const override
- {
- }
-
/* See language.h. */
void emitchar (int ch, struct type *chtype,
const struct lang_varobj_ops *varobj_ops () const override
{ return &ada_varobj_ops; }
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return ada_op_print_tab; }
-
protected:
/* See language.h. */
/* Prototypes for local functions. */
/* There's a standard order to the arguments of these functions:
- union exp_element ** --- pointer into expression
struct agent_expr * --- agent expression buffer to generate code into
struct axs_value * --- describes value left on top of stack */
-static struct value *const_var_ref (struct symbol *var);
-static struct value *const_expr (union exp_element **pc);
-static struct value *maybe_const_expr (union exp_element **pc);
-
static void gen_traced_pop (struct agent_expr *, struct axs_value *);
static void gen_sign_extend (struct agent_expr *, struct type *);
const char *operand_name);
static void gen_static_field (struct agent_expr *ax, struct axs_value *value,
struct type *type, int fieldno);
-static void gen_repeat (struct expression *exp, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value);
-static void gen_sizeof (struct expression *exp, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value,
- struct type *size_type);
-static void gen_expr_binop_rest (struct expression *exp,
- enum exp_opcode op, union exp_element **pc,
- struct agent_expr *ax,
- struct axs_value *value,
- struct axs_value *value1,
- struct axs_value *value2);
static void gen_expr_binop_rest (struct expression *exp,
enum exp_opcode op,
struct agent_expr *ax,
struct axs_value *value,
struct axs_value *value1,
struct axs_value *value2);
-\f
-
-/* Detecting constant expressions. */
-
-/* If the variable reference at *PC is a constant, return its value.
- Otherwise, return zero.
-
- Hey, Wally! How can a variable reference be a constant?
-
- Well, Beav, this function really handles the OP_VAR_VALUE operator,
- not specifically variable references. GDB uses OP_VAR_VALUE to
- refer to any kind of symbolic reference: function names, enum
- elements, and goto labels are all handled through the OP_VAR_VALUE
- operator, even though they're constants. It makes sense given the
- situation.
-
- Gee, Wally, don'cha wonder sometimes if data representations that
- subvert commonly accepted definitions of terms in favor of heavily
- context-specific interpretations are really just a tool of the
- programming hegemony to preserve their power and exclude the
- proletariat? */
-
-static struct value *
-const_var_ref (struct symbol *var)
-{
- struct type *type = SYMBOL_TYPE (var);
-
- switch (SYMBOL_CLASS (var))
- {
- case LOC_CONST:
- return value_from_longest (type, (LONGEST) SYMBOL_VALUE (var));
-
- case LOC_LABEL:
- return value_from_pointer (type, (CORE_ADDR) SYMBOL_VALUE_ADDRESS (var));
-
- default:
- return 0;
- }
-}
-
-
-/* If the expression starting at *PC has a constant value, return it.
- Otherwise, return zero. If we return a value, then *PC will be
- advanced to the end of it. If we return zero, *PC could be
- anywhere. */
-static struct value *
-const_expr (union exp_element **pc)
-{
- enum exp_opcode op = (*pc)->opcode;
- struct value *v1;
-
- switch (op)
- {
- case OP_LONG:
- {
- struct type *type = (*pc)[1].type;
- LONGEST k = (*pc)[2].longconst;
-
- (*pc) += 4;
- return value_from_longest (type, k);
- }
-
- case OP_VAR_VALUE:
- {
- struct value *v = const_var_ref ((*pc)[2].symbol);
-
- (*pc) += 4;
- return v;
- }
-
- /* We could add more operators in here. */
-
- case UNOP_NEG:
- (*pc)++;
- v1 = const_expr (pc);
- if (v1)
- return value_neg (v1);
- else
- return 0;
-
- default:
- return 0;
- }
-}
-
-/* Like const_expr, but guarantee also that *PC is undisturbed if the
- expression is not constant. */
-static struct value *
-maybe_const_expr (union exp_element **pc)
-{
- union exp_element *tentative_pc = *pc;
- struct value *v = const_expr (&tentative_pc);
-
- /* If we got a value, then update the real PC. */
- if (v)
- *pc = tentative_pc;
-
- return v;
-}
\f
/* Generating bytecode from GDB expressions: general assumptions */
return 0;
}
-/* Generate code for GDB's magical `repeat' operator.
- LVALUE @ INT creates an array INT elements long, and whose elements
- have the same type as LVALUE, located in memory so that LVALUE is
- its first element. For example, argv[0]@argc gives you the array
- of command-line arguments.
-
- Unfortunately, because we have to know the types before we actually
- have a value for the expression, we can't implement this perfectly
- without changing the type system, having values that occupy two
- stack slots, doing weird things with sizeof, etc. So we require
- the right operand to be a constant expression. */
-static void
-gen_repeat (struct expression *exp, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value)
-{
- struct axs_value value1;
-
- /* We don't want to turn this into an rvalue, so no conversions
- here. */
- gen_expr (exp, pc, ax, &value1);
- if (value1.kind != axs_lvalue_memory)
- error (_("Left operand of `@' must be an object in memory."));
-
- /* Evaluate the length; it had better be a constant. */
- {
- struct value *v = const_expr (pc);
- int length;
-
- if (!v)
- error (_("Right operand of `@' must be a "
- "constant, in agent expressions."));
- if (value_type (v)->code () != TYPE_CODE_INT)
- error (_("Right operand of `@' must be an integer."));
- length = value_as_long (v);
- if (length <= 0)
- error (_("Right operand of `@' must be positive."));
-
- /* The top of the stack is already the address of the object, so
- all we need to do is frob the type of the lvalue. */
- {
- /* FIXME-type-allocation: need a way to free this type when we are
- done with it. */
- struct type *array
- = lookup_array_range_type (value1.type, 0, length - 1);
-
- value->kind = axs_lvalue_memory;
- value->type = array;
- }
- }
-}
-
-
-/* Emit code for the `sizeof' operator.
- *PC should point at the start of the operand expression; we advance it
- to the first instruction after the operand. */
-static void
-gen_sizeof (struct expression *exp, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value,
- struct type *size_type)
-{
- /* We don't care about the value of the operand expression; we only
- care about its type. However, in the current arrangement, the
- only way to find an expression's type is to generate code for it.
- So we generate code for the operand, and then throw it away,
- replacing it with code that simply pushes its size. */
- int start = ax->len;
-
- gen_expr (exp, pc, ax, value);
-
- /* Throw away the code we just generated. */
- ax->len = start;
-
- ax_const_l (ax, TYPE_LENGTH (value->type));
- value->kind = axs_rvalue;
- value->type = size_type;
-}
\f
-/* Generate bytecode for a cast to TO_TYPE. Advance *PC over the
- subexpression. */
-
-static void
-gen_expr_for_cast (struct expression *exp, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value,
- struct type *to_type)
-{
- enum exp_opcode op = (*pc)[0].opcode;
-
- /* Don't let symbols be handled with gen_expr because that throws an
- "unknown type" error for no-debug data symbols. Instead, we want
- the cast to reinterpret such symbols. */
- if (op == OP_VAR_MSYM_VALUE || op == OP_VAR_VALUE)
- {
- if (op == OP_VAR_VALUE)
- {
- gen_var_ref (ax, value, (*pc)[2].symbol);
-
- if (value->optimized_out)
- error (_("`%s' has been optimized out, cannot use"),
- (*pc)[2].symbol->print_name ());
- }
- else
- gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile);
- if (value->type->code () == TYPE_CODE_ERROR)
- value->type = to_type;
- (*pc) += 4;
- }
- else
- gen_expr (exp, pc, ax, value);
- gen_cast (ax, value, to_type);
-}
-
-/* Generating bytecode from GDB expressions: general recursive thingy */
-
-/* XXX: i18n */
-/* A gen_expr function written by a Gen-X'er guy.
- Append code for the subexpression of EXPR starting at *POS_P to AX. */
-void
-gen_expr (struct expression *exp, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value)
-{
- /* Used to hold the descriptions of operand expressions. */
- struct axs_value value1, value2, value3;
- enum exp_opcode op = (*pc)[0].opcode, op2;
- int if1, go1, if2, go2, end;
- struct type *int_type = builtin_type (ax->gdbarch)->builtin_int;
-
- /* If we're looking at a constant expression, just push its value. */
- {
- struct value *v = maybe_const_expr (pc);
-
- if (v)
- {
- ax_const_l (ax, value_as_long (v));
- value->kind = axs_rvalue;
- value->type = check_typedef (value_type (v));
- return;
- }
- }
-
- /* Otherwise, go ahead and generate code for it. */
- switch (op)
- {
- /* Binary arithmetic operators. */
- case BINOP_ADD:
- case BINOP_SUB:
- case BINOP_MUL:
- case BINOP_DIV:
- case BINOP_REM:
- case BINOP_LSH:
- case BINOP_RSH:
- case BINOP_SUBSCRIPT:
- case BINOP_BITWISE_AND:
- case BINOP_BITWISE_IOR:
- case BINOP_BITWISE_XOR:
- case BINOP_EQUAL:
- case BINOP_NOTEQUAL:
- case BINOP_LESS:
- case BINOP_GTR:
- case BINOP_LEQ:
- case BINOP_GEQ:
- (*pc)++;
- gen_expr (exp, pc, ax, &value1);
- gen_usual_unary (ax, &value1);
- gen_expr_binop_rest (exp, op, pc, ax, value, &value1, &value2);
- break;
-
- case BINOP_LOGICAL_AND:
- (*pc)++;
- /* Generate the obvious sequence of tests and jumps. */
- gen_expr (exp, pc, ax, &value1);
- gen_usual_unary (ax, &value1);
- if1 = ax_goto (ax, aop_if_goto);
- go1 = ax_goto (ax, aop_goto);
- ax_label (ax, if1, ax->len);
- gen_expr (exp, pc, ax, &value2);
- gen_usual_unary (ax, &value2);
- if2 = ax_goto (ax, aop_if_goto);
- go2 = ax_goto (ax, aop_goto);
- ax_label (ax, if2, ax->len);
- ax_const_l (ax, 1);
- end = ax_goto (ax, aop_goto);
- ax_label (ax, go1, ax->len);
- ax_label (ax, go2, ax->len);
- ax_const_l (ax, 0);
- ax_label (ax, end, ax->len);
- value->kind = axs_rvalue;
- value->type = int_type;
- break;
-
- case BINOP_LOGICAL_OR:
- (*pc)++;
- /* Generate the obvious sequence of tests and jumps. */
- gen_expr (exp, pc, ax, &value1);
- gen_usual_unary (ax, &value1);
- if1 = ax_goto (ax, aop_if_goto);
- gen_expr (exp, pc, ax, &value2);
- gen_usual_unary (ax, &value2);
- if2 = ax_goto (ax, aop_if_goto);
- ax_const_l (ax, 0);
- end = ax_goto (ax, aop_goto);
- ax_label (ax, if1, ax->len);
- ax_label (ax, if2, ax->len);
- ax_const_l (ax, 1);
- ax_label (ax, end, ax->len);
- value->kind = axs_rvalue;
- value->type = int_type;
- break;
-
- case TERNOP_COND:
- (*pc)++;
- gen_expr (exp, pc, ax, &value1);
- gen_usual_unary (ax, &value1);
- /* For (A ? B : C), it's easiest to generate subexpression
- bytecodes in order, but if_goto jumps on true, so we invert
- the sense of A. Then we can do B by dropping through, and
- jump to do C. */
- gen_logical_not (ax, &value1, int_type);
- if1 = ax_goto (ax, aop_if_goto);
- gen_expr (exp, pc, ax, &value2);
- gen_usual_unary (ax, &value2);
- end = ax_goto (ax, aop_goto);
- ax_label (ax, if1, ax->len);
- gen_expr (exp, pc, ax, &value3);
- gen_usual_unary (ax, &value3);
- ax_label (ax, end, ax->len);
- /* This is arbitrary - what if B and C are incompatible types? */
- value->type = value2.type;
- value->kind = value2.kind;
- break;
-
- case BINOP_ASSIGN:
- (*pc)++;
- if ((*pc)[0].opcode == OP_INTERNALVAR)
- {
- const char *name = internalvar_name ((*pc)[1].internalvar);
- struct trace_state_variable *tsv;
-
- (*pc) += 3;
- gen_expr (exp, pc, ax, value);
- tsv = find_trace_state_variable (name);
- if (tsv)
- {
- ax_tsv (ax, aop_setv, tsv->number);
- if (ax->tracing)
- ax_tsv (ax, aop_tracev, tsv->number);
- }
- else
- error (_("$%s is not a trace state variable, "
- "may not assign to it"), name);
- }
- else
- error (_("May only assign to trace state variables"));
- break;
-
- case BINOP_ASSIGN_MODIFY:
- (*pc)++;
- op2 = (*pc)[0].opcode;
- (*pc)++;
- (*pc)++;
- if ((*pc)[0].opcode == OP_INTERNALVAR)
- {
- const char *name = internalvar_name ((*pc)[1].internalvar);
- struct trace_state_variable *tsv;
-
- (*pc) += 3;
- tsv = find_trace_state_variable (name);
- if (tsv)
- {
- /* The tsv will be the left half of the binary operation. */
- ax_tsv (ax, aop_getv, tsv->number);
- if (ax->tracing)
- ax_tsv (ax, aop_tracev, tsv->number);
- /* Trace state variables are always 64-bit integers. */
- value1.kind = axs_rvalue;
- value1.type = builtin_type (ax->gdbarch)->builtin_long_long;
- /* Now do right half of expression. */
- gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
- /* We have a result of the binary op, set the tsv. */
- ax_tsv (ax, aop_setv, tsv->number);
- if (ax->tracing)
- ax_tsv (ax, aop_tracev, tsv->number);
- }
- else
- error (_("$%s is not a trace state variable, "
- "may not assign to it"), name);
- }
- else
- error (_("May only assign to trace state variables"));
- break;
-
- /* Note that we need to be a little subtle about generating code
- for comma. In C, we can do some optimizations here because
- we know the left operand is only being evaluated for effect.
- However, if the tracing kludge is in effect, then we always
- need to evaluate the left hand side fully, so that all the
- variables it mentions get traced. */
- case BINOP_COMMA:
- (*pc)++;
- gen_expr (exp, pc, ax, &value1);
- /* Don't just dispose of the left operand. We might be tracing,
- in which case we want to emit code to trace it if it's an
- lvalue. */
- gen_traced_pop (ax, &value1);
- gen_expr (exp, pc, ax, value);
- /* It's the consumer's responsibility to trace the right operand. */
- break;
-
- case OP_LONG: /* some integer constant */
- {
- struct type *type = (*pc)[1].type;
- LONGEST k = (*pc)[2].longconst;
-
- (*pc) += 4;
- gen_int_literal (ax, value, k, type);
- }
- break;
-
- case OP_VAR_VALUE:
- gen_var_ref (ax, value, (*pc)[2].symbol);
-
- if (value->optimized_out)
- error (_("`%s' has been optimized out, cannot use"),
- (*pc)[2].symbol->print_name ());
-
- if (value->type->code () == TYPE_CODE_ERROR)
- error_unknown_type ((*pc)[2].symbol->print_name ());
-
- (*pc) += 4;
- break;
-
- case OP_VAR_MSYM_VALUE:
- gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile);
-
- if (value->type->code () == TYPE_CODE_ERROR)
- error_unknown_type ((*pc)[2].msymbol->linkage_name ());
-
- (*pc) += 4;
- break;
-
- case OP_REGISTER:
- {
- const char *name = &(*pc)[2].string;
- int reg;
-
- (*pc) += 4 + BYTES_TO_EXP_ELEM ((*pc)[1].longconst + 1);
- reg = user_reg_map_name_to_regnum (ax->gdbarch, name, strlen (name));
- if (reg == -1)
- internal_error (__FILE__, __LINE__,
- _("Register $%s not available"), name);
- /* No support for tracing user registers yet. */
- if (reg >= gdbarch_num_cooked_regs (ax->gdbarch))
- error (_("'%s' is a user-register; "
- "GDB cannot yet trace user-register contents."),
- name);
- value->kind = axs_lvalue_register;
- value->u.reg = reg;
- value->type = register_type (ax->gdbarch, reg);
- }
- break;
-
- case OP_INTERNALVAR:
- {
- struct internalvar *var = (*pc)[1].internalvar;
- const char *name = internalvar_name (var);
- struct trace_state_variable *tsv;
-
- (*pc) += 3;
- tsv = find_trace_state_variable (name);
- if (tsv)
- {
- ax_tsv (ax, aop_getv, tsv->number);
- if (ax->tracing)
- ax_tsv (ax, aop_tracev, tsv->number);
- /* Trace state variables are always 64-bit integers. */
- value->kind = axs_rvalue;
- value->type = builtin_type (ax->gdbarch)->builtin_long_long;
- }
- else if (! compile_internalvar_to_ax (var, ax, value))
- error (_("$%s is not a trace state variable; GDB agent "
- "expressions cannot use convenience variables."), name);
- }
- break;
-
- /* Weirdo operator: see comments for gen_repeat for details. */
- case BINOP_REPEAT:
- /* Note that gen_repeat handles its own argument evaluation. */
- (*pc)++;
- gen_repeat (exp, pc, ax, value);
- break;
-
- case UNOP_CAST:
- {
- struct type *type = (*pc)[1].type;
-
- (*pc) += 3;
- gen_expr_for_cast (exp, pc, ax, value, type);
- }
- break;
-
- case UNOP_CAST_TYPE:
- {
- int offset;
- struct value *val;
- struct type *type;
-
- ++*pc;
- offset = *pc - exp->elts;
- val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (val);
- *pc = &exp->elts[offset];
- gen_expr_for_cast (exp, pc, ax, value, type);
- }
- break;
-
- case UNOP_MEMVAL:
- {
- struct type *type = check_typedef ((*pc)[1].type);
-
- (*pc) += 3;
- gen_expr (exp, pc, ax, value);
-
- /* If we have an axs_rvalue or an axs_lvalue_memory, then we
- already have the right value on the stack. For
- axs_lvalue_register, we must convert. */
- if (value->kind == axs_lvalue_register)
- require_rvalue (ax, value);
-
- value->type = type;
- value->kind = axs_lvalue_memory;
- }
- break;
-
- case UNOP_MEMVAL_TYPE:
- {
- int offset;
- struct value *val;
- struct type *type;
-
- ++*pc;
- offset = *pc - exp->elts;
- val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (val);
- *pc = &exp->elts[offset];
-
- gen_expr (exp, pc, ax, value);
-
- /* If we have an axs_rvalue or an axs_lvalue_memory, then we
- already have the right value on the stack. For
- axs_lvalue_register, we must convert. */
- if (value->kind == axs_lvalue_register)
- require_rvalue (ax, value);
-
- value->type = type;
- value->kind = axs_lvalue_memory;
- }
- break;
-
- case UNOP_PLUS:
- (*pc)++;
- /* + FOO is equivalent to 0 + FOO, which can be optimized. */
- gen_expr (exp, pc, ax, value);
- gen_usual_unary (ax, value);
- break;
-
- case UNOP_NEG:
- (*pc)++;
- /* -FOO is equivalent to 0 - FOO. */
- gen_int_literal (ax, &value1, 0,
- builtin_type (ax->gdbarch)->builtin_int);
- gen_usual_unary (ax, &value1); /* shouldn't do much */
- gen_expr (exp, pc, ax, &value2);
- gen_usual_unary (ax, &value2);
- gen_usual_arithmetic (ax, &value1, &value2);
- gen_binop (ax, value, &value1, &value2, aop_sub, aop_sub, 1, "negation");
- break;
-
- case UNOP_LOGICAL_NOT:
- (*pc)++;
- gen_expr (exp, pc, ax, value);
- gen_usual_unary (ax, value);
- gen_logical_not (ax, value, int_type);
- break;
-
- case UNOP_COMPLEMENT:
- (*pc)++;
- gen_expr (exp, pc, ax, value);
- gen_usual_unary (ax, value);
- gen_integral_promotions (ax, value);
- gen_complement (ax, value);
- break;
-
- case UNOP_IND:
- (*pc)++;
- gen_expr (exp, pc, ax, value);
- gen_usual_unary (ax, value);
- if (!pointer_type (value->type))
- error (_("Argument of unary `*' is not a pointer."));
- gen_deref (value);
- break;
-
- case UNOP_ADDR:
- (*pc)++;
- gen_expr (exp, pc, ax, value);
- gen_address_of (value);
- break;
-
- case UNOP_SIZEOF:
- (*pc)++;
- /* Notice that gen_sizeof handles its own operand, unlike most
- of the other unary operator functions. This is because we
- have to throw away the code we generate. */
- gen_sizeof (exp, pc, ax, value,
- builtin_type (ax->gdbarch)->builtin_int);
- break;
-
- case STRUCTOP_STRUCT:
- case STRUCTOP_PTR:
- {
- int length = (*pc)[1].longconst;
- const char *name = &(*pc)[2].string;
-
- (*pc) += 4 + BYTES_TO_EXP_ELEM (length + 1);
- gen_expr (exp, pc, ax, value);
- if (op == STRUCTOP_STRUCT)
- gen_struct_ref (ax, value, name, ".", "structure or union");
- else if (op == STRUCTOP_PTR)
- gen_struct_ref (ax, value, name, "->",
- "pointer to a structure or union");
- else
- /* If this `if' chain doesn't handle it, then the case list
- shouldn't mention it, and we shouldn't be here. */
- internal_error (__FILE__, __LINE__,
- _("gen_expr: unhandled struct case"));
- }
- break;
-
- case OP_THIS:
- {
- struct symbol *sym, *func;
- const struct block *b;
- const struct language_defn *lang;
-
- b = block_for_pc (ax->scope);
- func = block_linkage_function (b);
- lang = language_def (func->language ());
-
- sym = lookup_language_this (lang, b).symbol;
- if (!sym)
- error (_("no `%s' found"), lang->name_of_this ());
-
- gen_var_ref (ax, value, sym);
-
- if (value->optimized_out)
- error (_("`%s' has been optimized out, cannot use"),
- sym->print_name ());
-
- (*pc) += 2;
- }
- break;
-
- case OP_SCOPE:
- {
- struct type *type = (*pc)[1].type;
- int length = longest_to_int ((*pc)[2].longconst);
- const char *name = &(*pc)[3].string;
- int found;
-
- found = gen_aggregate_elt_ref (ax, value, type, name);
- if (!found)
- error (_("There is no field named %s"), name);
- (*pc) += 5 + BYTES_TO_EXP_ELEM (length + 1);
- }
- break;
-
- case OP_TYPE:
- case OP_TYPEOF:
- case OP_DECLTYPE:
- error (_("Attempt to use a type name as an expression."));
-
- default:
- error (_("Unsupported operator %s (%d) in expression."),
- op_name (op), op);
- }
-}
-
namespace expr
{
}
}
-/* Variant of gen_expr_binop_rest that first generates the
- right-hand-side. */
-
-static void
-gen_expr_binop_rest (struct expression *exp,
- enum exp_opcode op, union exp_element **pc,
- struct agent_expr *ax, struct axs_value *value,
- struct axs_value *value1, struct axs_value *value2)
-{
- gen_expr (exp, pc, ax, value2);
- gen_expr_binop_rest (exp, op, ax, value, value1, value2);
-}
-
/* A helper function that emits a binop based on two operations. */
void
int trace_string)
{
agent_expr_up ax (new agent_expr (expr->gdbarch, scope));
- union exp_element *pc;
struct axs_value value;
- pc = expr->elts;
ax->tracing = 1;
ax->trace_string = trace_string;
value.optimized_out = 0;
- if (expr->op != nullptr)
- expr->op->generate_ax (expr, ax.get (), &value);
- else
- gen_expr (expr, &pc, ax.get (), &value);
+ expr->op->generate_ax (expr, ax.get (), &value);
/* Make sure we record the final object, and get rid of it. */
gen_traced_pop (ax.get (), &value);
gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
{
agent_expr_up ax (new agent_expr (expr->gdbarch, scope));
- union exp_element *pc;
struct axs_value value;
- pc = expr->elts;
ax->tracing = 0;
value.optimized_out = 0;
- if (expr->op != nullptr)
- expr->op->generate_ax (expr, ax.get (), &value);
- else
- gen_expr (expr, &pc, ax.get (), &value);
+ expr->op->generate_ax (expr, ax.get (), &value);
require_rvalue (ax.get (), &value);
int nargs, struct expression **exprs)
{
agent_expr_up ax (new agent_expr (gdbarch, scope));
- union exp_element *pc;
struct axs_value value;
int tem;
for (tem = nargs - 1; tem >= 0; --tem)
{
value.optimized_out = 0;
- 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);
- }
+ exprs[tem]->op->generate_ax (exprs[tem], ax.get (), &value);
require_rvalue (ax.get (), &value);
}
#include "ax.h" /* For agent_expr_up. */
struct expression;
-union exp_element;
/* Types and enums */
}
else if (within_current_scope && b->exp)
{
- int pc = 0;
std::vector<value_ref_ptr> val_chain;
struct value *v, *result;
struct program_space *frame_pspace;
- fetch_subexp_value (b->exp.get (), &pc, b->exp->op.get (), &v, &result,
+ fetch_subexp_value (b->exp.get (), b->exp->op.get (), &v, &result,
&val_chain, false);
/* Avoid setting b->val if it's already set. The meaning of
free_all_values. We can't call free_all_values because we
might be in the middle of evaluating a function call. */
- int pc = 0;
struct value *mark;
struct value *new_val;
return WP_VALUE_CHANGED;
mark = value_mark ();
- fetch_subexp_value (b->exp.get (), &pc, b->exp->op.get (), &new_val,
+ fetch_subexp_value (b->exp.get (), b->exp->op.get (), &new_val,
NULL, NULL, false);
if (b->val_bitsize != 0)
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)
- {
- int oplenp, argsp;
-
- /* We are only interested in the descriptor of each element. */
- operator_length (exp, i, &oplenp, &argsp);
- i -= oplenp;
-
- switch (exp->elts[i].opcode)
- {
- case BINOP_ADD:
- case BINOP_SUB:
- case BINOP_MUL:
- case BINOP_DIV:
- case BINOP_REM:
- case BINOP_MOD:
- case BINOP_LSH:
- case BINOP_RSH:
- case BINOP_LOGICAL_AND:
- case BINOP_LOGICAL_OR:
- case BINOP_BITWISE_AND:
- case BINOP_BITWISE_IOR:
- case BINOP_BITWISE_XOR:
- case BINOP_EQUAL:
- case BINOP_NOTEQUAL:
- case BINOP_LESS:
- case BINOP_GTR:
- case BINOP_LEQ:
- case BINOP_GEQ:
- case BINOP_REPEAT:
- case BINOP_COMMA:
- case BINOP_EXP:
- case BINOP_MIN:
- case BINOP_MAX:
- case BINOP_INTDIV:
- case BINOP_CONCAT:
- case TERNOP_COND:
- case TERNOP_SLICE:
-
- case OP_LONG:
- case OP_FLOAT:
- case OP_LAST:
- case OP_COMPLEX:
- case OP_STRING:
- case OP_ARRAY:
- case OP_TYPE:
- case OP_TYPEOF:
- case OP_DECLTYPE:
- case OP_TYPEID:
- case OP_NAME:
- case OP_OBJC_NSSTRING:
-
- case UNOP_NEG:
- case UNOP_LOGICAL_NOT:
- case UNOP_COMPLEMENT:
- case UNOP_ADDR:
- case UNOP_HIGH:
- case UNOP_CAST:
-
- case UNOP_CAST_TYPE:
- case UNOP_REINTERPRET_CAST:
- case UNOP_DYNAMIC_CAST:
- /* Unary, binary and ternary operators: We have to check
- their operands. If they are constant, then so is the
- result of that operation. For instance, if A and B are
- determined to be constants, then so is "A + B".
-
- UNOP_IND is one exception to the rule above, because the
- value of *ADDR is not necessarily a constant, even when
- ADDR is. */
- break;
-
- case OP_VAR_VALUE:
- /* Check whether the associated symbol is a constant.
-
- We use SYMBOL_CLASS rather than TYPE_CONST because it's
- possible that a buggy compiler could mark a variable as
- constant even when it is not, and TYPE_CONST would return
- true in this case, while SYMBOL_CLASS wouldn't.
-
- We also have to check for function symbols because they
- are always constant. */
- {
- struct symbol *s = exp->elts[i + 2].symbol;
-
- if (SYMBOL_CLASS (s) != LOC_BLOCK
- && SYMBOL_CLASS (s) != LOC_CONST
- && SYMBOL_CLASS (s) != LOC_CONST_BYTES)
- return false;
- break;
- }
-
- /* The default action is to return 0 because we are using
- the optimistic approach here: If we don't know something,
- then it is not a constant. */
- default:
- return false;
- }
- }
-
- return true;
+ return exp->op->constant_p ();
}
/* Watchpoint destructor. */
const char *cond_end = NULL;
enum bptype bp_type;
int thread = -1;
- int pc = 0;
/* Flag to indicate whether we are going to use masks for
the hardware watchpoint. */
bool use_mask = false;
exp_valid_block = tracker.block ();
struct value *mark = value_mark ();
struct value *val_as_value = nullptr;
- fetch_subexp_value (exp.get (), &pc, exp->op.get (), &val_as_value, &result,
- NULL, just_location);
+ fetch_subexp_value (exp.get (), exp->op.get (), &val_as_value, &result, NULL,
+ just_location);
if (val_as_value != NULL && just_location)
{
return false;
}
-\f
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-
-const struct op_print c_op_print_tab[] =
-{
- {",", BINOP_COMMA, PREC_COMMA, 0},
- {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"==", BINOP_EQUAL, PREC_EQUAL, 0},
- {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {">>", BINOP_RSH, PREC_SHIFT, 0},
- {"<<", BINOP_LSH, PREC_SHIFT, 0},
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"%", BINOP_REM, PREC_MUL, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"+", UNOP_PLUS, PREC_PREFIX, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
- {"*", UNOP_IND, PREC_PREFIX, 0},
- {"&", UNOP_ADDR, PREC_PREFIX, 0},
- {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
- {"alignof ", UNOP_ALIGNOF, PREC_PREFIX, 0},
- {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
- {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
- {NULL, OP_NULL, PREC_PREFIX, 0}
-};
\f
void
enum macro_expansion macro_expansion () const override
{ return macro_expansion_c; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return c_op_print_tab; }
};
/* Single instance of the C language class. */
const struct lang_varobj_ops *varobj_ops () const override
{ return &cplus_varobj_ops; }
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return c_op_print_tab; }
-
protected:
/* See language.h. */
enum macro_expansion macro_expansion () const override
{ return macro_expansion_c; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return c_op_print_tab; }
};
/* The single instance of the ASM language class. */
enum macro_expansion macro_expansion () const override
{ return macro_expansion_c; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return c_op_print_tab; }
};
/* The single instance of the minimal language class. */
extern void c_emit_char (int c, struct type *type,
struct ui_file *stream, int quoter);
-extern const struct op_print c_op_print_tab[];
-
/* These are in c-typeprint.c: */
extern void c_type_print_base (struct type *, struct ui_file *,
return gdb_demangle (symbol, options | DMGL_DLANG);
}
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-static const struct op_print d_op_print_tab[] =
-{
- {",", BINOP_COMMA, PREC_COMMA, 0},
- {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"==", BINOP_EQUAL, PREC_ORDER, 0},
- {"!=", BINOP_NOTEQUAL, PREC_ORDER, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {">>", BINOP_RSH, PREC_SHIFT, 0},
- {"<<", BINOP_LSH, PREC_SHIFT, 0},
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"~", BINOP_CONCAT, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"%", BINOP_REM, PREC_MUL, 0},
- {"^^", BINOP_EXP, PREC_REPEAT, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
- {"*", UNOP_IND, PREC_PREFIX, 0},
- {"&", UNOP_ADDR, PREC_PREFIX, 0},
- {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
- {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
- {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
- {NULL, OP_NULL, PREC_PREFIX, 0}
-};
-
/* Class representing the D language. */
class d_language : public language_defn
const char *name_of_this () const override
{ return "this"; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return d_op_print_tab; }
};
/* Single instance of the D language class. */
unsigned n)
{
struct dtrace_probe_arg *arg;
- union exp_element *pc;
arg = this->get_arg_by_number (n, expr->gdbarch);
-
- 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);
- }
+ arg->expr->op->generate_ax (arg->expr.get (), expr, value);
require_rvalue (expr, value);
value->type = arg->type;
#include "expop.h"
#include "c-exp.h"
-/* Prototypes for local functions. */
-
-static struct value *evaluate_subexp_for_sizeof (struct expression *, int *,
- enum noside);
-
-static struct value *evaluate_subexp_for_address (struct expression *,
- int *, enum noside);
-
-static value *evaluate_subexp_for_cast (expression *exp, int *pos,
- enum noside noside,
- struct type *type);
-
-static struct value *evaluate_struct_tuple (struct value *,
- struct expression *, int *,
- enum noside, int);
-
-struct value *
-evaluate_subexp (struct type *expect_type, struct expression *exp,
- int *pos, enum noside noside)
-{
- return ((*exp->language_defn->expression_ops ()->evaluate_exp)
- (expect_type, exp, pos, noside));
-}
\f
/* Parse the string EXP as a C expression, evaluate it,
and return the result as a number. */
&& !thread_stack_temporaries_enabled_p (inferior_thread ()))
stack_temporaries.emplace (inferior_thread ());
- 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);
- }
+ struct value *retval = op->evaluate (expect_type, this, noside);
if (stack_temporaries.has_value ()
&& value_in_thread_stack_temporaries (retval, inferior_thread ()))
return exp->evaluate (nullptr, EVAL_AVOID_SIDE_EFFECTS);
}
-/* Evaluate a subexpression, avoiding all memory references and
- getting a value whose type alone is correct. */
-
-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);
-}
-
/* Find the current value of a watchpoint on EXP. Return the value in
*VALP and *RESULTP and the chain of intermediate and final values
in *VAL_CHAIN. RESULTP and VAL_CHAIN may be NULL if the caller does
values will be left on the value chain. */
void
-fetch_subexp_value (struct expression *exp, int *pc,
+fetch_subexp_value (struct expression *exp,
expr::operation *op,
struct value **valp, struct value **resultp,
std::vector<value_ref_ptr> *val_chain,
try
{
- if (op == nullptr)
- result = evaluate_subexp (nullptr, exp, pc, EVAL_NORMAL);
- else
- result = op->evaluate (nullptr, exp, EVAL_NORMAL);
+ result = op->evaluate (nullptr, exp, EVAL_NORMAL);
}
catch (const gdb_exception &ex)
{
}
}
-/* Extract a field operation from an expression. If the subexpression
- of EXP starting at *SUBEXP is not a structure dereference
- operation, return NULL. Otherwise, return the name of the
- dereferenced field, and advance *SUBEXP to point to the
- subexpression of the left-hand-side of the dereference. This is
- used when completing field names. */
-
-const char *
-extract_field_op (struct expression *exp, int *subexp)
-{
- int tem;
- char *result;
-
- if (exp->elts[*subexp].opcode != STRUCTOP_STRUCT
- && exp->elts[*subexp].opcode != STRUCTOP_PTR)
- return NULL;
- tem = longest_to_int (exp->elts[*subexp + 1].longconst);
- result = &exp->elts[*subexp + 2].string;
- (*subexp) += 1 + 3 + BYTES_TO_EXP_ELEM (tem + 1);
- return result;
-}
-
-/* This function evaluates brace-initializers (in C/C++) for
- structure types. */
-
-static struct value *
-evaluate_struct_tuple (struct value *struct_val,
- struct expression *exp,
- int *pos, enum noside noside, int nargs)
-{
- struct type *struct_type = check_typedef (value_type (struct_val));
- struct type *field_type;
- int fieldno = -1;
-
- while (--nargs >= 0)
- {
- struct value *val = NULL;
- int bitpos, bitsize;
- bfd_byte *addr;
-
- fieldno++;
- /* Skip static fields. */
- while (fieldno < struct_type->num_fields ()
- && field_is_static (&struct_type->field (fieldno)))
- fieldno++;
- if (fieldno >= struct_type->num_fields ())
- error (_("too many initializers"));
- field_type = struct_type->field (fieldno).type ();
- if (field_type->code () == TYPE_CODE_UNION
- && TYPE_FIELD_NAME (struct_type, fieldno)[0] == '0')
- error (_("don't know which variant you want to set"));
-
- /* Here, struct_type is the type of the inner struct,
- while substruct_type is the type of the inner struct.
- These are the same for normal structures, but a variant struct
- contains anonymous union fields that contain substruct fields.
- The value fieldno is the index of the top-level (normal or
- anonymous union) field in struct_field, while the value
- subfieldno is the index of the actual real (named inner) field
- in substruct_type. */
-
- field_type = struct_type->field (fieldno).type ();
- if (val == 0)
- val = evaluate_subexp (field_type, exp, pos, noside);
-
- /* Now actually set the field in struct_val. */
-
- /* Assign val to field fieldno. */
- if (value_type (val) != field_type)
- val = value_cast (field_type, val);
-
- bitsize = TYPE_FIELD_BITSIZE (struct_type, fieldno);
- bitpos = TYPE_FIELD_BITPOS (struct_type, fieldno);
- addr = value_contents_writeable (struct_val) + bitpos / 8;
- if (bitsize)
- modify_field (struct_type, addr,
- value_as_long (val), bitpos % 8, bitsize);
- else
- memcpy (addr, value_contents (val),
- TYPE_LENGTH (value_type (val)));
-
- }
- return struct_val;
-}
-
/* Promote value ARG1 as appropriate before performing a unary operation
on this argument.
If the result is not appropriate for any particular language then it
}
}
-/* Helper for evaluating an OP_FUNCALL. */
-
-static value *
-evaluate_funcall (type *expect_type, expression *exp, int *pos,
- enum noside noside)
-{
- int tem;
- int pc2 = 0;
- value *arg1 = NULL;
- value *arg2 = NULL;
- int save_pos1;
- symbol *function = NULL;
- char *function_name = NULL;
- const char *var_func_name = NULL;
-
- int pc = (*pos);
- (*pos) += 2;
-
- exp_opcode op = exp->elts[*pos].opcode;
- int nargs = longest_to_int (exp->elts[pc].longconst);
- /* Allocate arg vector, including space for the function to be
- called in argvec[0], a potential `this', and a terminating
- NULL. */
- value **argvec = (value **) alloca (sizeof (value *) * (nargs + 3));
- if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
- {
- /* First, evaluate the structure into arg2. */
- pc2 = (*pos)++;
-
- if (op == STRUCTOP_MEMBER)
- {
- arg2 = evaluate_subexp_for_address (exp, pos, noside);
- }
- else
- {
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- }
-
- /* If the function is a virtual function, then the aggregate
- value (providing the structure) plays its part by providing
- the vtable. Otherwise, it is just along for the ride: call
- the function directly. */
-
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
-
- type *a1_type = check_typedef (value_type (arg1));
- if (noside == EVAL_SKIP)
- tem = 1; /* Set it to the right arg index so that all
- arguments can also be skipped. */
- else if (a1_type->code () == TYPE_CODE_METHODPTR)
- {
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- arg1 = value_zero (TYPE_TARGET_TYPE (a1_type), not_lval);
- else
- arg1 = cplus_method_ptr_to_value (&arg2, arg1);
-
- /* Now, say which argument to start evaluating from. */
- nargs++;
- tem = 2;
- argvec[1] = arg2;
- }
- else if (a1_type->code () == TYPE_CODE_MEMBERPTR)
- {
- struct type *type_ptr
- = lookup_pointer_type (TYPE_SELF_TYPE (a1_type));
- struct type *target_type_ptr
- = lookup_pointer_type (TYPE_TARGET_TYPE (a1_type));
-
- /* Now, convert these values to an address. */
- arg2 = value_cast (type_ptr, arg2);
-
- long mem_offset = value_as_long (arg1);
-
- arg1 = value_from_pointer (target_type_ptr,
- value_as_long (arg2) + mem_offset);
- arg1 = value_ind (arg1);
- tem = 1;
- }
- else
- error (_("Non-pointer-to-member value used in pointer-to-member "
- "construct"));
- }
- else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
- {
- /* Hair for method invocations. */
- int tem2;
-
- nargs++;
- /* First, evaluate the structure into arg2. */
- pc2 = (*pos)++;
- tem2 = longest_to_int (exp->elts[pc2 + 1].longconst);
- *pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1);
-
- if (op == STRUCTOP_STRUCT)
- {
- /* If v is a variable in a register, and the user types
- v.method (), this will produce an error, because v has no
- address.
-
- A possible way around this would be to allocate a copy of
- the variable on the stack, copy in the contents, call the
- function, and copy out the contents. I.e. convert this
- from call by reference to call by copy-return (or
- whatever it's called). However, this does not work
- because it is not the same: the method being called could
- stash a copy of the address, and then future uses through
- that address (after the method returns) would be expected
- to use the variable itself, not some copy of it. */
- arg2 = evaluate_subexp_for_address (exp, pos, noside);
- }
- else
- {
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
-
- /* Check to see if the operator '->' has been overloaded.
- If the operator has been overloaded replace arg2 with the
- value returned by the custom operator and continue
- evaluation. */
- while (unop_user_defined_p (op, arg2))
- {
- struct value *value = NULL;
- try
- {
- value = value_x_unop (arg2, op, noside);
- }
-
- catch (const gdb_exception_error &except)
- {
- if (except.error == NOT_FOUND_ERROR)
- break;
- else
- throw;
- }
-
- arg2 = value;
- }
- }
- /* Now, say which argument to start evaluating from. */
- tem = 2;
- }
- else if (op == OP_SCOPE
- && overload_resolution
- && (exp->language_defn->la_language == language_cplus))
- {
- /* Unpack it locally so we can properly handle overload
- resolution. */
- char *name;
- int local_tem;
-
- pc2 = (*pos)++;
- local_tem = longest_to_int (exp->elts[pc2 + 2].longconst);
- (*pos) += 4 + BYTES_TO_EXP_ELEM (local_tem + 1);
- struct type *type = exp->elts[pc2 + 1].type;
- name = &exp->elts[pc2 + 3].string;
-
- function = NULL;
- function_name = NULL;
- if (type->code () == TYPE_CODE_NAMESPACE)
- {
- function = cp_lookup_symbol_namespace (type->name (),
- name,
- get_selected_block (0),
- VAR_DOMAIN).symbol;
- if (function == NULL)
- error (_("No symbol \"%s\" in namespace \"%s\"."),
- name, type->name ());
-
- tem = 1;
- /* arg2 is left as NULL on purpose. */
- }
- else
- {
- gdb_assert (type->code () == TYPE_CODE_STRUCT
- || type->code () == TYPE_CODE_UNION);
- function_name = name;
-
- /* We need a properly typed value for method lookup. For
- static methods arg2 is otherwise unused. */
- arg2 = value_zero (type, lval_memory);
- ++nargs;
- tem = 2;
- }
- }
- else if (op == OP_ADL_FUNC)
- {
- /* Save the function position and move pos so that the arguments
- can be evaluated. */
- int func_name_len;
-
- save_pos1 = *pos;
- tem = 1;
-
- func_name_len = longest_to_int (exp->elts[save_pos1 + 3].longconst);
- (*pos) += 6 + BYTES_TO_EXP_ELEM (func_name_len + 1);
- }
- else
- {
- /* Non-method function call. */
- save_pos1 = *pos;
- tem = 1;
-
- /* If this is a C++ function wait until overload resolution. */
- if (op == OP_VAR_VALUE
- && overload_resolution
- && (exp->language_defn->la_language == language_cplus))
- {
- (*pos) += 4; /* Skip the evaluation of the symbol. */
- argvec[0] = NULL;
- }
- else
- {
- if (op == OP_VAR_MSYM_VALUE)
- {
- minimal_symbol *msym = exp->elts[*pos + 2].msymbol;
- var_func_name = msym->print_name ();
- }
- else if (op == OP_VAR_VALUE)
- {
- symbol *sym = exp->elts[*pos + 2].symbol;
- var_func_name = sym->print_name ();
- }
-
- argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside);
- type *type = value_type (argvec[0]);
- if (type && type->code () == TYPE_CODE_PTR)
- type = TYPE_TARGET_TYPE (type);
- if (type && type->code () == TYPE_CODE_FUNC)
- {
- for (; tem <= nargs && tem <= type->num_fields (); tem++)
- {
- argvec[tem] = evaluate_subexp (type->field (tem - 1).type (),
- exp, pos, noside);
- }
- }
- }
- }
-
- /* Evaluate arguments (if not already done, e.g., namespace::func()
- and overload-resolution is off). */
- for (; tem <= nargs; tem++)
- {
- /* Ensure that array expressions are coerced into pointer
- objects. */
- argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
- }
-
- /* Signal end of arglist. */
- argvec[tem] = 0;
-
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
-
- if (op == OP_ADL_FUNC)
- {
- struct symbol *symp;
- char *func_name;
- int name_len;
- int string_pc = save_pos1 + 3;
-
- /* Extract the function name. */
- name_len = longest_to_int (exp->elts[string_pc].longconst);
- func_name = (char *) alloca (name_len + 1);
- strcpy (func_name, &exp->elts[string_pc + 1].string);
-
- find_overload_match (gdb::make_array_view (&argvec[1], nargs),
- func_name,
- NON_METHOD, /* not method */
- NULL, NULL, /* pass NULL symbol since
- symbol is unknown */
- NULL, &symp, NULL, 0, noside);
-
- /* Now fix the expression being evaluated. */
- exp->elts[save_pos1 + 2].symbol = symp;
- argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
- }
-
- if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR
- || (op == OP_SCOPE && function_name != NULL))
- {
- int static_memfuncp;
- char *tstr;
-
- /* Method invocation: stuff "this" as first parameter. If the
- method turns out to be static we undo this below. */
- argvec[1] = arg2;
-
- if (op != OP_SCOPE)
- {
- /* Name of method from expression. */
- tstr = &exp->elts[pc2 + 2].string;
- }
- else
- tstr = function_name;
-
- if (overload_resolution && (exp->language_defn->la_language
- == language_cplus))
- {
- /* Language is C++, do some overload resolution before
- evaluation. */
- struct value *valp = NULL;
-
- (void) find_overload_match (gdb::make_array_view (&argvec[1], nargs),
- tstr,
- METHOD, /* method */
- &arg2, /* the object */
- NULL, &valp, NULL,
- &static_memfuncp, 0, noside);
-
- if (op == OP_SCOPE && !static_memfuncp)
- {
- /* For the time being, we don't handle this. */
- error (_("Call to overloaded function %s requires "
- "`this' pointer"),
- function_name);
- }
- argvec[1] = arg2; /* the ``this'' pointer */
- argvec[0] = valp; /* Use the method found after overload
- resolution. */
- }
- else
- /* Non-C++ case -- or no overload resolution. */
- {
- struct value *temp = arg2;
-
- argvec[0] = value_struct_elt (&temp, argvec + 1, tstr,
- &static_memfuncp,
- op == STRUCTOP_STRUCT
- ? "structure" : "structure pointer");
- /* value_struct_elt updates temp with the correct value of
- the ``this'' pointer if necessary, so modify argvec[1] to
- reflect any ``this'' changes. */
- arg2
- = value_from_longest (lookup_pointer_type(value_type (temp)),
- value_address (temp)
- + value_embedded_offset (temp));
- argvec[1] = arg2; /* the ``this'' pointer */
- }
-
- /* Take out `this' if needed. */
- if (static_memfuncp)
- {
- argvec[1] = argvec[0];
- nargs--;
- argvec++;
- }
- }
- else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
- {
- /* Pointer to member. argvec[1] is already set up. */
- argvec[0] = arg1;
- }
- else if (op == OP_VAR_VALUE || (op == OP_SCOPE && function != NULL))
- {
- /* Non-member function being called. */
- /* fn: This can only be done for C++ functions. A C-style
- function in a C++ program, for instance, does not have the
- fields that are expected here. */
-
- if (overload_resolution && (exp->language_defn->la_language
- == language_cplus))
- {
- /* Language is C++, do some overload resolution before
- evaluation. */
- struct symbol *symp;
- int no_adl = 0;
-
- /* If a scope has been specified disable ADL. */
- if (op == OP_SCOPE)
- no_adl = 1;
-
- if (op == OP_VAR_VALUE)
- function = exp->elts[save_pos1+2].symbol;
-
- (void) find_overload_match (gdb::make_array_view (&argvec[1], nargs),
- NULL, /* no need for name */
- NON_METHOD, /* not method */
- NULL, function, /* the function */
- NULL, &symp, NULL, no_adl, noside);
-
- if (op == OP_VAR_VALUE)
- {
- /* Now fix the expression being evaluated. */
- exp->elts[save_pos1+2].symbol = symp;
- argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1,
- noside);
- }
- else
- argvec[0] = value_of_variable (symp, get_selected_block (0));
- }
- else
- {
- /* Not C++, or no overload resolution allowed. */
- /* Nothing to be done; argvec already correctly set up. */
- }
- }
- else
- {
- /* It is probably a C-style function. */
- /* Nothing to be done; argvec already correctly set up. */
- }
-
- return evaluate_subexp_do_call (exp, noside, argvec[0],
- gdb::make_array_view (argvec + 1, nargs),
- var_func_name, expect_type);
-}
-
namespace expr
{
}
-struct value *
-evaluate_subexp_standard (struct type *expect_type,
- struct expression *exp, int *pos,
- enum noside noside)
-{
- enum exp_opcode op;
- int tem, tem2, tem3;
- int pc, oldpos;
- struct value *arg1 = NULL;
- struct value *arg2 = NULL;
- struct type *type;
- int nargs;
- struct value **argvec;
- int ix;
- struct type **arg_types;
-
- pc = (*pos)++;
- op = exp->elts[pc].opcode;
-
- switch (op)
- {
- case OP_SCOPE:
- tem = longest_to_int (exp->elts[pc + 2].longconst);
- (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
- return eval_op_scope (expect_type, exp, noside,
- exp->elts[pc + 1].type,
- &exp->elts[pc + 3].string);
-
- case OP_LONG:
- (*pos) += 3;
- return value_from_longest (exp->elts[pc + 1].type,
- exp->elts[pc + 2].longconst);
-
- case OP_FLOAT:
- (*pos) += 3;
- return value_from_contents (exp->elts[pc + 1].type,
- exp->elts[pc + 2].floatconst);
-
- case OP_ADL_FUNC:
- case OP_VAR_VALUE:
- {
- (*pos) += 3;
- symbol *var = exp->elts[pc + 2].symbol;
- if (SYMBOL_TYPE (var)->code () == TYPE_CODE_ERROR)
- error_unknown_type (var->print_name ());
- if (noside != EVAL_SKIP)
- return evaluate_var_value (noside, exp->elts[pc + 1].block, var);
- else
- {
- /* Return a dummy value of the correct type when skipping, so
- that parent functions know what is to be skipped. */
- return allocate_value (SYMBOL_TYPE (var));
- }
- }
-
- case OP_VAR_MSYM_VALUE:
- {
- (*pos) += 3;
-
- minimal_symbol *msymbol = exp->elts[pc + 2].msymbol;
- return eval_op_var_msym_value (expect_type, exp, noside,
- pc == 0, msymbol,
- exp->elts[pc + 1].objfile);
- }
-
- case OP_VAR_ENTRY_VALUE:
- (*pos) += 2;
-
- {
- struct symbol *sym = exp->elts[pc + 1].symbol;
-
- return eval_op_var_entry_value (expect_type, exp, noside, sym);
- }
-
- case OP_FUNC_STATIC_VAR:
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
-
- {
- value *func = evaluate_subexp_standard (NULL, exp, pos, noside);
-
- return eval_op_func_static_var (expect_type, exp, noside, func,
- &exp->elts[pc + 2].string);
- }
-
- case OP_LAST:
- (*pos) += 2;
- return
- access_value_history (longest_to_int (exp->elts[pc + 1].longconst));
-
- case OP_REGISTER:
- {
- const char *name = &exp->elts[pc + 2].string;
-
- (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
- return eval_op_register (expect_type, exp, noside, name);
- }
- case OP_BOOL:
- (*pos) += 2;
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, exp->elts[pc + 1].longconst);
-
- case OP_INTERNALVAR:
- (*pos) += 2;
- return value_of_internalvar (exp->gdbarch,
- exp->elts[pc + 1].internalvar);
-
- case OP_STRING:
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- return eval_op_string (expect_type, exp, noside, tem,
- &exp->elts[pc + 2].string);
-
- case OP_OBJC_NSSTRING: /* Objective C Foundation Class
- NSString constant. */
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- return value_nsstring (exp->gdbarch, &exp->elts[pc + 2].string, tem + 1);
-
- case OP_ARRAY:
- (*pos) += 3;
- tem2 = longest_to_int (exp->elts[pc + 1].longconst);
- tem3 = longest_to_int (exp->elts[pc + 2].longconst);
- nargs = tem3 - tem2 + 1;
- type = expect_type ? check_typedef (expect_type) : nullptr;
-
- if (expect_type != nullptr && noside != EVAL_SKIP
- && type->code () == TYPE_CODE_STRUCT)
- {
- struct value *rec = allocate_value (expect_type);
-
- memset (value_contents_raw (rec), '\0', TYPE_LENGTH (type));
- return evaluate_struct_tuple (rec, exp, pos, noside, nargs);
- }
-
- if (expect_type != nullptr && noside != EVAL_SKIP
- && type->code () == TYPE_CODE_ARRAY)
- {
- struct type *range_type = type->index_type ();
- struct type *element_type = TYPE_TARGET_TYPE (type);
- struct value *array = allocate_value (expect_type);
- int element_size = TYPE_LENGTH (check_typedef (element_type));
- LONGEST low_bound, high_bound, index;
-
- if (!get_discrete_bounds (range_type, &low_bound, &high_bound))
- {
- low_bound = 0;
- high_bound = (TYPE_LENGTH (type) / element_size) - 1;
- }
- index = low_bound;
- memset (value_contents_raw (array), 0, TYPE_LENGTH (expect_type));
- for (tem = nargs; --nargs >= 0;)
- {
- struct value *element;
-
- element = evaluate_subexp (element_type, exp, pos, noside);
- if (value_type (element) != element_type)
- element = value_cast (element_type, element);
- if (index > high_bound)
- /* To avoid memory corruption. */
- error (_("Too many array elements"));
- memcpy (value_contents_raw (array)
- + (index - low_bound) * element_size,
- value_contents (element),
- element_size);
- index++;
- }
- return array;
- }
-
- if (expect_type != nullptr && noside != EVAL_SKIP
- && type->code () == TYPE_CODE_SET)
- {
- struct value *set = allocate_value (expect_type);
- gdb_byte *valaddr = value_contents_raw (set);
- struct type *element_type = type->index_type ();
- struct type *check_type = element_type;
- LONGEST low_bound, high_bound;
-
- /* Get targettype of elementtype. */
- while (check_type->code () == TYPE_CODE_RANGE
- || check_type->code () == TYPE_CODE_TYPEDEF)
- check_type = TYPE_TARGET_TYPE (check_type);
-
- if (!get_discrete_bounds (element_type, &low_bound, &high_bound))
- error (_("(power)set type with unknown size"));
- memset (valaddr, '\0', TYPE_LENGTH (type));
- for (tem = 0; tem < nargs; tem++)
- {
- LONGEST range_low, range_high;
- struct type *range_low_type, *range_high_type;
- struct value *elem_val;
-
- elem_val = evaluate_subexp (element_type, exp, pos, noside);
- range_low_type = range_high_type = value_type (elem_val);
- range_low = range_high = value_as_long (elem_val);
-
- /* Check types of elements to avoid mixture of elements from
- different types. Also check if type of element is "compatible"
- with element type of powerset. */
- if (range_low_type->code () == TYPE_CODE_RANGE)
- range_low_type = TYPE_TARGET_TYPE (range_low_type);
- if (range_high_type->code () == TYPE_CODE_RANGE)
- range_high_type = TYPE_TARGET_TYPE (range_high_type);
- if ((range_low_type->code () != range_high_type->code ())
- || (range_low_type->code () == TYPE_CODE_ENUM
- && (range_low_type != range_high_type)))
- /* different element modes. */
- error (_("POWERSET tuple elements of different mode"));
- if ((check_type->code () != range_low_type->code ())
- || (check_type->code () == TYPE_CODE_ENUM
- && range_low_type != check_type))
- error (_("incompatible POWERSET tuple elements"));
- if (range_low > range_high)
- {
- warning (_("empty POWERSET tuple range"));
- continue;
- }
- if (range_low < low_bound || range_high > high_bound)
- error (_("POWERSET tuple element out of range"));
- range_low -= low_bound;
- range_high -= low_bound;
- for (; range_low <= range_high; range_low++)
- {
- int bit_index = (unsigned) range_low % TARGET_CHAR_BIT;
-
- if (gdbarch_byte_order (exp->gdbarch) == BFD_ENDIAN_BIG)
- bit_index = TARGET_CHAR_BIT - 1 - bit_index;
- valaddr[(unsigned) range_low / TARGET_CHAR_BIT]
- |= 1 << bit_index;
- }
- }
- return set;
- }
-
- argvec = XALLOCAVEC (struct value *, nargs);
- for (tem = 0; tem < nargs; tem++)
- {
- /* Ensure that array expressions are coerced into pointer
- objects. */
- argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
- }
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- return value_array (tem2, tem3, argvec);
-
- case TERNOP_SLICE:
- {
- struct value *array = evaluate_subexp (nullptr, exp, pos, noside);
- struct value *low = evaluate_subexp (nullptr, exp, pos, noside);
- struct value *upper = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_ternop (expect_type, exp, noside, array, low, upper);
- }
-
- case TERNOP_COND:
- /* Skip third and second args to evaluate the first one. */
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- if (value_logical_not (arg1))
- {
- evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
- return evaluate_subexp (nullptr, exp, pos, noside);
- }
- else
- {
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
- return arg2;
- }
-
- case OP_OBJC_SELECTOR:
- { /* Objective C @selector operator. */
- char *sel = &exp->elts[pc + 2].string;
- int len = longest_to_int (exp->elts[pc + 1].longconst);
-
- (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
- if (sel[len] != 0)
- sel[len] = 0; /* Make sure it's terminated. */
-
- return eval_op_objc_selector (expect_type, exp, noside, sel);
- }
-
- case OP_OBJC_MSGCALL:
- { /* Objective C message (method) call. */
- CORE_ADDR selector = 0;
-
- enum noside sub_no_side = EVAL_NORMAL;
-
- struct value *target = NULL;
-
- struct type *selector_type = NULL;
-
- selector = exp->elts[pc + 1].longconst;
- nargs = exp->elts[pc + 2].longconst;
- argvec = XALLOCAVEC (struct value *, nargs + 3);
-
- (*pos) += 3;
-
- selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr;
-
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- sub_no_side = EVAL_NORMAL;
- else
- sub_no_side = noside;
-
- target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
-
- if (value_as_long (target) == 0)
- sub_no_side = EVAL_SKIP;
- else
- sub_no_side = noside;
-
- /* Now depending on whether we found a symbol for the method,
- we will either call the runtime dispatcher or the method
- directly. */
-
- argvec[0] = nullptr;
- argvec[1] = nullptr;
- /* User-supplied arguments. */
- for (tem = 0; tem < nargs; tem++)
- argvec[tem + 2] = evaluate_subexp_with_coercion (exp, pos,
- sub_no_side);
- argvec[tem + 3] = 0;
-
- auto call_args = gdb::make_array_view (argvec, nargs + 3);
-
- return eval_op_objc_msgcall (expect_type, exp, noside, selector,
- target, call_args);
- }
- break;
-
- case OP_FUNCALL:
- return evaluate_funcall (expect_type, exp, pos, noside);
-
- case OP_COMPLEX:
- /* We have a complex number, There should be 2 floating
- point numbers that compose it. */
- (*pos) += 2;
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
-
- return value_literal_complex (arg1, arg2, exp->elts[pc + 1].type);
-
- case STRUCTOP_STRUCT:
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_structop_struct (expect_type, exp, noside, arg1,
- &exp->elts[pc + 2].string);
-
- case STRUCTOP_PTR:
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_structop_ptr (expect_type, exp, noside, arg1,
- &exp->elts[pc + 2].string);
-
- case STRUCTOP_MEMBER:
- case STRUCTOP_MPTR:
- if (op == STRUCTOP_MEMBER)
- arg1 = evaluate_subexp_for_address (exp, pos, noside);
- else
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
-
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
-
- return eval_op_member (expect_type, exp, noside, arg1, arg2);
-
- case TYPE_INSTANCE:
- {
- type_instance_flags flags
- = (type_instance_flag_value) longest_to_int (exp->elts[pc + 1].longconst);
- nargs = longest_to_int (exp->elts[pc + 2].longconst);
- arg_types = (struct type **) alloca (nargs * sizeof (struct type *));
- for (ix = 0; ix < nargs; ++ix)
- arg_types[ix] = exp->elts[pc + 2 + ix + 1].type;
-
- fake_method fake_expect_type (flags, nargs, arg_types);
- *(pos) += 4 + nargs;
- return evaluate_subexp_standard (fake_expect_type.type (), exp, pos,
- noside);
- }
-
- case BINOP_CONCAT:
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
- return eval_op_concat (expect_type, exp, noside, arg1, arg2);
-
- case BINOP_ASSIGN:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- /* Special-case assignments where the left-hand-side is a
- convenience variable -- in these, don't bother setting an
- expected type. This avoids a weird case where re-assigning a
- string or array to an internal variable could error with "Too
- many array elements". */
- arg2 = evaluate_subexp (VALUE_LVAL (arg1) == lval_internalvar
- ? nullptr
- : value_type (arg1),
- exp, pos, noside);
-
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- else
- return value_assign (arg1, arg2);
-
- case BINOP_ASSIGN_MODIFY:
- (*pos) += 2;
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- op = exp->elts[pc + 1].opcode;
- return eval_binop_assign_modify (expect_type, exp, noside, op,
- arg1, arg2);
-
- case BINOP_ADD:
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
- return eval_op_add (expect_type, exp, noside, arg1, arg2);
-
- case BINOP_SUB:
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
- return eval_op_sub (expect_type, exp, noside, arg1, arg2);
-
- case BINOP_EXP:
- case BINOP_MUL:
- case BINOP_DIV:
- case BINOP_INTDIV:
- case BINOP_REM:
- case BINOP_MOD:
- case BINOP_LSH:
- case BINOP_RSH:
- case BINOP_BITWISE_AND:
- case BINOP_BITWISE_IOR:
- case BINOP_BITWISE_XOR:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_binary (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_SUBSCRIPT:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_subscript (expect_type, exp, noside, op, arg1, arg2);
-
- case MULTI_SUBSCRIPT:
- (*pos) += 2;
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- argvec = XALLOCAVEC (struct value *, nargs);
- for (ix = 0; ix < nargs; ++ix)
- argvec[ix] = evaluate_subexp_with_coercion (exp, pos, noside);
- return eval_multi_subscript (expect_type, exp, noside, arg1,
- gdb::make_array_view (argvec, nargs));
-
- case BINOP_LOGICAL_AND:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (nullptr, exp, pos, noside);
- return eval_skip_value (exp);
- }
-
- oldpos = *pos;
- arg2 = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- *pos = oldpos;
-
- if (binop_user_defined_p (op, arg1, arg2))
- {
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- tem = value_logical_not (arg1);
- arg2
- = evaluate_subexp (nullptr, exp, pos, (tem ? EVAL_SKIP : noside));
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type,
- (LONGEST) (!tem && !value_logical_not (arg2)));
- }
-
- case BINOP_LOGICAL_OR:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (nullptr, exp, pos, noside);
- return eval_skip_value (exp);
- }
-
- oldpos = *pos;
- arg2 = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- *pos = oldpos;
-
- if (binop_user_defined_p (op, arg1, arg2))
- {
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- tem = value_logical_not (arg1);
- arg2
- = evaluate_subexp (nullptr, exp, pos, (!tem ? EVAL_SKIP : noside));
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type,
- (LONGEST) (!tem || !value_logical_not (arg2)));
- }
-
- case BINOP_EQUAL:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- return eval_op_equal (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_NOTEQUAL:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- return eval_op_notequal (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_LESS:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- return eval_op_less (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_GTR:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- return eval_op_gtr (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_GEQ:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- return eval_op_geq (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_LEQ:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- return eval_op_leq (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_REPEAT:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_repeat (expect_type, exp, noside, op, arg1, arg2);
-
- case BINOP_COMMA:
- evaluate_subexp (nullptr, exp, pos, noside);
- return evaluate_subexp (nullptr, exp, pos, noside);
-
- case UNOP_PLUS:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_plus (expect_type, exp, noside, op, arg1);
-
- case UNOP_NEG:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_neg (expect_type, exp, noside, op, arg1);
-
- case UNOP_COMPLEMENT:
- /* C++: check for and handle destructor names. */
-
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_complement (expect_type, exp, noside, op, arg1);
-
- case UNOP_LOGICAL_NOT:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- return eval_op_lognot (expect_type, exp, noside, op, arg1);
-
- case UNOP_IND:
- if (expect_type && expect_type->code () == TYPE_CODE_PTR)
- expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_ind (expect_type, exp, noside, arg1);
-
- case UNOP_ADDR:
- /* C++: check for and handle pointer to members. */
-
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
- return eval_skip_value (exp);
- }
- else
- return evaluate_subexp_for_address (exp, pos, noside);
-
- case UNOP_SIZEOF:
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
- return eval_skip_value (exp);
- }
- return evaluate_subexp_for_sizeof (exp, pos, noside);
-
- case UNOP_ALIGNOF:
- arg1 = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return eval_op_alignof (expect_type, exp, noside, arg1);
-
- case UNOP_CAST:
- (*pos) += 2;
- type = exp->elts[pc + 1].type;
- return evaluate_subexp_for_cast (exp, pos, noside, type);
-
- case UNOP_CAST_TYPE:
- arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (arg1);
- return evaluate_subexp_for_cast (exp, pos, noside, type);
-
- case UNOP_DYNAMIC_CAST:
- arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (arg1);
- arg1 = evaluate_subexp (type, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- return value_dynamic_cast (type, arg1);
-
- case UNOP_REINTERPRET_CAST:
- arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (arg1);
- arg1 = evaluate_subexp (type, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- return value_reinterpret_cast (type, arg1);
-
- case UNOP_MEMVAL:
- (*pos) += 2;
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_memval (expect_type, exp, noside, arg1,
- exp->elts[pc + 1].type);
-
- case UNOP_MEMVAL_TYPE:
- arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (arg1);
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_memval (expect_type, exp, noside, arg1, type);
-
- case UNOP_PREINCREMENT:
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_preinc (expect_type, exp, noside, op, arg1);
-
- case UNOP_PREDECREMENT:
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_predec (expect_type, exp, noside, op, arg1);
-
- case UNOP_POSTINCREMENT:
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_postinc (expect_type, exp, noside, op, arg1);
-
- case UNOP_POSTDECREMENT:
- arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- return eval_op_postdec (expect_type, exp, noside, op, arg1);
-
- case OP_THIS:
- (*pos) += 1;
- return value_of_this (exp->language_defn);
-
- case OP_TYPE:
- /* The value is not supposed to be used. This is here to make it
- easier to accommodate expressions that contain types. */
- (*pos) += 2;
- return eval_op_type (expect_type, exp, noside, exp->elts[pc + 1].type);
-
- case OP_TYPEOF:
- case OP_DECLTYPE:
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
- return eval_skip_value (exp);
- }
- else if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- enum exp_opcode sub_op = exp->elts[*pos].opcode;
- struct value *result;
-
- result = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
-
- /* 'decltype' has special semantics for lvalues. */
- if (op == OP_DECLTYPE
- && (sub_op == BINOP_SUBSCRIPT
- || sub_op == STRUCTOP_MEMBER
- || sub_op == STRUCTOP_MPTR
- || sub_op == UNOP_IND
- || sub_op == STRUCTOP_STRUCT
- || sub_op == STRUCTOP_PTR
- || sub_op == OP_SCOPE))
- {
- type = value_type (result);
-
- if (!TYPE_IS_REFERENCE (type))
- {
- type = lookup_lvalue_reference_type (type);
- result = allocate_value (type);
- }
- }
-
- return result;
- }
- else
- error (_("Attempt to use a type as an expression"));
-
- case OP_TYPEID:
- {
- struct value *result;
- enum exp_opcode sub_op = exp->elts[*pos].opcode;
-
- if (sub_op == OP_TYPE || sub_op == OP_DECLTYPE || sub_op == OP_TYPEOF)
- result = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- else
- result = evaluate_subexp (nullptr, exp, pos, noside);
-
- if (noside != EVAL_NORMAL)
- return allocate_value (cplus_typeid_type (exp->gdbarch));
-
- return cplus_typeid (result);
- }
-
- default:
- /* Removing this case and compiling with gcc -Wall reveals that
- a lot of cases are hitting this case. Some of these should
- probably be removed from expression.h; others are legitimate
- expressions which are (apparently) not fully implemented.
-
- If there are any cases landing here which mean a user error,
- then they should be separate cases, with more descriptive
- error messages. */
-
- error (_("GDB does not (yet) know how to "
- "evaluate that kind of expression"));
- }
-
- gdb_assert_not_reached ("missed return?");
-}
\f
/* Helper for evaluate_subexp_for_address. */
return value_addr (x);
}
-/* Evaluate a subexpression of EXP, at index *POS,
- and return the address of that subexpression.
- Advance *POS over the subexpression.
- If the subexpression isn't an lvalue, get an error.
- NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
- then only the type of the result need be correct. */
-
-static struct value *
-evaluate_subexp_for_address (struct expression *exp, int *pos,
- enum noside noside)
-{
- enum exp_opcode op;
- int pc;
- struct symbol *var;
- struct value *x;
- int tem;
-
- pc = (*pos);
- op = exp->elts[pc].opcode;
-
- switch (op)
- {
- case UNOP_IND:
- (*pos)++;
- x = evaluate_subexp (nullptr, exp, pos, noside);
-
- /* We can't optimize out "&*" if there's a user-defined operator*. */
- if (unop_user_defined_p (op, x))
- {
- x = value_x_unop (x, op, noside);
- goto default_case_after_eval;
- }
-
- return coerce_array (x);
-
- case UNOP_MEMVAL:
- (*pos) += 3;
- return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
- evaluate_subexp (nullptr, exp, pos, noside));
-
- case UNOP_MEMVAL_TYPE:
- {
- struct type *type;
-
- (*pos) += 1;
- x = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (x);
- return value_cast (lookup_pointer_type (type),
- evaluate_subexp (nullptr, exp, pos, noside));
- }
-
- case OP_VAR_VALUE:
- var = exp->elts[pc + 2].symbol;
-
- /* C++: The "address" of a reference should yield the address
- * of the object pointed to. Let value_addr() deal with it. */
- if (TYPE_IS_REFERENCE (SYMBOL_TYPE (var)))
- goto default_case;
-
- (*pos) += 4;
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- struct type *type =
- lookup_pointer_type (SYMBOL_TYPE (var));
- enum address_class sym_class = SYMBOL_CLASS (var);
-
- if (sym_class == LOC_CONST
- || sym_class == LOC_CONST_BYTES
- || sym_class == LOC_REGISTER)
- error (_("Attempt to take address of register or constant."));
-
- return
- value_zero (type, not_lval);
- }
- else
- return address_of_variable (var, exp->elts[pc + 1].block);
-
- case OP_VAR_MSYM_VALUE:
- {
- (*pos) += 4;
-
- value *val = evaluate_var_msym_value (noside,
- exp->elts[pc + 1].objfile,
- exp->elts[pc + 2].msymbol);
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- struct type *type = lookup_pointer_type (value_type (val));
- return value_zero (type, not_lval);
- }
- else
- return value_addr (val);
- }
-
- case OP_SCOPE:
- tem = longest_to_int (exp->elts[pc + 2].longconst);
- (*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1);
- x = value_aggregate_elt (exp->elts[pc + 1].type,
- &exp->elts[pc + 3].string,
- NULL, 1, noside);
- if (x == NULL)
- error (_("There is no field named %s"), &exp->elts[pc + 3].string);
- return x;
-
- default:
- default_case:
- x = evaluate_subexp (nullptr, exp, pos, noside);
- default_case_after_eval:
- return evaluate_subexp_for_address_base (exp, noside, x);
- }
-}
-
namespace expr
{
}
-/* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
- When used in contexts where arrays will be coerced anyway, this is
- equivalent to `evaluate_subexp' but much faster because it avoids
- actually fetching array contents (perhaps obsolete now that we have
- value_lazy()).
-
- Note that we currently only do the coercion for C expressions, where
- arrays are zero based and the coercion is correct. For other languages,
- with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION
- to decide if coercion is appropriate. */
-
-struct value *
-evaluate_subexp_with_coercion (struct expression *exp,
- int *pos, enum noside noside)
-{
- enum exp_opcode op;
- int pc;
- struct value *val;
- struct symbol *var;
- struct type *type;
-
- pc = (*pos);
- op = exp->elts[pc].opcode;
-
- switch (op)
- {
- case OP_VAR_VALUE:
- var = exp->elts[pc + 2].symbol;
- type = check_typedef (SYMBOL_TYPE (var));
- if (type->code () == TYPE_CODE_ARRAY
- && !type->is_vector ()
- && CAST_IS_CONVERSION (exp->language_defn))
- {
- (*pos) += 4;
- val = address_of_variable (var, exp->elts[pc + 1].block);
- return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
- val);
- }
- /* FALLTHROUGH */
-
- default:
- return evaluate_subexp (nullptr, exp, pos, noside);
- }
-}
-
namespace expr
{
return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
}
-/* Evaluate a subexpression of EXP, at index *POS,
- and return a value for the size of that subexpression.
- Advance *POS over the subexpression. If NOSIDE is EVAL_NORMAL
- we allow side-effects on the operand if its type is a variable
- length array. */
-
-static struct value *
-evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
- enum noside noside)
-{
- /* FIXME: This should be size_t. */
- struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
- enum exp_opcode op;
- int pc;
- struct type *type;
- struct value *val;
-
- pc = (*pos);
- op = exp->elts[pc].opcode;
-
- switch (op)
- {
- /* This case is handled specially
- so that we avoid creating a value for the result type.
- If the result type is very big, it's desirable not to
- create a value unnecessarily. */
- case UNOP_IND:
- (*pos)++;
- val = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = check_typedef (value_type (val));
- if (type->code () != TYPE_CODE_PTR
- && !TYPE_IS_REFERENCE (type)
- && type->code () != TYPE_CODE_ARRAY)
- error (_("Attempt to take contents of a non-pointer value."));
- type = TYPE_TARGET_TYPE (type);
- if (is_dynamic_type (type))
- type = value_type (value_ind (val));
- return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
-
- case UNOP_MEMVAL:
- (*pos) += 3;
- type = exp->elts[pc + 1].type;
- break;
-
- case UNOP_MEMVAL_TYPE:
- (*pos) += 1;
- val = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (val);
- break;
-
- case OP_VAR_VALUE:
- type = SYMBOL_TYPE (exp->elts[pc + 2].symbol);
- if (is_dynamic_type (type))
- {
- val = evaluate_subexp (nullptr, exp, pos, EVAL_NORMAL);
- type = value_type (val);
- if (type->code () == TYPE_CODE_ARRAY)
- {
- if (type_not_allocated (type) || type_not_associated (type))
- return value_zero (size_type, not_lval);
- else if (is_dynamic_type (type->index_type ())
- && type->bounds ()->high.kind () == PROP_UNDEFINED)
- return allocate_optimized_out_value (size_type);
- }
- }
- else
- (*pos) += 4;
- break;
-
- case OP_VAR_MSYM_VALUE:
- {
- (*pos) += 4;
-
- minimal_symbol *msymbol = exp->elts[pc + 2].msymbol;
- value *mval = evaluate_var_msym_value (noside,
- exp->elts[pc + 1].objfile,
- msymbol);
-
- type = value_type (mval);
- if (type->code () == TYPE_CODE_ERROR)
- error_unknown_type (msymbol->print_name ());
-
- return value_from_longest (size_type, TYPE_LENGTH (type));
- }
- break;
-
- /* Deal with the special case if NOSIDE is EVAL_NORMAL and the resulting
- type of the subscript is a variable length array type. In this case we
- must re-evaluate the right hand side of the subscription to allow
- side-effects. */
- case BINOP_SUBSCRIPT:
- if (noside == EVAL_NORMAL)
- {
- int npc = (*pos) + 1;
-
- val = evaluate_subexp (nullptr, exp, &npc, EVAL_AVOID_SIDE_EFFECTS);
- type = check_typedef (value_type (val));
- if (type->code () == TYPE_CODE_ARRAY)
- {
- type = check_typedef (TYPE_TARGET_TYPE (type));
- if (type->code () == TYPE_CODE_ARRAY)
- {
- type = type->index_type ();
- /* Only re-evaluate the right hand side if the resulting type
- is a variable length type. */
- if (type->bounds ()->flag_bound_evaluated)
- {
- val = evaluate_subexp (nullptr, exp, pos, EVAL_NORMAL);
- return value_from_longest
- (size_type, (LONGEST) TYPE_LENGTH (value_type (val)));
- }
- }
- }
- }
-
- /* Fall through. */
-
- default:
- val = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = value_type (val);
- break;
- }
-
- return evaluate_subexp_for_sizeof_base (exp, type);
-}
-
namespace expr
{
}
-/* Evaluate a subexpression of EXP, at index *POS, and return a value
- for that subexpression cast to TO_TYPE. Advance *POS over the
- subexpression. */
-
-static value *
-evaluate_subexp_for_cast (expression *exp, int *pos,
- enum noside noside,
- struct type *to_type)
-{
- int pc = *pos;
-
- /* Don't let symbols be evaluated with evaluate_subexp because that
- throws an "unknown type" error for no-debug data symbols.
- Instead, we want the cast to reinterpret the symbol. */
- if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE
- || exp->elts[pc].opcode == OP_VAR_VALUE)
- {
- (*pos) += 4;
-
- value *val;
- if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE)
- {
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value_zero (to_type, not_lval);
-
- val = evaluate_var_msym_value (noside,
- exp->elts[pc + 1].objfile,
- exp->elts[pc + 2].msymbol);
- }
- else
- val = evaluate_var_value (noside,
- exp->elts[pc + 1].block,
- exp->elts[pc + 2].symbol);
-
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
-
- val = value_cast (to_type, val);
-
- /* Don't allow e.g. '&(int)var_with_no_debug_info'. */
- if (VALUE_LVAL (val) == lval_memory)
- {
- if (value_lazy (val))
- value_fetch_lazy (val);
- VALUE_LVAL (val) = not_lval;
- }
- return val;
- }
-
- value *val = evaluate_subexp (to_type, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- return value_cast (to_type, val);
-}
-
namespace expr
{
tmp[length + 2] = '0';
tmp[length + 3] = '\0';
expression_up expr = parse_expression (tmp);
- if (expr->first_opcode () != UNOP_CAST)
+ expr::unop_cast_operation *op
+ = dynamic_cast<expr::unop_cast_operation *> (expr->op.get ());
+ if (op == nullptr)
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;
+ return op->get_type ();
}
#include <ctype.h>
-void
-print_expression (struct expression *exp, struct ui_file *stream)
-{
- int pc = 0;
-
- print_subexp (exp, &pc, stream, PREC_NULL);
-}
-
-/* Print the subexpression of EXP that starts in position POS, on STREAM.
- PREC is the precedence of the surrounding operator;
- if the precedence of the main operator of this subexpression is less,
- parentheses are needed here. */
-
-void
-print_subexp (struct expression *exp, int *pos,
- struct ui_file *stream, enum precedence prec)
-{
- exp->language_defn->expression_ops ()->print_subexp (exp, pos, stream,
- prec);
-}
-
-/* See parser-defs.h. */
-
-void
-print_subexp_funcall (struct expression *exp, int *pos,
- struct ui_file *stream)
-{
- unsigned nargs = longest_to_int (exp->elts[*pos].longconst);
- (*pos) += 2;
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered (" (", stream);
- for (unsigned tem = 0; tem < nargs; tem++)
- {
- if (tem != 0)
- fputs_filtered (", ", stream);
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- }
- fputs_filtered (")", stream);
-}
-
-/* Standard implementation of print_subexp for use in language_defn
- vectors. */
-void
-print_subexp_standard (struct expression *exp, int *pos,
- struct ui_file *stream, enum precedence prec)
-{
- unsigned tem;
- const struct op_print *op_print_tab;
- int pc;
- unsigned nargs;
- const char *op_str;
- int assign_modify = 0;
- enum exp_opcode opcode;
- enum precedence myprec = PREC_NULL;
- /* Set to 1 for a right-associative operator. */
- int assoc = 0;
- struct value *val;
- char *tempstr = NULL;
-
- op_print_tab = exp->language_defn->opcode_print_table ();
- pc = (*pos)++;
- opcode = exp->elts[pc].opcode;
- switch (opcode)
- {
- /* Common ops */
-
- case OP_TYPE:
- (*pos) += 2;
- type_print (exp->elts[pc + 1].type, "", stream, 0);
- return;
-
- case OP_SCOPE:
- myprec = PREC_PREFIX;
- assoc = 0;
- fputs_filtered (exp->elts[pc + 1].type->name (), stream);
- fputs_filtered ("::", stream);
- nargs = longest_to_int (exp->elts[pc + 2].longconst);
- (*pos) += 4 + BYTES_TO_EXP_ELEM (nargs + 1);
- fputs_filtered (&exp->elts[pc + 3].string, stream);
- return;
-
- case OP_LONG:
- {
- struct value_print_options opts;
-
- get_no_prettyformat_print_options (&opts);
- (*pos) += 3;
- value_print (value_from_longest (exp->elts[pc + 1].type,
- exp->elts[pc + 2].longconst),
- stream, &opts);
- }
- return;
-
- case OP_FLOAT:
- {
- struct value_print_options opts;
-
- get_no_prettyformat_print_options (&opts);
- (*pos) += 3;
- value_print (value_from_contents (exp->elts[pc + 1].type,
- exp->elts[pc + 2].floatconst),
- stream, &opts);
- }
- return;
-
- case OP_VAR_VALUE:
- {
- const struct block *b;
-
- (*pos) += 3;
- b = exp->elts[pc + 1].block;
- if (b != NULL
- && BLOCK_FUNCTION (b) != NULL
- && BLOCK_FUNCTION (b)->print_name () != NULL)
- {
- fputs_filtered (BLOCK_FUNCTION (b)->print_name (), stream);
- fputs_filtered ("::", stream);
- }
- fputs_filtered (exp->elts[pc + 2].symbol->print_name (), stream);
- }
- return;
-
- case OP_VAR_MSYM_VALUE:
- {
- (*pos) += 3;
- fputs_filtered (exp->elts[pc + 2].msymbol->print_name (), stream);
- }
- return;
-
- case OP_FUNC_STATIC_VAR:
- {
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- fputs_filtered (&exp->elts[pc + 1].string, stream);
- }
- return;
-
- case OP_VAR_ENTRY_VALUE:
- {
- (*pos) += 2;
- fprintf_filtered (stream, "%s@entry",
- exp->elts[pc + 1].symbol->print_name ());
- }
- return;
-
- case OP_LAST:
- (*pos) += 2;
- fprintf_filtered (stream, "$%d",
- longest_to_int (exp->elts[pc + 1].longconst));
- return;
-
- case OP_REGISTER:
- {
- const char *name = &exp->elts[pc + 2].string;
-
- (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
- fprintf_filtered (stream, "$%s", name);
- return;
- }
-
- case OP_BOOL:
- (*pos) += 2;
- fprintf_filtered (stream, "%s",
- longest_to_int (exp->elts[pc + 1].longconst)
- ? "TRUE" : "FALSE");
- return;
-
- case OP_INTERNALVAR:
- (*pos) += 2;
- fprintf_filtered (stream, "$%s",
- internalvar_name (exp->elts[pc + 1].internalvar));
- return;
-
- case OP_FUNCALL:
- print_subexp_funcall (exp, pos, stream);
- return;
-
- case OP_NAME:
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
- fputs_filtered (&exp->elts[pc + 2].string, stream);
- return;
-
- case OP_STRING:
- {
- struct value_print_options opts;
-
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
- /* LA_PRINT_STRING will print using the current repeat count threshold.
- If necessary, we can temporarily set it to zero, or pass it as an
- additional parameter to LA_PRINT_STRING. -fnf */
- get_user_print_options (&opts);
- exp->language_defn
- ->printstr (stream, builtin_type (exp->gdbarch)->builtin_char,
- (gdb_byte *) &exp->elts[pc + 2].string, nargs,
- NULL, 0, &opts);
- }
- return;
-
- case OP_OBJC_NSSTRING: /* Objective-C Foundation Class
- NSString constant. */
- {
- struct value_print_options opts;
-
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
- fputs_filtered ("@\"", stream);
- get_user_print_options (&opts);
- exp->language_defn
- ->printstr (stream, builtin_type (exp->gdbarch)->builtin_char,
- (gdb_byte *) &exp->elts[pc + 2].string, nargs,
- NULL, 0, &opts);
- fputs_filtered ("\"", stream);
- }
- return;
-
- case OP_OBJC_MSGCALL:
- { /* Objective C message (method) call. */
- (*pos) += 3;
- nargs = longest_to_int (exp->elts[pc + 2].longconst);
- fprintf_unfiltered (stream, "[");
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- gdb::unique_xmalloc_ptr<char> selector
- = target_read_string (exp->elts[pc + 1].longconst, 1024);
- if (selector == nullptr)
- error (_("bad selector"));
- if (nargs)
- {
- char *s, *nextS;
-
- s = selector.get ();
- for (tem = 0; tem < nargs; tem++)
- {
- nextS = strchr (s, ':');
- gdb_assert (nextS); /* Make sure we found ':'. */
- *nextS = '\0';
- fprintf_unfiltered (stream, " %s: ", s);
- s = nextS + 1;
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- }
- }
- else
- {
- fprintf_unfiltered (stream, " %s", selector.get ());
- }
- fprintf_unfiltered (stream, "]");
- return;
- }
-
- case OP_ARRAY:
- (*pos) += 3;
- nargs = longest_to_int (exp->elts[pc + 2].longconst);
- nargs -= longest_to_int (exp->elts[pc + 1].longconst);
- nargs++;
- tem = 0;
- if (exp->elts[pc + 4].opcode == OP_LONG
- && exp->elts[pc + 5].type
- == builtin_type (exp->gdbarch)->builtin_char
- && exp->language_defn->la_language == language_c)
- {
- /* Attempt to print C character arrays using string syntax.
- Walk through the args, picking up one character from each
- of the OP_LONG expression elements. If any array element
- does not match our expection of what we should find for
- a simple string, revert back to array printing. Note that
- the last expression element is an explicit null terminator
- byte, which doesn't get printed. */
- tempstr = (char *) alloca (nargs);
- pc += 4;
- while (tem < nargs)
- {
- if (exp->elts[pc].opcode != OP_LONG
- || exp->elts[pc + 1].type
- != builtin_type (exp->gdbarch)->builtin_char)
- {
- /* Not a simple array of char, use regular array
- printing. */
- tem = 0;
- break;
- }
- else
- {
- tempstr[tem++] =
- longest_to_int (exp->elts[pc + 2].longconst);
- pc += 4;
- }
- }
- }
- if (tem > 0)
- {
- struct value_print_options opts;
-
- get_user_print_options (&opts);
- exp->language_defn
- ->printstr (stream, builtin_type (exp->gdbarch)->builtin_char,
- (gdb_byte *) tempstr, nargs - 1, NULL, 0, &opts);
- (*pos) = pc;
- }
- else
- {
- fputs_filtered (" {", stream);
- for (tem = 0; tem < nargs; tem++)
- {
- if (tem != 0)
- {
- fputs_filtered (", ", stream);
- }
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- }
- fputs_filtered ("}", stream);
- }
- return;
-
- case TERNOP_COND:
- if ((int) prec > (int) PREC_COMMA)
- fputs_filtered ("(", stream);
- /* Print the subexpressions, forcing parentheses
- around any binary operations within them.
- This is more parentheses than are strictly necessary,
- but it looks clearer. */
- print_subexp (exp, pos, stream, PREC_HYPER);
- fputs_filtered (" ? ", stream);
- print_subexp (exp, pos, stream, PREC_HYPER);
- fputs_filtered (" : ", stream);
- print_subexp (exp, pos, stream, PREC_HYPER);
- if ((int) prec > (int) PREC_COMMA)
- fputs_filtered (")", stream);
- return;
-
- case TERNOP_SLICE:
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered ("(", stream);
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- fputs_filtered (opcode == TERNOP_SLICE ? " : " : " UP ", stream);
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- fputs_filtered (")", stream);
- return;
-
- case STRUCTOP_STRUCT:
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered (".", stream);
- fputs_filtered (&exp->elts[pc + 2].string, stream);
- return;
-
- /* Will not occur for Modula-2. */
- case STRUCTOP_PTR:
- tem = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered ("->", stream);
- fputs_filtered (&exp->elts[pc + 2].string, stream);
- return;
-
- case STRUCTOP_MEMBER:
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered (".*", stream);
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- return;
-
- case STRUCTOP_MPTR:
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered ("->*", stream);
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- return;
-
- case BINOP_SUBSCRIPT:
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered ("[", stream);
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- fputs_filtered ("]", stream);
- return;
-
- case UNOP_POSTINCREMENT:
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered ("++", stream);
- return;
-
- case UNOP_POSTDECREMENT:
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered ("--", stream);
- return;
-
- case UNOP_CAST:
- (*pos) += 2;
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered ("(", stream);
- fputs_filtered ("(", stream);
- type_print (exp->elts[pc + 1].type, "", stream, 0);
- fputs_filtered (") ", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered (")", stream);
- return;
-
- case UNOP_CAST_TYPE:
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered ("(", stream);
- fputs_filtered ("(", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- fputs_filtered (") ", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered (")", stream);
- return;
-
- case UNOP_DYNAMIC_CAST:
- case UNOP_REINTERPRET_CAST:
- fputs_filtered (opcode == UNOP_DYNAMIC_CAST ? "dynamic_cast"
- : "reinterpret_cast", stream);
- fputs_filtered ("<", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- fputs_filtered ("> (", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- fputs_filtered (")", stream);
- return;
-
- case UNOP_MEMVAL:
- (*pos) += 2;
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered ("(", stream);
- if (exp->elts[pc + 1].type->code () == TYPE_CODE_FUNC
- && exp->elts[pc + 3].opcode == OP_LONG)
- {
- struct value_print_options opts;
-
- /* We have a minimal symbol fn, probably. It's encoded
- as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
- Swallow the OP_LONG (including both its opcodes); ignore
- its type; print the value in the type of the MEMVAL. */
- (*pos) += 4;
- val = value_at_lazy (exp->elts[pc + 1].type,
- (CORE_ADDR) exp->elts[pc + 5].longconst);
- get_no_prettyformat_print_options (&opts);
- value_print (val, stream, &opts);
- }
- else
- {
- fputs_filtered ("{", stream);
- type_print (exp->elts[pc + 1].type, "", stream, 0);
- fputs_filtered ("} ", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- }
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered (")", stream);
- return;
-
- case UNOP_MEMVAL_TYPE:
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered ("(", stream);
- fputs_filtered ("{", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- fputs_filtered ("} ", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- if ((int) prec > (int) PREC_PREFIX)
- fputs_filtered (")", stream);
- return;
-
- case BINOP_ASSIGN_MODIFY:
- opcode = exp->elts[pc + 1].opcode;
- (*pos) += 2;
- myprec = PREC_ASSIGN;
- assoc = 1;
- assign_modify = 1;
- op_str = "???";
- for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
- if (op_print_tab[tem].opcode == opcode)
- {
- op_str = op_print_tab[tem].string;
- break;
- }
- if (op_print_tab[tem].opcode != opcode)
- /* Not found; don't try to keep going because we don't know how
- to interpret further elements. */
- error (_("Invalid expression"));
- break;
-
- /* C++ ops */
-
- case OP_THIS:
- ++(*pos);
- if (exp->language_defn->name_of_this () != NULL)
- fputs_filtered (exp->language_defn->name_of_this (), stream);
- else
- fprintf_styled (stream, metadata_style.style (),
- _("<language %s has no 'this'>"),
- exp->language_defn->name ());
- return;
-
- /* Modula-2 ops */
-
- case MULTI_SUBSCRIPT:
- (*pos) += 2;
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fprintf_unfiltered (stream, " [");
- for (tem = 0; tem < nargs; tem++)
- {
- if (tem != 0)
- fprintf_unfiltered (stream, ", ");
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- }
- fprintf_unfiltered (stream, "]");
- return;
-
- case BINOP_VAL:
- (*pos) += 2;
- fprintf_unfiltered (stream, "VAL(");
- type_print (exp->elts[pc + 1].type, "", stream, 0);
- fprintf_unfiltered (stream, ",");
- print_subexp (exp, pos, stream, PREC_PREFIX);
- fprintf_unfiltered (stream, ")");
- return;
-
- case TYPE_INSTANCE:
- {
- type_instance_flags flags
- = (type_instance_flag_value) longest_to_int (exp->elts[pc + 1].longconst);
- LONGEST count = exp->elts[pc + 2].longconst;
-
- /* The FLAGS. */
- (*pos)++;
- /* The COUNT. */
- (*pos)++;
- fputs_unfiltered ("TypeInstance(", stream);
- while (count-- > 0)
- {
- type_print (exp->elts[(*pos)++].type, "", stream, 0);
- if (count > 0)
- fputs_unfiltered (",", stream);
- }
- fputs_unfiltered (",", stream);
- /* Ending COUNT and ending TYPE_INSTANCE. */
- (*pos) += 2;
- print_subexp (exp, pos, stream, PREC_PREFIX);
-
- if (flags & TYPE_INSTANCE_FLAG_CONST)
- fputs_unfiltered (",const", stream);
- if (flags & TYPE_INSTANCE_FLAG_VOLATILE)
- fputs_unfiltered (",volatile", stream);
-
- fputs_unfiltered (")", stream);
- return;
- }
-
- case OP_RANGE:
- {
- enum range_flag range_flag;
-
- range_flag = (enum range_flag)
- longest_to_int (exp->elts[pc + 1].longconst);
- *pos += 2;
-
- if (range_flag & RANGE_HIGH_BOUND_EXCLUSIVE)
- fputs_filtered ("EXCLUSIVE_", stream);
- fputs_filtered ("RANGE(", stream);
- if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- fputs_filtered ("..", stream);
- if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
- print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
- fputs_filtered (")", stream);
- return;
- }
-
- /* Default ops */
-
- default:
- op_str = "???";
- for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
- if (op_print_tab[tem].opcode == opcode)
- {
- op_str = op_print_tab[tem].string;
- myprec = op_print_tab[tem].precedence;
- assoc = op_print_tab[tem].right_assoc;
- break;
- }
- if (op_print_tab[tem].opcode != opcode)
- /* Not found; don't try to keep going because we don't know how
- to interpret further elements. For example, this happens
- if opcode is OP_TYPE. */
- error (_("Invalid expression"));
- }
-
- /* Note that PREC_BUILTIN will always emit parentheses. */
- if ((int) myprec < (int) prec)
- fputs_filtered ("(", stream);
- if ((int) opcode > (int) BINOP_END)
- {
- if (assoc)
- {
- /* Unary postfix operator. */
- print_subexp (exp, pos, stream, PREC_SUFFIX);
- fputs_filtered (op_str, stream);
- }
- else
- {
- /* Unary prefix operator. */
- fputs_filtered (op_str, stream);
- if (myprec == PREC_BUILTIN_FUNCTION)
- fputs_filtered ("(", stream);
- print_subexp (exp, pos, stream, PREC_PREFIX);
- if (myprec == PREC_BUILTIN_FUNCTION)
- fputs_filtered (")", stream);
- }
- }
- else
- {
- /* Binary operator. */
- /* Print left operand.
- If operator is right-associative,
- increment precedence for this operand. */
- print_subexp (exp, pos, stream,
- (enum precedence) ((int) myprec + assoc));
- /* Print the operator itself. */
- if (assign_modify)
- fprintf_filtered (stream, " %s= ", op_str);
- else if (op_str[0] == ',')
- fprintf_filtered (stream, "%s ", op_str);
- else
- fprintf_filtered (stream, " %s ", op_str);
- /* Print right operand.
- If operator is left-associative,
- increment precedence for this operand. */
- print_subexp (exp, pos, stream,
- (enum precedence) ((int) myprec + !assoc));
- }
-
- if ((int) myprec < (int) prec)
- fputs_filtered (")", stream);
-}
-
-/* Return the operator corresponding to opcode OP as
- a string. NULL indicates that the opcode was not found in the
- current language table. */
-const char *
-op_string (enum exp_opcode op)
-{
- int tem;
- const struct op_print *op_print_tab;
-
- op_print_tab = current_language->opcode_print_table ();
- for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
- if (op_print_tab[tem].opcode == op)
- return op_print_tab[tem].string;
- return NULL;
-}
-
-/* Support for dumping the raw data from expressions in a human readable
- form. */
-
-static int dump_subexp_body (struct expression *exp, struct ui_file *, int);
-
/* Default name for the standard operator OPCODE (i.e., one defined in
the definition of enum exp_opcode). */
}
}
-/* Print a raw dump of expression EXP to STREAM.
- NOTE, if non-NULL, is printed as extra explanatory text. */
-
-void
-dump_raw_expression (struct expression *exp, struct ui_file *stream,
- const char *note)
-{
- int elt;
- char *eltscan;
- int eltsize;
-
- if (exp->op != nullptr)
- return;
-
- fprintf_filtered (stream, "Dump of expression @ ");
- gdb_print_host_address (exp, stream);
- if (note)
- fprintf_filtered (stream, ", %s:", note);
- fprintf_filtered (stream, "\n\tLanguage %s, %d elements, %ld bytes each.\n",
- exp->language_defn->name (), exp->nelts,
- (long) sizeof (union exp_element));
- fprintf_filtered (stream, "\t%5s %20s %16s %s\n", "Index", "Opcode",
- "Hex Value", "String Value");
- for (elt = 0; elt < exp->nelts; elt++)
- {
- fprintf_filtered (stream, "\t%5d ", elt);
-
- const char *opcode_name = op_name (exp->elts[elt].opcode);
- fprintf_filtered (stream, "%20s ", opcode_name);
-
- print_longest (stream, 'd', 0, exp->elts[elt].longconst);
- fprintf_filtered (stream, " ");
-
- for (eltscan = (char *) &exp->elts[elt],
- eltsize = sizeof (union exp_element);
- eltsize-- > 0;
- eltscan++)
- {
- fprintf_filtered (stream, "%c",
- isprint (*eltscan) ? (*eltscan & 0xFF) : '.');
- }
- fprintf_filtered (stream, "\n");
- }
-}
-
-/* Dump the subexpression of prefix expression EXP whose operator is at
- position ELT onto STREAM. Returns the position of the next
- subexpression in EXP. */
-
-int
-dump_subexp (struct expression *exp, struct ui_file *stream, int elt)
-{
- static int indent = 0;
- int i;
-
- fprintf_filtered (stream, "\n");
- fprintf_filtered (stream, "\t%5d ", elt);
-
- for (i = 1; i <= indent; i++)
- fprintf_filtered (stream, " ");
- indent += 2;
-
- fprintf_filtered (stream, "%-20s ", op_name (exp->elts[elt].opcode));
-
- elt = dump_subexp_body (exp, stream, elt);
-
- indent -= 2;
-
- return elt;
-}
-
-/* Dump the operands of prefix expression EXP whose opcode is at
- position ELT onto STREAM. Returns the position of the next
- subexpression in EXP. */
-
-static int
-dump_subexp_body (struct expression *exp, struct ui_file *stream, int elt)
-{
- return exp->language_defn->expression_ops ()->dump_subexp_body (exp, stream,
- elt);
-}
-
-/* See parser-defs.h. */
-
-int
-dump_subexp_body_funcall (struct expression *exp,
- struct ui_file *stream, int elt)
-{
- int nargs = longest_to_int (exp->elts[elt].longconst);
- fprintf_filtered (stream, "Number of args: %d", nargs);
- elt += 2;
-
- for (int i = 1; i <= nargs + 1; i++)
- elt = dump_subexp (exp, stream, elt);
-
- return elt;
-}
-
-/* Default value for subexp_body in exp_descriptor vector. */
-
-int
-dump_subexp_body_standard (struct expression *exp,
- struct ui_file *stream, int elt)
-{
- int opcode = exp->elts[elt++].opcode;
-
- switch (opcode)
- {
- case TERNOP_COND:
- case TERNOP_SLICE:
- elt = dump_subexp (exp, stream, elt);
- /* FALL THROUGH */
- case BINOP_ADD:
- case BINOP_SUB:
- case BINOP_MUL:
- case BINOP_DIV:
- case BINOP_REM:
- case BINOP_MOD:
- case BINOP_LSH:
- case BINOP_RSH:
- case BINOP_LOGICAL_AND:
- case BINOP_LOGICAL_OR:
- case BINOP_BITWISE_AND:
- case BINOP_BITWISE_IOR:
- case BINOP_BITWISE_XOR:
- case BINOP_EQUAL:
- case BINOP_NOTEQUAL:
- case BINOP_LESS:
- case BINOP_GTR:
- case BINOP_LEQ:
- case BINOP_GEQ:
- case BINOP_REPEAT:
- case BINOP_ASSIGN:
- case BINOP_COMMA:
- case BINOP_SUBSCRIPT:
- case BINOP_EXP:
- case BINOP_MIN:
- case BINOP_MAX:
- case BINOP_INTDIV:
- case BINOP_ASSIGN_MODIFY:
- case BINOP_VAL:
- case BINOP_CONCAT:
- case BINOP_END:
- case STRUCTOP_MEMBER:
- case STRUCTOP_MPTR:
- elt = dump_subexp (exp, stream, elt);
- /* FALL THROUGH */
- case UNOP_NEG:
- case UNOP_LOGICAL_NOT:
- case UNOP_COMPLEMENT:
- case UNOP_IND:
- case UNOP_ADDR:
- case UNOP_PREINCREMENT:
- case UNOP_POSTINCREMENT:
- case UNOP_PREDECREMENT:
- case UNOP_POSTDECREMENT:
- case UNOP_SIZEOF:
- case UNOP_ALIGNOF:
- case UNOP_PLUS:
- case UNOP_CAP:
- case UNOP_CHR:
- case UNOP_ORD:
- case UNOP_ABS:
- case UNOP_FLOAT:
- case UNOP_HIGH:
- case UNOP_MAX:
- case UNOP_MIN:
- case UNOP_ODD:
- case UNOP_TRUNC:
- elt = dump_subexp (exp, stream, elt);
- break;
- case OP_LONG:
- fprintf_filtered (stream, "Type @");
- gdb_print_host_address (exp->elts[elt].type, stream);
- fprintf_filtered (stream, " (");
- type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, "), value %ld (0x%lx)",
- (long) exp->elts[elt + 1].longconst,
- (long) exp->elts[elt + 1].longconst);
- elt += 3;
- break;
- case OP_FLOAT:
- fprintf_filtered (stream, "Type @");
- gdb_print_host_address (exp->elts[elt].type, stream);
- fprintf_filtered (stream, " (");
- type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, "), value ");
- print_floating (exp->elts[elt + 1].floatconst,
- exp->elts[elt].type, stream);
- elt += 3;
- break;
- case OP_VAR_VALUE:
- fprintf_filtered (stream, "Block @");
- gdb_print_host_address (exp->elts[elt].block, stream);
- fprintf_filtered (stream, ", symbol @");
- gdb_print_host_address (exp->elts[elt + 1].symbol, stream);
- fprintf_filtered (stream, " (%s)",
- exp->elts[elt + 1].symbol->print_name ());
- elt += 3;
- break;
- case OP_VAR_MSYM_VALUE:
- fprintf_filtered (stream, "Objfile @");
- gdb_print_host_address (exp->elts[elt].objfile, stream);
- fprintf_filtered (stream, ", msymbol @");
- gdb_print_host_address (exp->elts[elt + 1].msymbol, stream);
- fprintf_filtered (stream, " (%s)",
- exp->elts[elt + 1].msymbol->print_name ());
- elt += 3;
- break;
- case OP_VAR_ENTRY_VALUE:
- fprintf_filtered (stream, "Entry value of symbol @");
- gdb_print_host_address (exp->elts[elt].symbol, stream);
- fprintf_filtered (stream, " (%s)",
- exp->elts[elt].symbol->print_name ());
- elt += 2;
- break;
- case OP_LAST:
- fprintf_filtered (stream, "History element %ld",
- (long) exp->elts[elt].longconst);
- elt += 2;
- break;
- case OP_REGISTER:
- fprintf_filtered (stream, "Register $%s", &exp->elts[elt + 1].string);
- elt += 3 + BYTES_TO_EXP_ELEM (exp->elts[elt].longconst + 1);
- break;
- case OP_INTERNALVAR:
- fprintf_filtered (stream, "Internal var @");
- gdb_print_host_address (exp->elts[elt].internalvar, stream);
- fprintf_filtered (stream, " (%s)",
- internalvar_name (exp->elts[elt].internalvar));
- elt += 2;
- break;
- case OP_FUNCALL:
- elt = dump_subexp_body_funcall (exp, stream, elt);
- break;
- case OP_ARRAY:
- {
- int lower, upper;
- int i;
-
- lower = longest_to_int (exp->elts[elt].longconst);
- upper = longest_to_int (exp->elts[elt + 1].longconst);
-
- fprintf_filtered (stream, "Bounds [%d:%d]", lower, upper);
- elt += 3;
-
- for (i = 1; i <= upper - lower + 1; i++)
- elt = dump_subexp (exp, stream, elt);
- }
- break;
- case UNOP_DYNAMIC_CAST:
- case UNOP_REINTERPRET_CAST:
- case UNOP_CAST_TYPE:
- case UNOP_MEMVAL_TYPE:
- fprintf_filtered (stream, " (");
- elt = dump_subexp (exp, stream, elt);
- fprintf_filtered (stream, ")");
- elt = dump_subexp (exp, stream, elt);
- break;
- case UNOP_MEMVAL:
- case UNOP_CAST:
- fprintf_filtered (stream, "Type @");
- gdb_print_host_address (exp->elts[elt].type, stream);
- fprintf_filtered (stream, " (");
- type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, ")");
- elt = dump_subexp (exp, stream, elt + 2);
- break;
- case OP_TYPE:
- fprintf_filtered (stream, "Type @");
- gdb_print_host_address (exp->elts[elt].type, stream);
- fprintf_filtered (stream, " (");
- type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, ")");
- elt += 2;
- break;
- case OP_TYPEOF:
- case OP_DECLTYPE:
- fprintf_filtered (stream, "Typeof (");
- elt = dump_subexp (exp, stream, elt);
- fprintf_filtered (stream, ")");
- break;
- case OP_TYPEID:
- fprintf_filtered (stream, "typeid (");
- elt = dump_subexp (exp, stream, elt);
- fprintf_filtered (stream, ")");
- break;
- case STRUCTOP_STRUCT:
- case STRUCTOP_PTR:
- {
- char *elem_name;
- int len;
-
- len = longest_to_int (exp->elts[elt].longconst);
- elem_name = &exp->elts[elt + 1].string;
-
- fprintf_filtered (stream, "Element name: `%.*s'", len, elem_name);
- elt = dump_subexp (exp, stream, elt + 3 + BYTES_TO_EXP_ELEM (len + 1));
- }
- break;
- case OP_SCOPE:
- {
- char *elem_name;
- int len;
-
- fprintf_filtered (stream, "Type @");
- gdb_print_host_address (exp->elts[elt].type, stream);
- fprintf_filtered (stream, " (");
- type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, ") ");
-
- len = longest_to_int (exp->elts[elt + 1].longconst);
- elem_name = &exp->elts[elt + 2].string;
-
- fprintf_filtered (stream, "Field name: `%.*s'", len, elem_name);
- elt += 4 + BYTES_TO_EXP_ELEM (len + 1);
- }
- break;
-
- case OP_FUNC_STATIC_VAR:
- {
- int len = longest_to_int (exp->elts[elt].longconst);
- const char *var_name = &exp->elts[elt + 1].string;
- fprintf_filtered (stream, "Field name: `%.*s'", len, var_name);
- elt += 3 + BYTES_TO_EXP_ELEM (len + 1);
- }
- break;
-
- case TYPE_INSTANCE:
- {
- type_instance_flags flags
- = (type_instance_flag_value) longest_to_int (exp->elts[elt++].longconst);
- LONGEST len = exp->elts[elt++].longconst;
- fprintf_filtered (stream, "%s TypeInstance: ", plongest (len));
- while (len-- > 0)
- {
- fprintf_filtered (stream, "Type @");
- gdb_print_host_address (exp->elts[elt].type, stream);
- fprintf_filtered (stream, " (");
- type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, ")");
- elt++;
- if (len > 0)
- fputs_filtered (", ", stream);
- }
-
- fprintf_filtered (stream, " Flags: %s (", hex_string (flags));
- bool space = false;
- auto print_one = [&] (const char *mod)
- {
- if (space)
- fputs_filtered (" ", stream);
- space = true;
- fprintf_filtered (stream, "%s", mod);
- };
- if (flags & TYPE_INSTANCE_FLAG_CONST)
- print_one ("const");
- if (flags & TYPE_INSTANCE_FLAG_VOLATILE)
- print_one ("volatile");
- fprintf_filtered (stream, ")");
-
- /* Ending LEN and ending TYPE_INSTANCE. */
- elt += 2;
- elt = dump_subexp (exp, stream, elt);
- }
- break;
- case OP_STRING:
- {
- LONGEST len = exp->elts[elt].longconst;
- LONGEST type = exp->elts[elt + 1].longconst;
-
- fprintf_filtered (stream, "Language-specific string type: %s",
- plongest (type));
-
- /* Skip length. */
- elt += 1;
-
- /* Skip string content. */
- elt += BYTES_TO_EXP_ELEM (len);
-
- /* Skip length and ending OP_STRING. */
- elt += 2;
- }
- break;
- case OP_RANGE:
- {
- enum range_flag range_flag;
-
- range_flag = (enum range_flag)
- longest_to_int (exp->elts[elt].longconst);
- elt += 2;
-
- if (range_flag & RANGE_HIGH_BOUND_EXCLUSIVE)
- fputs_filtered ("Exclusive", stream);
- fputs_filtered ("Range '", stream);
- if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
- fputs_filtered ("EXP", stream);
- fputs_filtered ("..", stream);
- if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
- fputs_filtered ("EXP", stream);
- if (range_flag & RANGE_HAS_STRIDE)
- fputs_filtered (":EXP", stream);
- fputs_filtered ("'", stream);
-
- if (!(range_flag & RANGE_LOW_BOUND_DEFAULT))
- elt = dump_subexp (exp, stream, elt);
- if (!(range_flag & RANGE_HIGH_BOUND_DEFAULT))
- elt = dump_subexp (exp, stream, elt);
- if (range_flag & RANGE_HAS_STRIDE)
- elt = dump_subexp (exp, stream, elt);
- }
- break;
-
- case OP_BOOL:
- {
- bool val = (bool) (exp->elts[elt].longconst);
- fputs_filtered (val ? "TRUE" : "FALSE", stream);
- elt += 2;
- }
- break;
-
- default:
- case OP_NULL:
- case MULTI_SUBSCRIPT:
- case OP_COMPLEX:
- case OP_M2_STRING:
- case OP_THIS:
- case OP_NAME:
- fprintf_filtered (stream, "Unknown format");
- }
-
- return elt;
-}
-
void
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,
- (long) sizeof (union exp_element));
- fputs_filtered ("\n", stream);
-
- for (elt = 0; elt < exp->nelts;)
- elt = dump_subexp (exp, stream, elt);
- fputs_filtered ("\n", stream);
+ exp->op->dump (stream, 0);
}
namespace expr
DEF_ENUM_FLAGS_TYPE (enum innermost_block_tracker_type,
innermost_block_tracker_types);
-/* Definitions for saved C expressions. */
-
-/* An expression is represented as a vector of union exp_element's.
- Each exp_element is an opcode, except that some opcodes cause
- the following exp_element to be treated as a long or double constant
- or as a variable. The opcodes are obeyed, using a stack for temporaries.
- The value is left on the temporary stack at the end. */
-
-/* When it is necessary to include a string,
- it can occupy as many exp_elements as it needs.
- We find the length of the string using strlen,
- divide to find out how many exp_elements are used up,
- and skip that many. Strings, like numbers, are indicated
- by the preceding opcode. */
-
enum exp_opcode : uint8_t
{
#define OP(name) name ,
}
-union exp_element
- {
- enum exp_opcode opcode;
- struct symbol *symbol;
- struct minimal_symbol *msymbol;
- LONGEST longconst;
- gdb_byte floatconst[16];
- /* Really sizeof (union exp_element) characters (or less for the last
- element of a string). */
- char string;
- struct type *type;
- struct internalvar *internalvar;
- const struct block *block;
- struct objfile *objfile;
- };
-
struct expression
{
- expression (const struct language_defn *, struct gdbarch *, size_t);
+ expression (const struct language_defn *, struct gdbarch *);
~expression ();
DISABLE_COPY_AND_ASSIGN (expression);
- void resize (size_t);
-
/* Return the opcode for the outermost sub-expression of this
expression. */
enum exp_opcode first_opcode () const
{
- if (op != nullptr)
- return op->opcode ();
- return elts[0].opcode;
+ return op->opcode ();
}
/* Evaluate the expression. EXPECT_TYPE is the context type of the
/* Architecture it was parsed in. */
struct gdbarch *gdbarch;
expr::operation_up op;
- int nelts = 0;
- union exp_element *elts;
};
typedef std::unique_ptr<expression> expression_up;
-/* Macros for converting between number of expression elements and bytes
- to store that many expression elements. */
-
-#define EXP_ELEM_TO_BYTES(elements) \
- ((elements) * sizeof (union exp_element))
-#define BYTES_TO_EXP_ELEM(bytes) \
- (((bytes) + sizeof (union exp_element) - 1) / sizeof (union exp_element))
-
/* From parse.c */
class innermost_block_tracker;
/* From eval.c */
-extern struct value *evaluate_subexp_standard
- (struct type *, struct expression *, int *, enum noside);
-
/* Evaluate a function call. The function to be called is in CALLEE and
the arguments passed to the function are in ARGVEC.
FUNCTION_NAME is the name of the function, if known.
/* From expprint.c */
-extern void print_expression (struct expression *, struct ui_file *);
-
extern const char *op_name (enum exp_opcode opcode);
-extern const char *op_string (enum exp_opcode);
-
-extern void dump_raw_expression (struct expression *,
- struct ui_file *, const char *);
extern void dump_prefix_expression (struct expression *, struct ui_file *);
/* In an OP_RANGE expression, either bound could be empty, indicating
\f
-/* Table of operators and their precedences for printing expressions. */
-
-const struct op_print f_language::op_print_tab[] =
-{
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"+", UNOP_PLUS, PREC_PREFIX, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"DIV", BINOP_INTDIV, PREC_MUL, 0},
- {"MOD", BINOP_REM, PREC_MUL, 0},
- {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {".OR.", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {".AND.", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {".NOT.", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {".EQ.", BINOP_EQUAL, PREC_EQUAL, 0},
- {".NE.", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {".LE.", BINOP_LEQ, PREC_ORDER, 0},
- {".GE.", BINOP_GEQ, PREC_ORDER, 0},
- {".GT.", BINOP_GTR, PREC_ORDER, 0},
- {".LT.", BINOP_LESS, PREC_ORDER, 0},
- {"**", UNOP_IND, PREC_PREFIX, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {NULL, OP_NULL, PREC_REPEAT, 0}
-};
-\f
-
/* A helper function for the "bound" intrinsics that checks that TYPE
is an array. LBOUND_P is true for lower bound; this is used for
the error message, if any. */
enum array_ordering array_ordering () const override
{ return array_column_major; }
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return op_print_tab; }
-
protected:
/* See language.h. */
(const lookup_name_info &lookup_name) const override;
private:
- /* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
-
- static const struct op_print op_print_tab[];
-
/* Return the encoding that should be used for the character type
TYPE. */
return NULL;
}
-/* See go-lang.h.
-
- TODO(dje): &^ ? */
-
-const struct op_print go_language::op_print_tab[] =
-{
- {",", BINOP_COMMA, PREC_COMMA, 0},
- {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"==", BINOP_EQUAL, PREC_EQUAL, 0},
- {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {">>", BINOP_RSH, PREC_SHIFT, 0},
- {"<<", BINOP_LSH, PREC_SHIFT, 0},
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"%", BINOP_REM, PREC_MUL, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"^", UNOP_COMPLEMENT, PREC_PREFIX, 0},
- {"*", UNOP_IND, PREC_PREFIX, 0},
- {"&", UNOP_ADDR, PREC_PREFIX, 0},
- {"unsafe.Sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
- {"++", UNOP_POSTINCREMENT, PREC_SUFFIX, 0},
- {"--", UNOP_POSTDECREMENT, PREC_SUFFIX, 0},
- {NULL, OP_NULL, PREC_SUFFIX, 0}
-};
-
/* See language.h. */
void
bool store_sym_names_in_linkage_form_p () const override
{ return true; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return op_print_tab; }
-
-private:
-
- /* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
-
- static const struct op_print op_print_tab[];
-
};
#endif /* !defined (GO_LANG_H) */
return &c_varobj_ops;
}
-/* See language.h. */
-
-const struct exp_descriptor *
-language_defn::expression_ops () const
-{
- return &exp_descriptor_standard;
-}
-
/* Parent class for both the "auto" and "unknown" languages. These two
pseudo-languages are very similar so merging their implementations like
this makes sense. */
const char *name_of_this () const override
{ return "this"; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- {
- static const struct op_print unk_op_print_tab[] =
- {
- {NULL, OP_NULL, PREC_NULL, 0}
- };
-
- return unk_op_print_tab;
- }
};
/* Class representing the fake "auto" language. */
virtual int parser (struct parser_state *ps) const;
- /* Given an expression *EXPP created by prefixifying the result of
- la_parser, perform any remaining processing necessary to complete its
- translation. *EXPP may change; la_post_parser is responsible for
- releasing its previous contents, if necessary. */
-
- virtual void post_parser (expression_up *expp, struct parser_state *ps)
- const
- {
- /* By default the post-parser does nothing. */
- }
-
/* Print the character CH (of type CHTYPE) on STREAM as part of the
contents of a literal string whose delimiter is QUOTER. */
virtual const struct lang_varobj_ops *varobj_ops () const;
- /* Definitions related to expression printing, prefixifying, and
- dumping. */
-
- virtual const struct exp_descriptor *expression_ops () const;
-
- /* Table for printing expressions. */
-
- virtual const struct op_print *opcode_print_table () const = 0;
-
protected:
/* This is the overridable part of the GET_SYMBOL_NAME_MATCHER method.
\f
-/* Table of operators and their precedences for printing expressions. */
-
-const struct op_print m2_language::op_print_tab[] =
-{
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"+", UNOP_PLUS, PREC_PREFIX, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"DIV", BINOP_INTDIV, PREC_MUL, 0},
- {"MOD", BINOP_REM, PREC_MUL, 0},
- {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"=", BINOP_EQUAL, PREC_EQUAL, 0},
- {"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {"^", UNOP_IND, PREC_PREFIX, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"CAP", UNOP_CAP, PREC_BUILTIN_FUNCTION, 0},
- {"CHR", UNOP_CHR, PREC_BUILTIN_FUNCTION, 0},
- {"ORD", UNOP_ORD, PREC_BUILTIN_FUNCTION, 0},
- {"FLOAT", UNOP_FLOAT, PREC_BUILTIN_FUNCTION, 0},
- {"HIGH", UNOP_HIGH, PREC_BUILTIN_FUNCTION, 0},
- {"MAX", UNOP_MAX, PREC_BUILTIN_FUNCTION, 0},
- {"MIN", UNOP_MIN, PREC_BUILTIN_FUNCTION, 0},
- {"ODD", UNOP_ODD, PREC_BUILTIN_FUNCTION, 0},
- {"TRUNC", UNOP_TRUNC, PREC_BUILTIN_FUNCTION, 0},
- {NULL, OP_NULL, PREC_BUILTIN_FUNCTION, 0}
-};
-\f
-
/* Single instance of the M2 language. */
static m2_language m2_language_defn;
bool range_checking_on_by_default () const override
{ return true; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return op_print_tab; }
-
-private:
- /* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
- static const struct op_print op_print_tab[];
};
#endif /* M2_LANG_H */
return NULL; /* Not an objc mangled name. */
}
-
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-
-static const struct op_print objc_op_print_tab[] =
- {
- {",", BINOP_COMMA, PREC_COMMA, 0},
- {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"==", BINOP_EQUAL, PREC_EQUAL, 0},
- {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {">>", BINOP_RSH, PREC_SHIFT, 0},
- {"<<", BINOP_LSH, PREC_SHIFT, 0},
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"%", BINOP_REM, PREC_MUL, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
- {"*", UNOP_IND, PREC_PREFIX, 0},
- {"&", UNOP_ADDR, PREC_PREFIX, 0},
- {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
- {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
- {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
- {NULL, OP_NULL, PREC_NULL, 0}
-};
-
/* Class representing the Objective-C language. */
class objc_language : public language_defn
enum macro_expansion macro_expansion () const override
{ return macro_expansion_c; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return objc_op_print_tab; }
};
/* Single instance of the class representing the Objective-C language. */
enum macro_expansion macro_expansion () const override
{ return macro_expansion_c; }
-
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return c_op_print_tab; }
};
/* Single instance of the OpenCL language class. */
\f
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-
-const struct op_print pascal_language::op_print_tab[] =
-{
- {",", BINOP_COMMA, PREC_COMMA, 0},
- {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"or", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"xor", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"and", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"=", BINOP_EQUAL, PREC_EQUAL, 0},
- {"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {"shr", BINOP_RSH, PREC_SHIFT, 0},
- {"shl", BINOP_LSH, PREC_SHIFT, 0},
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"div", BINOP_INTDIV, PREC_MUL, 0},
- {"mod", BINOP_REM, PREC_MUL, 0},
- {"@", BINOP_REPEAT, PREC_REPEAT, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"not", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"^", UNOP_IND, PREC_SUFFIX, 1},
- {"@", UNOP_ADDR, PREC_PREFIX, 0},
- {"sizeof", UNOP_SIZEOF, PREC_PREFIX, 0},
- {NULL, OP_NULL, PREC_PREFIX, 0}
-};
-\f
-
/* See language.h. */
void pascal_language::language_arch_info
bool range_checking_on_by_default () const override
{ return true; }
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return op_print_tab; }
-
private:
- /* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
-
- static const struct op_print op_print_tab[];
-
/* Print the character C on STREAM as part of the contents of a literal
string. IN_QUOTES is reset to 0 if a char is written with #4 notation. */
#include "gdbsupport/gdb_optional.h"
#include "c-exp.h"
-/* Standard set of definitions for printing, dumping, prefixifying,
- * and evaluating expressions. */
-
-const struct exp_descriptor exp_descriptor_standard =
- {
- print_subexp_standard,
- operator_length_standard,
- operator_check_standard,
- dump_subexp_body_standard,
- evaluate_subexp_standard
- };
-\f
static unsigned int expressiondebug = 0;
static void
show_expressiondebug (struct ui_file *file, int from_tty,
}
-static int prefixify_subexp (struct expression *, struct expression *, int,
- int, int);
-
static expression_up parse_exp_in_context (const char **, CORE_ADDR,
const struct block *, int,
- bool, int *,
- innermost_block_tracker *,
+ bool, innermost_block_tracker *,
expr_completion_state *);
-static void increase_expout_size (struct expr_builder *ps, size_t lenelt);
-
-
/* Documented at it's declaration. */
void
expr_builder::expr_builder (const struct language_defn *lang,
struct gdbarch *gdbarch)
- : expout_size (10),
- expout (new expression (lang, gdbarch, expout_size)),
- expout_ptr (0)
+ : expout (new expression (lang, gdbarch))
{
}
expression_up
expr_builder::release ()
{
- /* Record the actual number of expression elements, and then
- reallocate the expression memory so that we free up any
- excess elements. */
-
- expout->nelts = expout_ptr;
- expout->resize (expout_ptr);
-
return std::move (expout);
}
-expression::expression (const struct language_defn *lang, struct gdbarch *arch,
- size_t n)
+expression::expression (const struct language_defn *lang, struct gdbarch *arch)
: language_defn (lang),
- gdbarch (arch),
- elts (nullptr)
+ gdbarch (arch)
{
- resize (n);
}
expression::~expression ()
{
- xfree (elts);
-}
-
-void
-expression::resize (size_t n)
-{
- elts = XRESIZEVAR (union exp_element, elts, EXP_ELEM_TO_BYTES (n));
-}
-
-/* This page contains the functions for adding data to the struct expression
- being constructed. */
-
-/* Add one element to the end of the expression. */
-
-/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
- a register through here. */
-
-static void
-write_exp_elt (struct expr_builder *ps, const union exp_element *expelt)
-{
- if (ps->expout_ptr >= ps->expout_size)
- {
- ps->expout_size *= 2;
- ps->expout->resize (ps->expout_size);
- }
- ps->expout->elts[ps->expout_ptr++] = *expelt;
-}
-
-void
-write_exp_elt_opcode (struct expr_builder *ps, enum exp_opcode expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.opcode = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_sym (struct expr_builder *ps, struct symbol *expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.symbol = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-static void
-write_exp_elt_msym (struct expr_builder *ps, minimal_symbol *expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.msymbol = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_block (struct expr_builder *ps, const struct block *b)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.block = b;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_objfile (struct expr_builder *ps, struct objfile *objfile)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.objfile = objfile;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_longcst (struct expr_builder *ps, LONGEST expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.longconst = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_floatcst (struct expr_builder *ps, const gdb_byte expelt[16])
-{
- union exp_element tmp;
- int index;
-
- for (index = 0; index < 16; index++)
- tmp.floatconst[index] = expelt[index];
-
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_type (struct expr_builder *ps, struct type *expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.type = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_intern (struct expr_builder *ps, struct internalvar *expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.internalvar = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-/* Add a string constant to the end of the expression.
-
- String constants are stored by first writing an expression element
- that contains the length of the string, then stuffing the string
- constant itself into however many expression elements are needed
- to hold it, and then writing another expression element that contains
- the length of the string. I.e. an expression element at each end of
- the string records the string length, so you can skip over the
- expression elements containing the actual string bytes from either
- end of the string. Note that this also allows gdb to handle
- strings with embedded null bytes, as is required for some languages.
-
- Don't be fooled by the fact that the string is null byte terminated,
- this is strictly for the convenience of debugging gdb itself.
- Gdb does not depend up the string being null terminated, since the
- actual length is recorded in expression elements at each end of the
- string. The null byte is taken into consideration when computing how
- many expression elements are required to hold the string constant, of
- course. */
-
-
-void
-write_exp_string (struct expr_builder *ps, struct stoken str)
-{
- int len = str.length;
- size_t lenelt;
- char *strdata;
-
- /* Compute the number of expression elements required to hold the string
- (including a null byte terminator), along with one expression element
- at each end to record the actual string length (not including the
- null byte terminator). */
-
- lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1);
-
- increase_expout_size (ps, lenelt);
-
- /* Write the leading length expression element (which advances the current
- expression element index), then write the string constant followed by a
- terminating null byte, and then write the trailing length expression
- element. */
-
- write_exp_elt_longcst (ps, (LONGEST) len);
- strdata = (char *) &ps->expout->elts[ps->expout_ptr];
- memcpy (strdata, str.ptr, len);
- *(strdata + len) = '\0';
- ps->expout_ptr += lenelt - 2;
- write_exp_elt_longcst (ps, (LONGEST) len);
-}
-
-/* Add a vector of string constants to the end of the expression.
-
- This adds an OP_STRING operation, but encodes the contents
- differently from write_exp_string. The language is expected to
- handle evaluation of this expression itself.
-
- After the usual OP_STRING header, TYPE is written into the
- expression as a long constant. The interpretation of this field is
- up to the language evaluator.
-
- Next, each string in VEC is written. The length is written as a
- long constant, followed by the contents of the string. */
-
-void
-write_exp_string_vector (struct expr_builder *ps, int type,
- struct stoken_vector *vec)
-{
- int i, len;
- size_t n_slots;
-
- /* Compute the size. We compute the size in number of slots to
- avoid issues with string padding. */
- n_slots = 0;
- for (i = 0; i < vec->len; ++i)
- {
- /* One slot for the length of this element, plus the number of
- slots needed for this string. */
- n_slots += 1 + BYTES_TO_EXP_ELEM (vec->tokens[i].length);
- }
-
- /* One more slot for the type of the string. */
- ++n_slots;
-
- /* Now compute a phony string length. */
- len = EXP_ELEM_TO_BYTES (n_slots) - 1;
-
- n_slots += 4;
- increase_expout_size (ps, n_slots);
-
- write_exp_elt_opcode (ps, OP_STRING);
- write_exp_elt_longcst (ps, len);
- write_exp_elt_longcst (ps, type);
-
- for (i = 0; i < vec->len; ++i)
- {
- write_exp_elt_longcst (ps, vec->tokens[i].length);
- memcpy (&ps->expout->elts[ps->expout_ptr], vec->tokens[i].ptr,
- vec->tokens[i].length);
- ps->expout_ptr += BYTES_TO_EXP_ELEM (vec->tokens[i].length);
- }
-
- write_exp_elt_longcst (ps, len);
- write_exp_elt_opcode (ps, OP_STRING);
-}
-
-/* Add a bitstring constant to the end of the expression.
-
- Bitstring constants are stored by first writing an expression element
- that contains the length of the bitstring (in bits), then stuffing the
- bitstring constant itself into however many expression elements are
- needed to hold it, and then writing another expression element that
- contains the length of the bitstring. I.e. an expression element at
- each end of the bitstring records the bitstring length, so you can skip
- over the expression elements containing the actual bitstring bytes from
- either end of the bitstring. */
-
-void
-write_exp_bitstring (struct expr_builder *ps, struct stoken str)
-{
- int bits = str.length; /* length in bits */
- int len = (bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
- size_t lenelt;
- char *strdata;
-
- /* Compute the number of expression elements required to hold the bitstring,
- along with one expression element at each end to record the actual
- bitstring length in bits. */
-
- lenelt = 2 + BYTES_TO_EXP_ELEM (len);
-
- increase_expout_size (ps, lenelt);
-
- /* Write the leading length expression element (which advances the current
- expression element index), then write the bitstring constant, and then
- write the trailing length expression element. */
-
- write_exp_elt_longcst (ps, (LONGEST) bits);
- strdata = (char *) &ps->expout->elts[ps->expout_ptr];
- memcpy (strdata, str.ptr, len);
- ps->expout_ptr += lenelt - 2;
- write_exp_elt_longcst (ps, (LONGEST) bits);
}
/* Return the type of MSYMBOL, a minimal symbol of OBJFILE. If
}
}
-/* Add the appropriate elements for a minimal symbol to the end of
- the expression. */
-
-void
-write_exp_msymbol (struct expr_builder *ps,
- struct bound_minimal_symbol bound_msym)
-{
- write_exp_elt_opcode (ps, OP_VAR_MSYM_VALUE);
- write_exp_elt_objfile (ps, bound_msym.objfile);
- write_exp_elt_msym (ps, bound_msym.minsym);
- write_exp_elt_opcode (ps, OP_VAR_MSYM_VALUE);
-}
-
-/* See parser-defs.h. */
-
-void
-parser_state::mark_struct_expression ()
-{
- gdb_assert (parse_completion
- && (m_completion_state.expout_tag_completion_type
- == TYPE_CODE_UNDEF)
- && m_completion_state.expout_last_op == nullptr);
- m_completion_state.expout_last_struct = expout_ptr;
-}
-
/* See parser-defs.h. */
void
{
gdb_assert (parse_completion
&& (m_completion_state.expout_tag_completion_type
- == TYPE_CODE_UNDEF)
- && m_completion_state.expout_last_struct == -1);
+ == TYPE_CODE_UNDEF));
m_completion_state.expout_last_op = op;
}
&& (m_completion_state.expout_tag_completion_type
== TYPE_CODE_UNDEF)
&& m_completion_state.expout_completion_name == NULL
- && m_completion_state.expout_last_struct == -1
&& m_completion_state.expout_last_op == nullptr);
gdb_assert (tag == TYPE_CODE_UNION
|| tag == TYPE_CODE_STRUCT
}
\f
-/* Recognize tokens that start with '$'. These include:
-
- $regname A native register name or a "standard
- register name".
-
- $variable A convenience variable with a name chosen
- by the user.
-
- $digits Value history with index <digits>, starting
- from the first value which has index 1.
-
- $$digits Value history with index <digits> relative
- to the last value. I.e. $$0 is the last
- value, $$1 is the one previous to that, $$2
- is the one previous to $$1, etc.
-
- $ | $0 | $$0 The last value in the value history.
-
- $$ An abbreviation for the second to the last
- value in the value history, I.e. $$1 */
-
-void
-write_dollar_variable (struct parser_state *ps, struct stoken str)
-{
- struct block_symbol sym;
- struct bound_minimal_symbol msym;
- struct internalvar *isym = NULL;
- std::string copy;
-
- /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
- and $$digits (equivalent to $<-digits> if you could type that). */
-
- int negate = 0;
- int i = 1;
- /* Double dollar means negate the number and add -1 as well.
- Thus $$ alone means -1. */
- if (str.length >= 2 && str.ptr[1] == '$')
- {
- negate = 1;
- i = 2;
- }
- if (i == str.length)
- {
- /* Just dollars (one or two). */
- i = -negate;
- goto handle_last;
- }
- /* Is the rest of the token digits? */
- for (; i < str.length; i++)
- if (!(str.ptr[i] >= '0' && str.ptr[i] <= '9'))
- break;
- if (i == str.length)
- {
- i = atoi (str.ptr + 1 + negate);
- if (negate)
- i = -i;
- goto handle_last;
- }
-
- /* Handle tokens that refer to machine registers:
- $ followed by a register name. */
- i = user_reg_map_name_to_regnum (ps->gdbarch (),
- str.ptr + 1, str.length - 1);
- if (i >= 0)
- goto handle_register;
-
- /* Any names starting with $ are probably debugger internal variables. */
-
- copy = copy_name (str);
- isym = lookup_only_internalvar (copy.c_str () + 1);
- if (isym)
- {
- write_exp_elt_opcode (ps, OP_INTERNALVAR);
- write_exp_elt_intern (ps, isym);
- write_exp_elt_opcode (ps, OP_INTERNALVAR);
- return;
- }
-
- /* On some systems, such as HP-UX and hppa-linux, certain system routines
- have names beginning with $ or $$. Check for those, first. */
-
- sym = lookup_symbol (copy.c_str (), NULL, VAR_DOMAIN, NULL);
- if (sym.symbol)
- {
- write_exp_elt_opcode (ps, OP_VAR_VALUE);
- write_exp_elt_block (ps, sym.block);
- write_exp_elt_sym (ps, sym.symbol);
- write_exp_elt_opcode (ps, OP_VAR_VALUE);
- return;
- }
- msym = lookup_bound_minimal_symbol (copy.c_str ());
- if (msym.minsym)
- {
- write_exp_msymbol (ps, msym);
- return;
- }
-
- /* Any other names are assumed to be debugger internal variables. */
-
- write_exp_elt_opcode (ps, OP_INTERNALVAR);
- write_exp_elt_intern (ps, create_internalvar (copy.c_str () + 1));
- write_exp_elt_opcode (ps, OP_INTERNALVAR);
- return;
-handle_last:
- write_exp_elt_opcode (ps, OP_LAST);
- write_exp_elt_longcst (ps, (LONGEST) i);
- write_exp_elt_opcode (ps, OP_LAST);
- return;
-handle_register:
- write_exp_elt_opcode (ps, OP_REGISTER);
- str.length--;
- str.ptr++;
- write_exp_string (ps, str);
- write_exp_elt_opcode (ps, OP_REGISTER);
- ps->block_tracker->update (ps->expression_context_block,
- INNERMOST_BLOCK_FOR_REGISTERS);
- return;
-}
-
-/* See parser-defs.h. */
-
-void
-write_exp_symbol_reference (struct parser_state *pstate, const char *name,
- struct block_symbol sym)
-{
- if (sym.symbol != nullptr)
- {
- if (symbol_read_needs_frame (sym.symbol))
- pstate->block_tracker->update (sym);
- write_exp_elt_opcode (pstate, OP_VAR_VALUE);
- write_exp_elt_block (pstate, sym.block);
- write_exp_elt_sym (pstate, sym.symbol);
- write_exp_elt_opcode (pstate, OP_VAR_VALUE);
- }
- else
- {
- struct bound_minimal_symbol msymbol = lookup_bound_minimal_symbol (name);
- if (msymbol.minsym != NULL)
- write_exp_msymbol (pstate, msymbol);
- else if (!have_full_symbols () && !have_partial_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command."));
- else
- error (_("No symbol \"%s\" in current context."), name);
- }
-}
const char *
find_template_name_end (const char *p)
}
\f
-/* See comments on parser-defs.h. */
-
-int
-prefixify_expression (struct expression *expr, int last_struct)
-{
- gdb_assert (expr->nelts > 0);
- int len = EXP_ELEM_TO_BYTES (expr->nelts);
- struct expression temp (expr->language_defn, expr->gdbarch, expr->nelts);
- int inpos = expr->nelts, outpos = 0;
-
- /* Copy the original expression into temp. */
- memcpy (temp.elts, expr->elts, len);
-
- return prefixify_subexp (&temp, expr, inpos, outpos, last_struct);
-}
-
-/* Return the number of exp_elements in the postfix subexpression
- of EXPR whose operator is at index ENDPOS - 1 in EXPR. */
-
-static int
-length_of_subexp (struct expression *expr, int endpos)
-{
- int oplen, args;
-
- operator_length (expr, endpos, &oplen, &args);
-
- while (args > 0)
- {
- oplen += length_of_subexp (expr, endpos - oplen);
- args--;
- }
-
- return oplen;
-}
-
-/* Sets *OPLENP to the length of the operator whose (last) index is
- ENDPOS - 1 in EXPR, and sets *ARGSP to the number of arguments that
- operator takes. */
-
-void
-operator_length (const struct expression *expr, int endpos, int *oplenp,
- int *argsp)
-{
- expr->language_defn->expression_ops ()->operator_length (expr, endpos,
- oplenp, argsp);
-}
-
-/* Default value for operator_length in exp_descriptor vectors. */
-
-void
-operator_length_standard (const struct expression *expr, int endpos,
- int *oplenp, int *argsp)
-{
- int oplen = 1;
- int args = 0;
- enum range_flag range_flag;
- int i;
-
- if (endpos < 1)
- error (_("?error in operator_length_standard"));
-
- i = (int) expr->elts[endpos - 1].opcode;
-
- switch (i)
- {
- /* C++ */
- case OP_SCOPE:
- oplen = longest_to_int (expr->elts[endpos - 2].longconst);
- oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
- break;
-
- case OP_LONG:
- case OP_FLOAT:
- case OP_VAR_VALUE:
- case OP_VAR_MSYM_VALUE:
- oplen = 4;
- break;
-
- case OP_FUNC_STATIC_VAR:
- oplen = longest_to_int (expr->elts[endpos - 2].longconst);
- oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
- args = 1;
- break;
-
- case OP_TYPE:
- case OP_BOOL:
- case OP_LAST:
- case OP_INTERNALVAR:
- case OP_VAR_ENTRY_VALUE:
- oplen = 3;
- break;
-
- case OP_COMPLEX:
- oplen = 3;
- args = 2;
- break;
-
- case OP_FUNCALL:
- oplen = 3;
- args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
- break;
-
- case TYPE_INSTANCE:
- oplen = 5 + longest_to_int (expr->elts[endpos - 2].longconst);
- args = 1;
- break;
-
- case OP_OBJC_MSGCALL: /* Objective C message (method) call. */
- oplen = 4;
- args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
- break;
-
- case UNOP_MAX:
- case UNOP_MIN:
- oplen = 3;
- break;
-
- case UNOP_CAST_TYPE:
- case UNOP_DYNAMIC_CAST:
- case UNOP_REINTERPRET_CAST:
- case UNOP_MEMVAL_TYPE:
- oplen = 1;
- args = 2;
- break;
-
- case BINOP_VAL:
- case UNOP_CAST:
- case UNOP_MEMVAL:
- oplen = 3;
- args = 1;
- break;
-
- case UNOP_ABS:
- case UNOP_CAP:
- case UNOP_CHR:
- case UNOP_FLOAT:
- case UNOP_HIGH:
- case UNOP_ODD:
- case UNOP_ORD:
- case UNOP_TRUNC:
- case OP_TYPEOF:
- case OP_DECLTYPE:
- case OP_TYPEID:
- oplen = 1;
- args = 1;
- break;
-
- case OP_ADL_FUNC:
- oplen = longest_to_int (expr->elts[endpos - 2].longconst);
- oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
- oplen++;
- oplen++;
- break;
-
- case STRUCTOP_STRUCT:
- case STRUCTOP_PTR:
- args = 1;
- /* fall through */
- case OP_REGISTER:
- case OP_M2_STRING:
- case OP_STRING:
- case OP_OBJC_NSSTRING: /* Objective C Foundation Class
- NSString constant. */
- case OP_OBJC_SELECTOR: /* Objective C "@selector" pseudo-op. */
- case OP_NAME:
- oplen = longest_to_int (expr->elts[endpos - 2].longconst);
- oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
- break;
-
- case OP_ARRAY:
- oplen = 4;
- args = longest_to_int (expr->elts[endpos - 2].longconst);
- args -= longest_to_int (expr->elts[endpos - 3].longconst);
- args += 1;
- break;
-
- case TERNOP_COND:
- case TERNOP_SLICE:
- args = 3;
- break;
-
- /* Modula-2 */
- case MULTI_SUBSCRIPT:
- oplen = 3;
- args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
- break;
-
- case BINOP_ASSIGN_MODIFY:
- oplen = 3;
- args = 2;
- break;
-
- /* C++ */
- case OP_THIS:
- oplen = 2;
- break;
-
- case OP_RANGE:
- oplen = 3;
- range_flag = (enum range_flag)
- longest_to_int (expr->elts[endpos - 2].longconst);
-
- /* Assume the range has 2 arguments (low bound and high bound), then
- reduce the argument count if any bounds are set to default. */
- args = 2;
- if (range_flag & RANGE_HAS_STRIDE)
- ++args;
- if (range_flag & RANGE_LOW_BOUND_DEFAULT)
- --args;
- if (range_flag & RANGE_HIGH_BOUND_DEFAULT)
- --args;
-
- break;
-
- default:
- args = 1 + (i < (int) BINOP_END);
- }
-
- *oplenp = oplen;
- *argsp = args;
-}
-
-/* Copy the subexpression ending just before index INEND in INEXPR
- into OUTEXPR, starting at index OUTBEG.
- In the process, convert it from suffix to prefix form.
- If LAST_STRUCT is -1, then this function always returns -1.
- Otherwise, it returns the index of the subexpression which is the
- left-hand-side of the expression at LAST_STRUCT. */
-
-static int
-prefixify_subexp (struct expression *inexpr,
- struct expression *outexpr, int inend, int outbeg,
- int last_struct)
-{
- int oplen;
- int args;
- int i;
- int *arglens;
- int result = -1;
-
- operator_length (inexpr, inend, &oplen, &args);
-
- /* Copy the final operator itself, from the end of the input
- to the beginning of the output. */
- inend -= oplen;
- memcpy (&outexpr->elts[outbeg], &inexpr->elts[inend],
- EXP_ELEM_TO_BYTES (oplen));
- outbeg += oplen;
-
- if (last_struct == inend)
- result = outbeg - oplen;
-
- /* Find the lengths of the arg subexpressions. */
- arglens = (int *) alloca (args * sizeof (int));
- for (i = args - 1; i >= 0; i--)
- {
- oplen = length_of_subexp (inexpr, inend);
- arglens[i] = oplen;
- inend -= oplen;
- }
-
- /* Now copy each subexpression, preserving the order of
- the subexpressions, but prefixifying each one.
- In this loop, inend starts at the beginning of
- the expression this level is working on
- and marches forward over the arguments.
- outbeg does similarly in the output. */
- for (i = 0; i < args; i++)
- {
- int r;
-
- oplen = arglens[i];
- inend += oplen;
- r = prefixify_subexp (inexpr, outexpr, inend, outbeg, last_struct);
- if (r != -1)
- {
- /* Return immediately. We probably have only parsed a
- partial expression, so we don't want to try to reverse
- the other operands. */
- return r;
- }
- outbeg += oplen;
- }
-
- return result;
-}
-\f
/* Read an expression from the string *STRINGPTR points to,
parse it, and return a pointer to a struct expression that we malloc.
Use block BLOCK as the lexical context for variable names;
parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
int comma, innermost_block_tracker *tracker)
{
- return parse_exp_in_context (stringptr, pc, block, comma, false, NULL,
+ return parse_exp_in_context (stringptr, pc, block, comma, false,
tracker, nullptr);
}
/* As for parse_exp_1, except that if VOID_CONTEXT_P, then
- no value is expected from the expression.
- OUT_SUBEXP is set when attempting to complete a field name; in this
- case it is set to the index of the subexpression on the
- left-hand-side of the struct op. If not doing such completion, it
- is left untouched. */
+ no value is expected from the expression. */
static expression_up
parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
const struct block *block,
- int comma, bool void_context_p, int *out_subexp,
+ int comma, bool void_context_p,
innermost_block_tracker *tracker,
expr_completion_state *cstate)
{
/* 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->op == nullptr && ps.expout_ptr == 0))
+ if (! ps.parse_completion || ps.expout->op == nullptr)
throw;
}
- /* We have to operate on an "expression *", due to la_post_parser,
- which explains this funny-looking double release. */
expression_up result = ps.release ();
-
- /* Convert expression from postfix form as generated by yacc
- parser, to a prefix form. */
-
- if (expressiondebug)
- dump_raw_expression (result.get (), gdb_stdlog,
- "before conversion to prefix form");
-
- 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);
- }
- else
- result->op->set_outermost ();
+ result->op->set_outermost ();
if (expressiondebug)
dump_prefix_expression (result.get (), gdb_stdlog);
bool void_context_p)
{
expression_up exp = parse_exp_in_context (&string, 0, nullptr, 0,
- void_context_p, nullptr,
+ void_context_p,
tracker, nullptr);
if (*string)
error (_("Junk after end of expression."));
enum type_code *code)
{
expression_up exp;
- struct value *val;
- int subexp;
expr_completion_state cstate;
try
{
- exp = parse_exp_in_context (&string, 0, 0, 0, false, &subexp,
- nullptr, &cstate);
+ exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, &cstate);
}
catch (const gdb_exception_error &except)
{
return NULL;
}
- if (cstate.expout_last_op != nullptr)
- {
- expr::structop_base_operation *op = cstate.expout_last_op;
- const std::string &fld = op->get_string ();
- *name = make_unique_xstrdup (fld.c_str ());
- return value_type (op->evaluate_lhs (exp.get ()));
- }
+ if (cstate.expout_last_op == nullptr)
+ return nullptr;
- if (cstate.expout_last_struct == -1)
- return NULL;
-
- const char *fieldname = extract_field_op (exp.get (), &subexp);
- if (fieldname == NULL)
- {
- name->reset ();
- return NULL;
- }
-
- name->reset (xstrdup (fieldname));
- /* This might throw an exception. If so, we want to let it
- propagate. */
- val = evaluate_subexpression_type (exp.get (), subexp);
-
- return value_type (val);
+ expr::structop_base_operation *op = cstate.expout_last_op;
+ const std::string &fld = op->get_string ();
+ *name = make_unique_xstrdup (fld.c_str ());
+ return value_type (op->evaluate_lhs (exp.get ()));
}
/* Parse floating point value P of length LEN.
va_end (args);
}
-/* Implementation of the exp_descriptor method operator_check. */
-
-int
-operator_check_standard (struct expression *exp, int pos,
- int (*objfile_func) (struct objfile *objfile,
- void *data),
- void *data)
-{
- const union exp_element *const elts = exp->elts;
- struct type *type = NULL;
- struct objfile *objfile = NULL;
-
- /* Extended operators should have been already handled by exp_descriptor
- iterate method of its specific language. */
- gdb_assert (elts[pos].opcode < OP_EXTENDED0);
-
- /* Track the callers of write_exp_elt_type for this table. */
-
- switch (elts[pos].opcode)
- {
- case BINOP_VAL:
- case OP_COMPLEX:
- case OP_FLOAT:
- case OP_LONG:
- case OP_SCOPE:
- case OP_TYPE:
- case UNOP_CAST:
- case UNOP_MAX:
- case UNOP_MEMVAL:
- case UNOP_MIN:
- type = elts[pos + 1].type;
- break;
-
- case TYPE_INSTANCE:
- {
- LONGEST arg, nargs = elts[pos + 2].longconst;
-
- for (arg = 0; arg < nargs; arg++)
- {
- struct type *inst_type = elts[pos + 3 + arg].type;
- struct objfile *inst_objfile = inst_type->objfile_owner ();
-
- if (inst_objfile && (*objfile_func) (inst_objfile, data))
- return 1;
- }
- }
- break;
-
- case OP_VAR_VALUE:
- {
- const struct block *const block = elts[pos + 1].block;
- const struct symbol *const symbol = elts[pos + 2].symbol;
-
- /* Check objfile where the variable itself is placed. */
- if ((*objfile_func) (symbol_objfile (symbol), data))
- return 1;
-
- /* Check objfile where is placed the code touching the variable. */
- objfile = block_objfile (block);
-
- type = SYMBOL_TYPE (symbol);
- }
- break;
- case OP_VAR_MSYM_VALUE:
- objfile = elts[pos + 1].objfile;
- break;
- }
-
- /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */
-
- if (type != nullptr && type->objfile_owner () != nullptr
- && objfile_func (type->objfile_owner (), data))
- return 1;
-
- if (objfile && (*objfile_func) (objfile, data))
- return 1;
-
- return 0;
-}
-
-/* Call OBJFILE_FUNC for any objfile found being referenced by EXP.
- OBJFILE_FUNC is never called with NULL OBJFILE. OBJFILE_FUNC get
- passed an arbitrary caller supplied DATA pointer. If OBJFILE_FUNC
- returns non-zero value then (any other) non-zero value is immediately
- returned to the caller. Otherwise zero is returned after iterating
- through whole EXP. */
-
-static int
-exp_iterate (struct expression *exp,
- int (*objfile_func) (struct objfile *objfile, void *data),
- void *data)
-{
- int endpos;
-
- for (endpos = exp->nelts; endpos > 0; )
- {
- int pos, args, oplen = 0;
-
- operator_length (exp, endpos, &oplen, &args);
- gdb_assert (oplen > 0);
-
- pos = endpos - oplen;
- if (exp->language_defn->expression_ops ()->operator_check (exp, pos,
- objfile_func,
- data))
- return 1;
-
- endpos = pos;
- }
-
- return 0;
-}
-
-/* Helper for exp_uses_objfile. */
-
-static int
-exp_uses_objfile_iter (struct objfile *exp_objfile, void *objfile_voidp)
-{
- struct objfile *objfile = (struct objfile *) objfile_voidp;
-
- if (exp_objfile->separate_debug_objfile_backlink)
- exp_objfile = exp_objfile->separate_debug_objfile_backlink;
-
- return exp_objfile == objfile;
-}
-
/* Return 1 if EXP uses OBJFILE (and will become dangling when OBJFILE
is unloaded), otherwise return 0. OBJFILE must not be a separate debug info
file. */
{
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);
-}
-
-/* Reallocate the `expout' pointer inside PS so that it can accommodate
- at least LENELT expression elements. This function does nothing if
- there is enough room for the elements. */
-
-static void
-increase_expout_size (struct expr_builder *ps, size_t lenelt)
-{
- if ((ps->expout_ptr + lenelt) >= ps->expout_size)
- {
- ps->expout_size = std::max (ps->expout_size * 2,
- ps->expout_ptr + lenelt + 10);
- ps->expout->resize (ps->expout_size);
- }
+ return exp->op->uses_objfile (objfile);
}
void _initialize_parse ();
expout->op = std::move (op);
}
- /* The size of the expression above. */
-
- size_t expout_size;
-
/* The expression related to this parser state. */
expression_up expout;
-
- /* The number of elements already in the expression. This is used
- to know where to put new elements. */
-
- size_t expout_ptr;
};
/* This is used for expression completion. */
struct expr_completion_state
{
- /* The index of the last struct expression directly before a '.' or
- '->'. This is set when parsing and is only used when completing a
- field name. It is -1 if no dereference operation was found. */
- int expout_last_struct = -1;
-
/* The last struct expression directly before a '.' or '->'. This
is set when parsing and is only used when completing a field
name. It is nullptr if no dereference operation was found. */
return val;
}
- /* Mark the current index as the starting location of a structure
- expression. This is used when completing on field names. */
-
- void mark_struct_expression ();
-
/* Mark the given operation as the starting location of a structure
expression. This is used when completing on field names. */
int theclass;
};
-/* Reverse an expression from suffix form (in which it is constructed)
- to prefix form (in which we can conveniently print or execute it).
- Ordinarily this always returns -1. However, if LAST_STRUCT
- is not -1 (i.e., we are trying to complete a field name), it will
- return the index of the subexpression which is the left-hand-side
- of the struct operation at LAST_STRUCT. */
-
-extern int prefixify_expression (struct expression *expr,
- int last_struct = -1);
-
-extern void write_exp_elt_opcode (struct expr_builder *, enum exp_opcode);
-
-extern void write_exp_elt_sym (struct expr_builder *, struct symbol *);
-
-extern void write_exp_elt_longcst (struct expr_builder *, LONGEST);
-
-extern void write_exp_elt_floatcst (struct expr_builder *, const gdb_byte *);
-
-extern void write_exp_elt_type (struct expr_builder *, struct type *);
-
-extern void write_exp_elt_intern (struct expr_builder *, struct internalvar *);
-
-extern void write_exp_string (struct expr_builder *, struct stoken);
-
-void write_exp_string_vector (struct expr_builder *, int type,
- struct stoken_vector *vec);
-
-extern void write_exp_bitstring (struct expr_builder *, struct stoken);
-
-extern void write_exp_elt_block (struct expr_builder *, const struct block *);
-
-extern void write_exp_elt_objfile (struct expr_builder *,
- struct objfile *objfile);
-
-extern void write_exp_msymbol (struct expr_builder *,
- struct bound_minimal_symbol);
-
-extern void write_dollar_variable (struct parser_state *, struct stoken str);
-
-/* Write a reference to a symbol to the expression being built in PS.
- NAME is the name of the symbol to write; SYM is the symbol. If SYM
- is nullptr (meaning the 'symbol' member), a minimal symbol will be
- searched for and used if available. Throws an exception if SYM is
- nullptr and no minimal symbol can be found. */
-
-extern void write_exp_symbol_reference (struct parser_state *ps,
- const char *name,
- struct block_symbol sym);
-
extern const char *find_template_name_end (const char *);
extern std::string copy_name (struct stoken);
-extern int dump_subexp (struct expression *, struct ui_file *, int);
-
-extern int dump_subexp_body_standard (struct expression *,
- struct ui_file *, int);
-
-/* Dump (to STREAM) a function call like expression at position ELT in the
- expression array EXP. Return a new value for ELT just after the
- function call expression. */
-
-extern int dump_subexp_body_funcall (struct expression *exp,
- struct ui_file *stream, int elt);
-
-extern void operator_length (const struct expression *, int, int *, int *);
-
-extern void operator_length_standard (const struct expression *, int, int *,
- int *);
-
-extern int operator_check_standard (struct expression *exp, int pos,
- int (*objfile_func)
- (struct objfile *objfile, void *data),
- void *data);
-
extern bool parse_float (const char *p, int len,
const struct type *type, gdb_byte *data);
\f
-/* These codes indicate operator precedences for expression printing,
- least tightly binding first. */
-/* Adding 1 to a precedence value is done for binary operators,
- on the operand which is more tightly bound, so that operators
- of equal precedence within that operand will get parentheses. */
-/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
- they are used as the "surrounding precedence" to force
- various kinds of things to be parenthesized. */
-enum precedence
- {
- PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_LOGICAL_OR,
- PREC_LOGICAL_AND, PREC_BITWISE_IOR, PREC_BITWISE_AND, PREC_BITWISE_XOR,
- PREC_EQUAL, PREC_ORDER, PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
- PREC_HYPER, PREC_PREFIX, PREC_SUFFIX, PREC_BUILTIN_FUNCTION
- };
-
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-
-struct op_print
- {
- const char *string;
- enum exp_opcode opcode;
- /* Precedence of operator. These values are used only by comparisons. */
- enum precedence precedence;
-
- /* For a binary operator: 1 iff right associate.
- For a unary operator: 1 iff postfix. */
- int right_assoc;
- };
-
-/* Information needed to print, prefixify, and evaluate expressions for
- a given language. */
-
-struct exp_descriptor
- {
- /* Print subexpression. */
- void (*print_subexp) (struct expression *, int *, struct ui_file *,
- enum precedence);
-
- /* Returns number of exp_elements needed to represent an operator and
- the number of subexpressions it takes. */
- void (*operator_length) (const struct expression*, int, int*, int *);
-
- /* Call OBJFILE_FUNC for any objfile found being referenced by the
- single operator of EXP at position POS. Operator parameters are
- located at positive (POS + number) offsets in EXP. OBJFILE_FUNC
- should never be called with NULL OBJFILE. OBJFILE_FUNC should
- get passed an arbitrary caller supplied DATA pointer. If it
- returns non-zero value then (any other) non-zero value should be
- immediately returned to the caller. Otherwise zero should be
- returned. */
- int (*operator_check) (struct expression *exp, int pos,
- int (*objfile_func) (struct objfile *objfile,
- void *data),
- void *data);
-
- /* Dump the rest of this (prefix) expression after the operator
- itself has been printed. See dump_subexp_body_standard in
- (expprint.c). */
- int (*dump_subexp_body) (struct expression *, struct ui_file *, int);
-
- /* Evaluate an expression. */
- struct value *(*evaluate_exp) (struct type *, struct expression *,
- int *, enum noside);
- };
-
-
-/* Default descriptor containing standard definitions of all
- elements. */
-extern const struct exp_descriptor exp_descriptor_standard;
-
-/* Functions used by language-specific extended operators to (recursively)
- print/dump subexpressions. */
-
-extern void print_subexp (struct expression *, int *, struct ui_file *,
- enum precedence);
-
-extern void print_subexp_standard (struct expression *, int *,
- struct ui_file *, enum precedence);
-
-/* Print a function call like expression to STREAM. This is called as a
- helper function by which point the expression node identifying this as a
- function call has already been stripped off and POS should point to the
- number of function call arguments. EXP is the object containing the
- list of expression elements. */
-
-extern void print_subexp_funcall (struct expression *exp, int *pos,
- struct ui_file *stream);
/* Function used to avoid direct calls to fprintf
in the code generated by the bison parser. */
struct expression *cond,
CORE_ADDR *data_value, int *len)
{
- int pc = 1, num_accesses_left, num_accesses_right;
+ int num_accesses_left, num_accesses_right;
struct value *left_val, *right_val;
std::vector<value_ref_ptr> left_chain, right_chain;
- if (cond->first_opcode () != BINOP_EQUAL)
+ expr::equal_operation *eqop
+ = dynamic_cast<expr::equal_operation *> (cond->op.get ());
+ if (eqop == nullptr)
return 0;
+ expr::operation *lhs = eqop->get_lhs ();
+ expr::operation *rhs = eqop->get_rhs ();
- 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);
+ fetch_subexp_value (cond, 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, rhs, &right_val, NULL, &right_chain, false);
+ fetch_subexp_value (cond, rhs, &right_val, NULL, &right_chain, false);
num_accesses_right = num_memory_accesses (right_chain);
if (right_val == NULL || num_accesses_right < 0)
{
expression_up expr = parse_expression (exp);
- 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)
+ switch (expr->op->opcode ())
{
case UNOP_PREINCREMENT:
case UNOP_POSTINCREMENT:
bool range_checking_on_by_default () const override
{ return true; }
- /* See language.h. */
-
- const struct op_print *opcode_print_table () const override
- { return c_op_print_tab; }
-
private:
/* Helper for value_print_inner, arguments are as for that function.
unsigned n)
{
struct stap_probe_arg *arg;
- union exp_element *pc;
arg = this->get_arg_by_number (n, expr->gdbarch);
- pc = arg->aexpr->elts;
- if (arg->aexpr->op != nullptr)
- arg->aexpr->op->generate_ax (arg->aexpr.get (), expr, value);
- else
- gen_expr (arg->aexpr.get (), &pc, expr, value);
+ arg->aexpr->op->generate_ax (arg->aexpr.get (), expr, value);
require_rvalue (expr, value);
value->type = arg->atype;
if (exp->first_opcode () == OP_VAR_VALUE)
{
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;
+ expr::var_value_operation *vvop
+ = (dynamic_cast<expr::var_value_operation *>
+ (exp->op.get ()));
+ sym = vvop->get_symbol ();
if (SYMBOL_CLASS (sym) == LOC_CONST)
{
{
case OP_REGISTER:
{
- 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;
+ expr::register_operation *regop
+ = (dynamic_cast<expr::register_operation *>
+ (exp->op.get ()));
+ const char *name = regop->get_name ();
i = user_reg_map_name_to_regnum (target_gdbarch (),
name, strlen (name));
/* 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;
+ expr::unop_memval_operation *memop
+ = (dynamic_cast<expr::unop_memval_operation *>
+ (exp->op.get ()));
+ struct type *type = memop->get_type ();
/* Initialize the TYPE_LENGTH if it is a typedef. */
check_typedef (type);
collect->add_memrange (target_gdbarch (),
case OP_VAR_VALUE:
{
- 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;
+ expr::var_value_operation *vvo
+ = (dynamic_cast<expr::var_value_operation *>
+ (exp->op.get ()));
+ struct symbol *sym = vvo->get_symbol ();
const char *name = sym->natural_name ();
collect->collect_symbol (sym,
/* Validate the expression.
Was the expression an assignment?
Or even an expression at all? */
- if ((expr->nelts == 0 && expr->op == nullptr)
- || expr->first_opcode () != BINOP_ASSIGN)
+ if (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->op == nullptr)
+ /* Extract the variable from the parsed expression. */
+ expr::assign_operation *assign
+ = dynamic_cast<expr::assign_operation *> (expr->op.get ());
+ if (assign != 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 ();
- }
+ 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)
extern struct value *evaluate_type (struct expression *exp);
-extern struct value *evaluate_subexp (struct type *expect_type,
- struct expression *exp,
- int *pos, enum noside noside);
-
-extern struct value *evaluate_subexpression_type (struct expression *exp,
- int subexp);
-
extern value *evaluate_var_value (enum noside noside, const block *blk,
symbol *var);
extern value *eval_skip_value (expression *exp);
namespace expr { class operation; };
-extern void fetch_subexp_value (struct expression *exp, int *pc,
+extern void fetch_subexp_value (struct expression *exp,
expr::operation *op,
struct value **valp, struct value **resultp,
std::vector<value_ref_ptr> *val_chain,
bool preserve_errors);
-extern const char *extract_field_op (struct expression *exp, int *subexp);
-
-extern struct value *evaluate_subexp_with_coercion (struct expression *,
- int *, enum noside);
-
extern struct value *parse_and_eval (const char *exp);
extern struct value *parse_to_comma_and_eval (const char **expp);