#include "objfiles.h"
#include "typeprint.h"
#include <ctype.h>
+#include "expop.h"
+#include "c-exp.h"
/* Prototypes for local functions. */
/* Helper function that implements the body of OP_SCOPE. */
-static struct value *
+struct value *
eval_op_scope (struct type *expect_type, struct expression *exp,
enum noside noside,
struct type *type, const char *string)
/* Helper function that implements the body of OP_VAR_ENTRY_VALUE. */
-static struct value *
+struct value *
eval_op_var_entry_value (struct type *expect_type, struct expression *exp,
enum noside noside, symbol *sym)
{
/* Helper function that implements the body of OP_VAR_MSYM_VALUE. */
-static struct value *
+struct value *
eval_op_var_msym_value (struct type *expect_type, struct expression *exp,
enum noside noside, bool outermost_p,
minimal_symbol *msymbol, struct objfile *objfile)
/* Helper function that implements the body of OP_FUNC_STATIC_VAR. */
-static struct value *
+struct value *
eval_op_func_static_var (struct type *expect_type, struct expression *exp,
enum noside noside,
value *func, const char *var)
/* Helper function that implements the body of OP_REGISTER. */
-static struct value *
+struct value *
eval_op_register (struct type *expect_type, struct expression *exp,
enum noside noside, const char *name)
{
/* Helper function that implements the body of OP_STRING. */
-static struct value *
+struct value *
eval_op_string (struct type *expect_type, struct expression *exp,
enum noside noside, int len, const char *string)
{
/* Helper function that implements the body of OP_OBJC_SELECTOR. */
-static struct value *
+struct value *
eval_op_objc_selector (struct type *expect_type, struct expression *exp,
enum noside noside,
const char *sel)
/* Helper function that implements the body of BINOP_CONCAT. */
-static struct value *
+struct value *
eval_op_concat (struct type *expect_type, struct expression *exp,
- enum noside noside,
- enum exp_opcode op, struct value *arg1, struct value *arg2)
+ enum noside noside, struct value *arg1, struct value *arg2)
{
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ if (binop_user_defined_p (BINOP_CONCAT, arg1, arg2))
+ return value_x_binop (arg1, arg2, BINOP_CONCAT, OP_NULL, noside);
else
return value_concat (arg1, arg2);
}
/* A helper function for TERNOP_SLICE. */
-static struct value *
+struct value *
eval_op_ternop (struct type *expect_type, struct expression *exp,
enum noside noside,
struct value *array, struct value *low, struct value *upper)
/* A helper function for STRUCTOP_STRUCT. */
-static struct value *
+struct value *
eval_op_structop_struct (struct type *expect_type, struct expression *exp,
enum noside noside,
struct value *arg1, const char *string)
/* A helper function for STRUCTOP_PTR. */
-static struct value *
+struct value *
eval_op_structop_ptr (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
+ enum noside noside,
struct value *arg1, const char *string)
{
if (noside == EVAL_SKIP)
/* Check to see if operator '->' has been overloaded. If so replace
arg1 with the value returned by evaluating operator->(). */
- while (unop_user_defined_p (op, arg1))
+ while (unop_user_defined_p (STRUCTOP_PTR, arg1))
{
struct value *value = NULL;
try
{
- value = value_x_unop (arg1, op, noside);
+ value = value_x_unop (arg1, STRUCTOP_PTR, noside);
}
catch (const gdb_exception_error &except)
/* A helper function for STRUCTOP_MEMBER. */
-static struct value *
+struct value *
eval_op_member (struct type *expect_type, struct expression *exp,
enum noside noside,
struct value *arg1, struct value *arg2)
arg1 = value_cast_pointers (lookup_pointer_type (TYPE_SELF_TYPE (type)),
arg1, 1);
- mem_offset = value_as_long (arg2);
+ mem_offset = value_as_long (arg2);
+
+ arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+ value_as_long (arg1) + mem_offset);
+ return value_ind (arg3);
+
+ default:
+ error (_("non-pointer-to-member value used "
+ "in pointer-to-member construct"));
+ }
+}
+
+/* A helper function for BINOP_ADD. */
+
+struct value *
+eval_op_add (struct type *expect_type, struct expression *exp,
+ enum noside noside,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (BINOP_ADD, arg1, arg2))
+ return value_x_binop (arg1, arg2, BINOP_ADD, OP_NULL, noside);
+ else if (ptrmath_type_p (exp->language_defn, value_type (arg1))
+ && is_integral_or_integral_reference (value_type (arg2)))
+ return value_ptradd (arg1, value_as_long (arg2));
+ else if (ptrmath_type_p (exp->language_defn, value_type (arg2))
+ && is_integral_or_integral_reference (value_type (arg1)))
+ return value_ptradd (arg2, value_as_long (arg1));
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ return value_binop (arg1, arg2, BINOP_ADD);
+ }
+}
+
+/* A helper function for BINOP_SUB. */
+
+struct value *
+eval_op_sub (struct type *expect_type, struct expression *exp,
+ enum noside noside,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (BINOP_SUB, arg1, arg2))
+ return value_x_binop (arg1, arg2, BINOP_SUB, OP_NULL, noside);
+ else if (ptrmath_type_p (exp->language_defn, value_type (arg1))
+ && ptrmath_type_p (exp->language_defn, value_type (arg2)))
+ {
+ /* FIXME -- should be ptrdiff_t */
+ struct type *type = builtin_type (exp->gdbarch)->builtin_long;
+ return value_from_longest (type, value_ptrdiff (arg1, arg2));
+ }
+ else if (ptrmath_type_p (exp->language_defn, value_type (arg1))
+ && is_integral_or_integral_reference (value_type (arg2)))
+ return value_ptradd (arg1, - value_as_long (arg2));
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ return value_binop (arg1, arg2, BINOP_SUB);
+ }
+}
+
+/* Helper function for several different binary operations. */
+
+struct value *
+eval_op_binary (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else
+ {
+ /* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero,
+ fudge arg2 to avoid division-by-zero, the caller is
+ (theoretically) only looking for the type of the result. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS
+ /* ??? Do we really want to test for BINOP_MOD here?
+ The implementation of value_binop gives it a well-defined
+ value. */
+ && (op == BINOP_DIV
+ || op == BINOP_INTDIV
+ || op == BINOP_REM
+ || op == BINOP_MOD)
+ && value_logical_not (arg2))
+ {
+ struct value *v_one;
+
+ v_one = value_one (value_type (arg2));
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &v_one);
+ return value_binop (arg1, v_one, op);
+ }
+ else
+ {
+ /* For shift and integer exponentiation operations,
+ only promote the first argument. */
+ if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP)
+ && is_integral_type (value_type (arg2)))
+ unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+ else
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+
+ return value_binop (arg1, arg2, op);
+ }
+ }
+}
+
+/* A helper function for BINOP_SUBSCRIPT. */
+
+static struct value *
+eval_op_subscript (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else
+ {
+ /* If the user attempts to subscript something that is not an
+ array or pointer type (like a plain int variable for example),
+ then report this as an error. */
+
+ arg1 = coerce_ref (arg1);
+ struct type *type = check_typedef (value_type (arg1));
+ if (type->code () != TYPE_CODE_ARRAY
+ && type->code () != TYPE_CODE_PTR)
+ {
+ if (type->name ())
+ error (_("cannot subscript something of type `%s'"),
+ type->name ());
+ else
+ error (_("cannot subscript requested type"));
+ }
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
+ else
+ return value_subscript (arg1, value_as_long (arg2));
+ }
+}
+
+/* A helper function for BINOP_EQUAL. */
+
+static struct value *
+eval_op_equal (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ int tem = value_equal (arg1, arg2);
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) tem);
+ }
+}
+
+/* A helper function for BINOP_NOTEQUAL. */
+
+static struct value *
+eval_op_notequal (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ int tem = value_equal (arg1, arg2);
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) ! tem);
+ }
+}
+
+/* A helper function for BINOP_LESS. */
+
+static struct value *
+eval_op_less (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ int tem = value_less (arg1, arg2);
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) tem);
+ }
+}
+
+/* A helper function for BINOP_GTR. */
+
+static struct value *
+eval_op_gtr (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ int tem = value_less (arg2, arg1);
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) tem);
+ }
+}
+
+/* A helper function for BINOP_GEQ. */
+
+static struct value *
+eval_op_geq (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ int tem = value_less (arg2, arg1) || value_equal (arg1, arg2);
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) tem);
+ }
+}
+
+/* A helper function for BINOP_LEQ. */
+
+static struct value *
+eval_op_leq (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ int tem = value_less (arg1, arg2) || value_equal (arg1, arg2);
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) tem);
+ }
+}
+
+/* A helper function for BINOP_REPEAT. */
+
+static struct value *
+eval_op_repeat (struct type *expect_type, struct expression *exp,
+ enum noside noside,
+ struct value *arg1, struct value *arg2)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ struct type *type = check_typedef (value_type (arg2));
+ if (type->code () != TYPE_CODE_INT
+ && type->code () != TYPE_CODE_ENUM)
+ error (_("Non-integral right operand for \"@\" operator."));
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ return allocate_repeat_value (value_type (arg1),
+ longest_to_int (value_as_long (arg2)));
+ }
+ else
+ return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
+}
+
+/* A helper function for UNOP_PLUS. */
+
+static struct value *
+eval_op_plus (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op, noside);
+ else
+ {
+ unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+ return value_pos (arg1);
+ }
+}
+
+/* A helper function for UNOP_NEG. */
+
+static struct value *
+eval_op_neg (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op, noside);
+ else
+ {
+ unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+ return value_neg (arg1);
+ }
+}
+
+/* A helper function for UNOP_COMPLEMENT. */
+
+static struct value *
+eval_op_complement (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (unop_user_defined_p (UNOP_COMPLEMENT, arg1))
+ return value_x_unop (arg1, UNOP_COMPLEMENT, noside);
+ else
+ {
+ unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+ return value_complement (arg1);
+ }
+}
+
+/* A helper function for UNOP_LOGICAL_NOT. */
+
+static struct value *
+eval_op_lognot (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op, noside);
+ else
+ {
+ struct type *type = language_bool_type (exp->language_defn,
+ exp->gdbarch);
+ return value_from_longest (type, (LONGEST) value_logical_not (arg1));
+ }
+}
+
+/* A helper function for UNOP_IND. */
+
+static struct value *
+eval_op_ind (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ struct type *type = check_typedef (value_type (arg1));
+ if (type->code () == TYPE_CODE_METHODPTR
+ || type->code () == TYPE_CODE_MEMBERPTR)
+ error (_("Attempt to dereference pointer "
+ "to member without an object"));
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op, noside);
+ else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ type = check_typedef (value_type (arg1));
+
+ /* If the type pointed to is dynamic then in order to resolve the
+ dynamic properties we must actually dereference the pointer.
+ There is a risk that this dereference will have side-effects
+ in the inferior, but being able to print accurate type
+ information seems worth the risk. */
+ if ((type->code () != TYPE_CODE_PTR
+ && !TYPE_IS_REFERENCE (type))
+ || !is_dynamic_type (TYPE_TARGET_TYPE (type)))
+ {
+ if (type->code () == TYPE_CODE_PTR
+ || TYPE_IS_REFERENCE (type)
+ /* In C you can dereference an array to get the 1st elt. */
+ || type->code () == TYPE_CODE_ARRAY)
+ return value_zero (TYPE_TARGET_TYPE (type),
+ lval_memory);
+ else if (type->code () == TYPE_CODE_INT)
+ /* GDB allows dereferencing an int. */
+ return value_zero (builtin_type (exp->gdbarch)->builtin_int,
+ lval_memory);
+ else
+ error (_("Attempt to take contents of a non-pointer value."));
+ }
+ }
+
+ /* Allow * on an integer so we can cast it to whatever we want.
+ This returns an int, which seems like the most C-like thing to
+ do. "long long" variables are rare enough that
+ BUILTIN_TYPE_LONGEST would seem to be a mistake. */
+ if (type->code () == TYPE_CODE_INT)
+ return value_at_lazy (builtin_type (exp->gdbarch)->builtin_int,
+ (CORE_ADDR) value_as_address (arg1));
+ return value_ind (arg1);
+}
+
+/* A helper function for UNOP_ALIGNOF. */
+
+static struct value *
+eval_op_alignof (struct type *expect_type, struct expression *exp,
+ enum noside noside,
+ struct value *arg1)
+{
+ struct type *type = value_type (arg1);
+ /* FIXME: This should be size_t. */
+ struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
+ ULONGEST align = type_align (type);
+ if (align == 0)
+ error (_("could not determine alignment of type"));
+ return value_from_longest (size_type, align);
+}
+
+/* A helper function for UNOP_MEMVAL. */
+
+static struct value *
+eval_op_memval (struct type *expect_type, struct expression *exp,
+ enum noside noside,
+ struct value *arg1, struct type *type)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (type, lval_memory);
+ else
+ return value_at_lazy (type, value_as_address (arg1));
+}
+
+/* A helper function for UNOP_PREINCREMENT. */
+
+static struct value *
+eval_op_preinc (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ struct value *arg2;
+ if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
+ arg2 = value_ptradd (arg1, 1);
+ else
+ {
+ struct value *tmp = arg1;
+
+ arg2 = value_one (value_type (arg1));
+ binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
+ arg2 = value_binop (tmp, arg2, BINOP_ADD);
+ }
+
+ return value_assign (arg1, arg2);
+ }
+}
+
+/* A helper function for UNOP_PREDECREMENT. */
+
+static struct value *
+eval_op_predec (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ struct value *arg2;
+ if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
+ arg2 = value_ptradd (arg1, -1);
+ else
+ {
+ struct value *tmp = arg1;
+
+ arg2 = value_one (value_type (arg1));
+ binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
+ arg2 = value_binop (tmp, arg2, BINOP_SUB);
+ }
+
+ return value_assign (arg1, arg2);
+ }
+}
+
+/* A helper function for UNOP_POSTINCREMENT. */
+
+static struct value *
+eval_op_postinc (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ struct value *arg3 = value_non_lval (arg1);
+ struct value *arg2;
+
+ if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
+ arg2 = value_ptradd (arg1, 1);
+ else
+ {
+ struct value *tmp = arg1;
+
+ arg2 = value_one (value_type (arg1));
+ binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
+ arg2 = value_binop (tmp, arg2, BINOP_ADD);
+ }
+
+ value_assign (arg1, arg2);
+ return arg3;
+ }
+}
+
+/* A helper function for UNOP_POSTDECREMENT. */
+
+static struct value *
+eval_op_postdec (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1)
+{
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ struct value *arg3 = value_non_lval (arg1);
+ struct value *arg2;
+
+ if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
+ arg2 = value_ptradd (arg1, -1);
+ else
+ {
+ struct value *tmp = arg1;
+
+ arg2 = value_one (value_type (arg1));
+ binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
+ arg2 = value_binop (tmp, arg2, BINOP_SUB);
+ }
+
+ value_assign (arg1, arg2);
+ return arg3;
+ }
+}
+
+/* A helper function for OP_TYPE. */
+
+static struct value *
+eval_op_type (struct type *expect_type, struct expression *exp,
+ enum noside noside, struct type *type)
+{
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return allocate_value (type);
+ else
+ error (_("Attempt to use a type name as an expression"));
+}
+
+/* A helper function for BINOP_ASSIGN_MODIFY. */
+
+static struct value *
+eval_binop_assign_modify (struct type *expect_type, struct expression *exp,
+ enum noside noside, enum exp_opcode op,
+ struct value *arg1, struct value *arg2)
+{
+ 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, BINOP_ASSIGN_MODIFY, op, noside);
+ else if (op == BINOP_ADD && ptrmath_type_p (exp->language_defn,
+ value_type (arg1))
+ && is_integral_type (value_type (arg2)))
+ arg2 = value_ptradd (arg1, value_as_long (arg2));
+ else if (op == BINOP_SUB && ptrmath_type_p (exp->language_defn,
+ value_type (arg1))
+ && is_integral_type (value_type (arg2)))
+ arg2 = value_ptradd (arg1, - value_as_long (arg2));
+ else
+ {
+ struct value *tmp = arg1;
+
+ /* For shift and integer exponentiation operations,
+ only promote the first argument. */
+ if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP)
+ && is_integral_type (value_type (arg2)))
+ unop_promote (exp->language_defn, exp->gdbarch, &tmp);
+ else
+ binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
+
+ arg2 = value_binop (tmp, arg2, op);
+ }
+ return value_assign (arg1, arg2);
+}
+
+/* Note that ARGS needs 2 empty slots up front and must end with a
+ null pointer. */
+static struct value *
+eval_op_objc_msgcall (struct type *expect_type, struct expression *exp,
+ enum noside noside, CORE_ADDR selector,
+ value *target, gdb::array_view<value *> args)
+{
+ CORE_ADDR responds_selector = 0;
+ CORE_ADDR method_selector = 0;
+
+ int struct_return = 0;
+
+ struct value *msg_send = NULL;
+ struct value *msg_send_stret = NULL;
+ int gnu_runtime = 0;
+
+ struct value *method = NULL;
+ struct value *called_method = NULL;
+
+ struct type *selector_type = NULL;
+ struct type *long_type;
+ struct type *type;
+
+ struct value *ret = NULL;
+ CORE_ADDR addr = 0;
+
+ value *argvec[5];
+
+ long_type = builtin_type (exp->gdbarch)->builtin_long;
+ selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr;
+
+ if (value_as_long (target) == 0)
+ return value_from_longest (long_type, 0);
+
+ if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0).minsym)
+ gnu_runtime = 1;
+
+ /* Find the method dispatch (Apple runtime) or method lookup
+ (GNU runtime) function for Objective-C. These will be used
+ to lookup the symbol information for the method. If we
+ can't find any symbol information, then we'll use these to
+ call the method, otherwise we can call the method
+ directly. The msg_send_stret function is used in the special
+ case of a method that returns a structure (Apple runtime
+ only). */
+ if (gnu_runtime)
+ {
+ type = selector_type;
+
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+
+ msg_send = find_function_in_inferior ("objc_msg_lookup", NULL);
+ msg_send_stret
+ = find_function_in_inferior ("objc_msg_lookup", NULL);
+
+ msg_send = value_from_pointer (type, value_as_address (msg_send));
+ msg_send_stret = value_from_pointer (type,
+ value_as_address (msg_send_stret));
+ }
+ else
+ {
+ msg_send = find_function_in_inferior ("objc_msgSend", NULL);
+ /* Special dispatcher for methods returning structs. */
+ msg_send_stret
+ = find_function_in_inferior ("objc_msgSend_stret", NULL);
+ }
+
+ /* Verify the target object responds to this method. The
+ standard top-level 'Object' class uses a different name for
+ the verification method than the non-standard, but more
+ often used, 'NSObject' class. Make sure we check for both. */
+
+ responds_selector
+ = lookup_child_selector (exp->gdbarch, "respondsToSelector:");
+ if (responds_selector == 0)
+ responds_selector
+ = lookup_child_selector (exp->gdbarch, "respondsTo:");
+
+ if (responds_selector == 0)
+ error (_("no 'respondsTo:' or 'respondsToSelector:' method"));
+
+ method_selector
+ = lookup_child_selector (exp->gdbarch, "methodForSelector:");
+ if (method_selector == 0)
+ method_selector
+ = lookup_child_selector (exp->gdbarch, "methodFor:");
+
+ if (method_selector == 0)
+ error (_("no 'methodFor:' or 'methodForSelector:' method"));
+
+ /* Call the verification method, to make sure that the target
+ class implements the desired method. */
+
+ argvec[0] = msg_send;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (long_type, responds_selector);
+ argvec[3] = value_from_longest (long_type, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
+ if (gnu_runtime)
+ {
+ /* Function objc_msg_lookup returns a pointer. */
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
+ }
+ if (value_as_long (ret) == 0)
+ error (_("Target does not respond to this message selector."));
+
+ /* Call "methodForSelector:" method, to get the address of a
+ function method that implements this selector for this
+ class. If we can find a symbol at that address, then we
+ know the return type, parameter types etc. (that's a good
+ thing). */
+
+ argvec[0] = msg_send;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (long_type, method_selector);
+ argvec[3] = value_from_longest (long_type, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
+ if (gnu_runtime)
+ {
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
+ }
+
+ /* ret should now be the selector. */
+
+ addr = value_as_long (ret);
+ if (addr)
+ {
+ struct symbol *sym = NULL;
+
+ /* The address might point to a function descriptor;
+ resolve it to the actual code address instead. */
+ addr = gdbarch_convert_from_func_ptr_addr (exp->gdbarch, addr,
+ current_top_target ());
+
+ /* Is it a high_level symbol? */
+ sym = find_pc_function (addr);
+ if (sym != NULL)
+ method = value_of_variable (sym, 0);
+ }
+
+ /* If we found a method with symbol information, check to see
+ if it returns a struct. Otherwise assume it doesn't. */
+
+ if (method)
+ {
+ CORE_ADDR funaddr;
+ struct type *val_type;
+
+ funaddr = find_function_addr (method, &val_type);
- arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
- value_as_long (arg1) + mem_offset);
- return value_ind (arg3);
+ block_for_pc (funaddr);
- default:
- error (_("non-pointer-to-member value used "
- "in pointer-to-member construct"));
+ val_type = check_typedef (val_type);
+
+ if ((val_type == NULL)
+ || (val_type->code () == TYPE_CODE_ERROR))
+ {
+ if (expect_type != NULL)
+ val_type = expect_type;
+ }
+
+ struct_return = using_struct_return (exp->gdbarch, method,
+ val_type);
+ }
+ else if (expect_type != NULL)
+ {
+ struct_return = using_struct_return (exp->gdbarch, NULL,
+ check_typedef (expect_type));
}
-}
-/* A helper function for BINOP_ADD. */
+ /* Found a function symbol. Now we will substitute its
+ value in place of the message dispatcher (obj_msgSend),
+ so that we call the method directly instead of thru
+ the dispatcher. The main reason for doing this is that
+ we can now evaluate the return value and parameter values
+ according to their known data types, in case we need to
+ do things like promotion, dereferencing, special handling
+ of structs and doubles, etc.
-static struct value *
-eval_op_add (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2)
-{
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- else if (ptrmath_type_p (exp->language_defn, value_type (arg1))
- && is_integral_or_integral_reference (value_type (arg2)))
- return value_ptradd (arg1, value_as_long (arg2));
- else if (ptrmath_type_p (exp->language_defn, value_type (arg2))
- && is_integral_or_integral_reference (value_type (arg1)))
- return value_ptradd (arg2, value_as_long (arg1));
+ We want to use the type signature of 'method', but still
+ jump to objc_msgSend() or objc_msgSend_stret() to better
+ mimic the behavior of the runtime. */
+
+ if (method)
+ {
+ if (value_type (method)->code () != TYPE_CODE_FUNC)
+ error (_("method address has symbol information "
+ "with non-function type; skipping"));
+
+ /* Create a function pointer of the appropriate type, and
+ replace its value with the value of msg_send or
+ msg_send_stret. We must use a pointer here, as
+ msg_send and msg_send_stret are of pointer type, and
+ the representation may be different on systems that use
+ function descriptors. */
+ if (struct_return)
+ called_method
+ = value_from_pointer (lookup_pointer_type (value_type (method)),
+ value_as_address (msg_send_stret));
+ else
+ called_method
+ = value_from_pointer (lookup_pointer_type (value_type (method)),
+ value_as_address (msg_send));
+ }
else
{
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- return value_binop (arg1, arg2, BINOP_ADD);
+ if (struct_return)
+ called_method = msg_send_stret;
+ else
+ called_method = msg_send;
}
-}
-
-/* A helper function for BINOP_SUB. */
-static struct value *
-eval_op_sub (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2)
-{
if (noside == EVAL_SKIP)
return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- else if (ptrmath_type_p (exp->language_defn, value_type (arg1))
- && ptrmath_type_p (exp->language_defn, value_type (arg2)))
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
- /* FIXME -- should be ptrdiff_t */
- struct type *type = builtin_type (exp->gdbarch)->builtin_long;
- return value_from_longest (type, value_ptrdiff (arg1, arg2));
+ /* If the return type doesn't look like a function type,
+ call an error. This can happen if somebody tries to
+ turn a variable into a function call. This is here
+ because people often want to call, eg, strcmp, which
+ gdb doesn't know is a function. If gdb isn't asked for
+ it's opinion (ie. through "whatis"), it won't offer
+ it. */
+
+ struct type *callee_type = value_type (called_method);
+
+ if (callee_type && callee_type->code () == TYPE_CODE_PTR)
+ callee_type = TYPE_TARGET_TYPE (callee_type);
+ callee_type = TYPE_TARGET_TYPE (callee_type);
+
+ if (callee_type)
+ {
+ if ((callee_type->code () == TYPE_CODE_ERROR) && expect_type)
+ return allocate_value (expect_type);
+ else
+ return allocate_value (callee_type);
+ }
+ else
+ error (_("Expression of type other than "
+ "\"method returning ...\" used as a method"));
}
- else if (ptrmath_type_p (exp->language_defn, value_type (arg1))
- && is_integral_or_integral_reference (value_type (arg2)))
- return value_ptradd (arg1, - value_as_long (arg2));
- else
+
+ /* Now depending on whether we found a symbol for the method,
+ we will either call the runtime dispatcher or the method
+ directly. */
+
+ args[0] = target;
+ args[1] = value_from_longest (long_type, selector);
+
+ if (gnu_runtime && (method != NULL))
{
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- return value_binop (arg1, arg2, BINOP_SUB);
+ /* Function objc_msg_lookup returns a pointer. */
+ struct type *tem_type = value_type (called_method);
+ tem_type = lookup_pointer_type (lookup_function_type (tem_type));
+ deprecated_set_value_type (called_method, tem_type);
+ called_method = call_function_by_hand (called_method, NULL, args);
}
+
+ return call_function_by_hand (called_method, NULL, args);
}
-/* Helper function for several different binary operations. */
+/* Helper function for MULTI_SUBSCRIPT. */
static struct value *
-eval_op_binary (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2)
+eval_multi_subscript (struct type *expect_type, struct expression *exp,
+ enum noside noside, value *arg1,
+ gdb::array_view<value *> args)
{
if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- else
+ return arg1;
+ for (value *arg2 : args)
{
- /* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero,
- fudge arg2 to avoid division-by-zero, the caller is
- (theoretically) only looking for the type of the result. */
- if (noside == EVAL_AVOID_SIDE_EFFECTS
- /* ??? Do we really want to test for BINOP_MOD here?
- The implementation of value_binop gives it a well-defined
- value. */
- && (op == BINOP_DIV
- || op == BINOP_INTDIV
- || op == BINOP_REM
- || op == BINOP_MOD)
- && value_logical_not (arg2))
+ if (binop_user_defined_p (MULTI_SUBSCRIPT, arg1, arg2))
{
- struct value *v_one;
-
- v_one = value_one (value_type (arg2));
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &v_one);
- return value_binop (arg1, v_one, op);
+ arg1 = value_x_binop (arg1, arg2, MULTI_SUBSCRIPT, OP_NULL, noside);
}
else
{
- /* For shift and integer exponentiation operations,
- only promote the first argument. */
- if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP)
- && is_integral_type (value_type (arg2)))
- unop_promote (exp->language_defn, exp->gdbarch, &arg1);
- else
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+ arg1 = coerce_ref (arg1);
+ struct type *type = check_typedef (value_type (arg1));
- return value_binop (arg1, arg2, op);
+ switch (type->code ())
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRING:
+ arg1 = value_subscript (arg1, value_as_long (arg2));
+ break;
+
+ default:
+ if (type->name ())
+ error (_("cannot subscript something of type `%s'"),
+ type->name ());
+ else
+ error (_("cannot subscript requested type"));
+ }
}
}
+ return (arg1);
}
struct value *
int pc, oldpos;
struct value *arg1 = NULL;
struct value *arg2 = NULL;
- struct value *arg3;
struct type *type;
int nargs;
struct value **argvec;
case OP_OBJC_MSGCALL:
{ /* Objective C message (method) call. */
-
- CORE_ADDR responds_selector = 0;
- CORE_ADDR method_selector = 0;
-
CORE_ADDR selector = 0;
- int struct_return = 0;
enum noside sub_no_side = EVAL_NORMAL;
- struct value *msg_send = NULL;
- struct value *msg_send_stret = NULL;
- int gnu_runtime = 0;
-
struct value *target = NULL;
- struct value *method = NULL;
- struct value *called_method = NULL;
struct type *selector_type = NULL;
- struct type *long_type;
-
- struct value *ret = NULL;
- CORE_ADDR addr = 0;
selector = exp->elts[pc + 1].longconst;
nargs = exp->elts[pc + 2].longconst;
- argvec = XALLOCAVEC (struct value *, nargs + 5);
+ argvec = XALLOCAVEC (struct value *, nargs + 3);
(*pos) += 3;
- long_type = builtin_type (exp->gdbarch)->builtin_long;
selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
if (value_as_long (target) == 0)
- return value_from_longest (long_type, 0);
-
- if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0).minsym)
- gnu_runtime = 1;
-
- /* Find the method dispatch (Apple runtime) or method lookup
- (GNU runtime) function for Objective-C. These will be used
- to lookup the symbol information for the method. If we
- can't find any symbol information, then we'll use these to
- call the method, otherwise we can call the method
- directly. The msg_send_stret function is used in the special
- case of a method that returns a structure (Apple runtime
- only). */
- if (gnu_runtime)
- {
- type = selector_type;
-
- type = lookup_function_type (type);
- type = lookup_pointer_type (type);
- type = lookup_function_type (type);
- type = lookup_pointer_type (type);
-
- msg_send = find_function_in_inferior ("objc_msg_lookup", NULL);
- msg_send_stret
- = find_function_in_inferior ("objc_msg_lookup", NULL);
-
- msg_send = value_from_pointer (type, value_as_address (msg_send));
- msg_send_stret = value_from_pointer (type,
- value_as_address (msg_send_stret));
- }
- else
- {
- msg_send = find_function_in_inferior ("objc_msgSend", NULL);
- /* Special dispatcher for methods returning structs. */
- msg_send_stret
- = find_function_in_inferior ("objc_msgSend_stret", NULL);
- }
-
- /* Verify the target object responds to this method. The
- standard top-level 'Object' class uses a different name for
- the verification method than the non-standard, but more
- often used, 'NSObject' class. Make sure we check for both. */
-
- responds_selector
- = lookup_child_selector (exp->gdbarch, "respondsToSelector:");
- if (responds_selector == 0)
- responds_selector
- = lookup_child_selector (exp->gdbarch, "respondsTo:");
-
- if (responds_selector == 0)
- error (_("no 'respondsTo:' or 'respondsToSelector:' method"));
-
- method_selector
- = lookup_child_selector (exp->gdbarch, "methodForSelector:");
- if (method_selector == 0)
- method_selector
- = lookup_child_selector (exp->gdbarch, "methodFor:");
-
- if (method_selector == 0)
- error (_("no 'methodFor:' or 'methodForSelector:' method"));
-
- /* Call the verification method, to make sure that the target
- class implements the desired method. */
-
- argvec[0] = msg_send;
- argvec[1] = target;
- argvec[2] = value_from_longest (long_type, responds_selector);
- argvec[3] = value_from_longest (long_type, selector);
- argvec[4] = 0;
-
- ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
- if (gnu_runtime)
- {
- /* Function objc_msg_lookup returns a pointer. */
- argvec[0] = ret;
- ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
- }
- if (value_as_long (ret) == 0)
- error (_("Target does not respond to this message selector."));
-
- /* Call "methodForSelector:" method, to get the address of a
- function method that implements this selector for this
- class. If we can find a symbol at that address, then we
- know the return type, parameter types etc. (that's a good
- thing). */
-
- argvec[0] = msg_send;
- argvec[1] = target;
- argvec[2] = value_from_longest (long_type, method_selector);
- argvec[3] = value_from_longest (long_type, selector);
- argvec[4] = 0;
-
- ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
- if (gnu_runtime)
- {
- argvec[0] = ret;
- ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3});
- }
-
- /* ret should now be the selector. */
-
- addr = value_as_long (ret);
- if (addr)
- {
- struct symbol *sym = NULL;
-
- /* The address might point to a function descriptor;
- resolve it to the actual code address instead. */
- addr = gdbarch_convert_from_func_ptr_addr (exp->gdbarch, addr,
- current_top_target ());
-
- /* Is it a high_level symbol? */
- sym = find_pc_function (addr);
- if (sym != NULL)
- method = value_of_variable (sym, 0);
- }
-
- /* If we found a method with symbol information, check to see
- if it returns a struct. Otherwise assume it doesn't. */
-
- if (method)
- {
- CORE_ADDR funaddr;
- struct type *val_type;
-
- funaddr = find_function_addr (method, &val_type);
-
- block_for_pc (funaddr);
-
- val_type = check_typedef (val_type);
-
- if ((val_type == NULL)
- || (val_type->code () == TYPE_CODE_ERROR))
- {
- if (expect_type != NULL)
- val_type = expect_type;
- }
-
- struct_return = using_struct_return (exp->gdbarch, method,
- val_type);
- }
- else if (expect_type != NULL)
- {
- struct_return = using_struct_return (exp->gdbarch, NULL,
- check_typedef (expect_type));
- }
-
- /* Found a function symbol. Now we will substitute its
- value in place of the message dispatcher (obj_msgSend),
- so that we call the method directly instead of thru
- the dispatcher. The main reason for doing this is that
- we can now evaluate the return value and parameter values
- according to their known data types, in case we need to
- do things like promotion, dereferencing, special handling
- of structs and doubles, etc.
-
- We want to use the type signature of 'method', but still
- jump to objc_msgSend() or objc_msgSend_stret() to better
- mimic the behavior of the runtime. */
-
- if (method)
- {
- if (value_type (method)->code () != TYPE_CODE_FUNC)
- error (_("method address has symbol information "
- "with non-function type; skipping"));
-
- /* Create a function pointer of the appropriate type, and
- replace its value with the value of msg_send or
- msg_send_stret. We must use a pointer here, as
- msg_send and msg_send_stret are of pointer type, and
- the representation may be different on systems that use
- function descriptors. */
- if (struct_return)
- called_method
- = value_from_pointer (lookup_pointer_type (value_type (method)),
- value_as_address (msg_send_stret));
- else
- called_method
- = value_from_pointer (lookup_pointer_type (value_type (method)),
- value_as_address (msg_send));
- }
+ sub_no_side = EVAL_SKIP;
else
- {
- if (struct_return)
- called_method = msg_send_stret;
- else
- called_method = msg_send;
- }
-
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
-
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- /* If the return type doesn't look like a function type,
- call an error. This can happen if somebody tries to
- turn a variable into a function call. This is here
- because people often want to call, eg, strcmp, which
- gdb doesn't know is a function. If gdb isn't asked for
- it's opinion (ie. through "whatis"), it won't offer
- it. */
-
- struct type *callee_type = value_type (called_method);
-
- if (callee_type && callee_type->code () == TYPE_CODE_PTR)
- callee_type = TYPE_TARGET_TYPE (callee_type);
- callee_type = TYPE_TARGET_TYPE (callee_type);
-
- if (callee_type)
- {
- if ((callee_type->code () == TYPE_CODE_ERROR) && expect_type)
- return allocate_value (expect_type);
- else
- return allocate_value (callee_type);
- }
- else
- error (_("Expression of type other than "
- "\"method returning ...\" used as a method"));
- }
+ 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] = called_method;
- argvec[1] = target;
- argvec[2] = value_from_longest (long_type, selector);
+ argvec[0] = nullptr;
+ argvec[1] = nullptr;
/* User-supplied arguments. */
for (tem = 0; tem < nargs; tem++)
- argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem + 2] = evaluate_subexp_with_coercion (exp, pos,
+ sub_no_side);
argvec[tem + 3] = 0;
- auto call_args = gdb::make_array_view (argvec + 1, nargs + 2);
+ auto call_args = gdb::make_array_view (argvec, nargs + 3);
- if (gnu_runtime && (method != NULL))
- {
- /* Function objc_msg_lookup returns a pointer. */
- deprecated_set_value_type (argvec[0],
- lookup_pointer_type (lookup_function_type (value_type (argvec[0]))));
- argvec[0] = call_function_by_hand (argvec[0], NULL, call_args);
- }
-
- return call_function_by_hand (argvec[0], NULL, call_args);
+ return eval_op_objc_msgcall (expect_type, exp, noside, selector,
+ target, call_args);
}
break;
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, op, arg1,
+ return eval_op_structop_ptr (expect_type, exp, noside, arg1,
&exp->elts[pc + 2].string);
case STRUCTOP_MEMBER:
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, op, arg1, arg2);
+ return eval_op_concat (expect_type, exp, noside, arg1, arg2);
case BINOP_ASSIGN:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
(*pos) += 2;
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
op = exp->elts[pc + 1].opcode;
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside);
- else if (op == BINOP_ADD && ptrmath_type_p (exp->language_defn,
- value_type (arg1))
- && is_integral_type (value_type (arg2)))
- arg2 = value_ptradd (arg1, value_as_long (arg2));
- else if (op == BINOP_SUB && ptrmath_type_p (exp->language_defn,
- value_type (arg1))
- && is_integral_type (value_type (arg2)))
- arg2 = value_ptradd (arg1, - value_as_long (arg2));
- else
- {
- struct value *tmp = arg1;
-
- /* For shift and integer exponentiation operations,
- only promote the first argument. */
- if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP)
- && is_integral_type (value_type (arg2)))
- unop_promote (exp->language_defn, exp->gdbarch, &tmp);
- else
- binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
-
- arg2 = value_binop (tmp, arg2, op);
- }
- return value_assign (arg1, arg2);
+ 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, op, arg1, arg2);
+ 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, op, arg1, arg2);
+ return eval_op_sub (expect_type, exp, noside, arg1, arg2);
case BINOP_EXP:
case BINOP_MUL:
case BINOP_SUBSCRIPT:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
arg2 = evaluate_subexp (nullptr, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- else
- {
- /* If the user attempts to subscript something that is not an
- array or pointer type (like a plain int variable for example),
- then report this as an error. */
+ return eval_op_subscript (expect_type, exp, noside, op, arg1, arg2);
- arg1 = coerce_ref (arg1);
- type = check_typedef (value_type (arg1));
- if (type->code () != TYPE_CODE_ARRAY
- && type->code () != TYPE_CODE_PTR)
- {
- if (type->name ())
- error (_("cannot subscript something of type `%s'"),
- type->name ());
- else
- error (_("cannot subscript requested type"));
- }
-
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
- else
- return value_subscript (arg1, value_as_long (arg2));
- }
case MULTI_SUBSCRIPT:
(*pos) += 2;
nargs = longest_to_int (exp->elts[pc + 1].longconst);
argvec = XALLOCAVEC (struct value *, nargs);
for (ix = 0; ix < nargs; ++ix)
argvec[ix] = evaluate_subexp_with_coercion (exp, pos, noside);
- if (noside == EVAL_SKIP)
- return arg1;
- for (ix = 0; ix < nargs; ++ix)
- {
- arg2 = argvec[ix];
-
- if (binop_user_defined_p (op, arg1, arg2))
- {
- arg1 = value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- arg1 = coerce_ref (arg1);
- type = check_typedef (value_type (arg1));
-
- switch (type->code ())
- {
- case TYPE_CODE_PTR:
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_STRING:
- arg1 = value_subscript (arg1, value_as_long (arg2));
- break;
-
- default:
- if (type->name ())
- error (_("cannot subscript something of type `%s'"),
- type->name ());
- else
- error (_("cannot subscript requested type"));
- }
- }
- }
- return (arg1);
+ 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);
}
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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- {
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- tem = value_equal (arg1, arg2);
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) tem);
- }
-
- case BINOP_NOTEQUAL:
- arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
+ 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
{
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- tem = value_equal (arg1, arg2);
+ 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);
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- {
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- tem = value_less (arg1, arg2);
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) tem);
- }
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- {
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- tem = value_less (arg2, arg1);
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) tem);
- }
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- {
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- tem = value_less (arg2, arg1) || value_equal (arg1, arg2);
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) tem);
- }
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (binop_user_defined_p (op, arg1, arg2))
- {
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
- }
- else
- {
- binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
- tem = value_less (arg1, arg2) || value_equal (arg1, arg2);
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) tem);
- }
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- type = check_typedef (value_type (arg2));
- if (type->code () != TYPE_CODE_INT
- && type->code () != TYPE_CODE_ENUM)
- error (_("Non-integral right operand for \"@\" operator."));
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- return allocate_repeat_value (value_type (arg1),
- longest_to_int (value_as_long (arg2)));
- }
- else
- return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
+ return eval_op_repeat (expect_type, exp, noside, arg1, arg2);
case BINOP_COMMA:
evaluate_subexp (nullptr, exp, pos, noside);
case UNOP_PLUS:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (unop_user_defined_p (op, arg1))
- return value_x_unop (arg1, op, noside);
- else
- {
- unop_promote (exp->language_defn, exp->gdbarch, &arg1);
- return value_pos (arg1);
- }
+ return eval_op_plus (expect_type, exp, noside, op, arg1);
case UNOP_NEG:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (unop_user_defined_p (op, arg1))
- return value_x_unop (arg1, op, noside);
- else
- {
- unop_promote (exp->language_defn, exp->gdbarch, &arg1);
- return value_neg (arg1);
- }
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (unop_user_defined_p (UNOP_COMPLEMENT, arg1))
- return value_x_unop (arg1, UNOP_COMPLEMENT, noside);
- else
- {
- unop_promote (exp->language_defn, exp->gdbarch, &arg1);
- return value_complement (arg1);
- }
+ return eval_op_complement (expect_type, exp, noside, op, arg1);
case UNOP_LOGICAL_NOT:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (unop_user_defined_p (op, arg1))
- return value_x_unop (arg1, op, noside);
- else
- {
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) value_logical_not (arg1));
- }
+ 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);
- type = check_typedef (value_type (arg1));
- if (type->code () == TYPE_CODE_METHODPTR
- || type->code () == TYPE_CODE_MEMBERPTR)
- error (_("Attempt to dereference pointer "
- "to member without an object"));
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (unop_user_defined_p (op, arg1))
- return value_x_unop (arg1, op, noside);
- else if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- type = check_typedef (value_type (arg1));
-
- /* If the type pointed to is dynamic then in order to resolve the
- dynamic properties we must actually dereference the pointer.
- There is a risk that this dereference will have side-effects
- in the inferior, but being able to print accurate type
- information seems worth the risk. */
- if ((type->code () != TYPE_CODE_PTR
- && !TYPE_IS_REFERENCE (type))
- || !is_dynamic_type (TYPE_TARGET_TYPE (type)))
- {
- if (type->code () == TYPE_CODE_PTR
- || TYPE_IS_REFERENCE (type)
- /* In C you can dereference an array to get the 1st elt. */
- || type->code () == TYPE_CODE_ARRAY)
- return value_zero (TYPE_TARGET_TYPE (type),
- lval_memory);
- else if (type->code () == TYPE_CODE_INT)
- /* GDB allows dereferencing an int. */
- return value_zero (builtin_type (exp->gdbarch)->builtin_int,
- lval_memory);
- else
- error (_("Attempt to take contents of a non-pointer value."));
- }
- }
-
- /* Allow * on an integer so we can cast it to whatever we want.
- This returns an int, which seems like the most C-like thing to
- do. "long long" variables are rare enough that
- BUILTIN_TYPE_LONGEST would seem to be a mistake. */
- if (type->code () == TYPE_CODE_INT)
- return value_at_lazy (builtin_type (exp->gdbarch)->builtin_int,
- (CORE_ADDR) value_as_address (arg1));
- return value_ind (arg1);
+ return eval_op_ind (expect_type, exp, noside, op, arg1);
case UNOP_ADDR:
/* C++: check for and handle pointer to members. */
return evaluate_subexp_for_sizeof (exp, pos, noside);
case UNOP_ALIGNOF:
- {
- type = value_type (
- evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS));
- /* FIXME: This should be size_t. */
- struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
- ULONGEST align = type_align (type);
- if (align == 0)
- error (_("could not determine alignment of type"));
- return value_from_longest (size_type, align);
- }
+ arg1 = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ return eval_op_alignof (expect_type, exp, noside, arg1);
case UNOP_CAST:
(*pos) += 2;
case UNOP_MEMVAL:
(*pos) += 2;
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value_zero (exp->elts[pc + 1].type, lval_memory);
- else
- return value_at_lazy (exp->elts[pc + 1].type,
- value_as_address (arg1));
+ 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);
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value_zero (type, lval_memory);
- else
- return value_at_lazy (type, value_as_address (arg1));
+ return eval_op_memval (expect_type, exp, noside, arg1, type);
case UNOP_PREINCREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- else if (unop_user_defined_p (op, arg1))
- {
- return value_x_unop (arg1, op, noside);
- }
- else
- {
- if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
- arg2 = value_ptradd (arg1, 1);
- else
- {
- struct value *tmp = arg1;
-
- arg2 = value_one (value_type (arg1));
- binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
- arg2 = value_binop (tmp, arg2, BINOP_ADD);
- }
-
- return value_assign (arg1, arg2);
- }
+ return eval_op_preinc (expect_type, exp, noside, op, arg1);
case UNOP_PREDECREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- else if (unop_user_defined_p (op, arg1))
- {
- return value_x_unop (arg1, op, noside);
- }
- else
- {
- if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
- arg2 = value_ptradd (arg1, -1);
- else
- {
- struct value *tmp = arg1;
-
- arg2 = value_one (value_type (arg1));
- binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
- arg2 = value_binop (tmp, arg2, BINOP_SUB);
- }
-
- return value_assign (arg1, arg2);
- }
+ return eval_op_predec (expect_type, exp, noside, op, arg1);
case UNOP_POSTINCREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- else if (unop_user_defined_p (op, arg1))
- {
- return value_x_unop (arg1, op, noside);
- }
- else
- {
- arg3 = value_non_lval (arg1);
-
- if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
- arg2 = value_ptradd (arg1, 1);
- else
- {
- struct value *tmp = arg1;
-
- arg2 = value_one (value_type (arg1));
- binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
- arg2 = value_binop (tmp, arg2, BINOP_ADD);
- }
-
- value_assign (arg1, arg2);
- return arg3;
- }
+ return eval_op_postinc (expect_type, exp, noside, op, arg1);
case UNOP_POSTDECREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- else if (unop_user_defined_p (op, arg1))
- {
- return value_x_unop (arg1, op, noside);
- }
- else
- {
- arg3 = value_non_lval (arg1);
-
- if (ptrmath_type_p (exp->language_defn, value_type (arg1)))
- arg2 = value_ptradd (arg1, -1);
- else
- {
- struct value *tmp = arg1;
-
- arg2 = value_one (value_type (arg1));
- binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
- arg2 = value_binop (tmp, arg2, BINOP_SUB);
- }
-
- value_assign (arg1, arg2);
- return arg3;
- }
+ return eval_op_postdec (expect_type, exp, noside, op, arg1);
case OP_THIS:
(*pos) += 1;
/* The value is not supposed to be used. This is here to make it
easier to accommodate expressions that contain types. */
(*pos) += 2;
- if (noside == EVAL_SKIP)
- return eval_skip_value (exp);
- else if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (exp->elts[pc + 1].type);
- else
- error (_("Attempt to use a type name as an expression"));
+ return eval_op_type (expect_type, exp, noside, exp->elts[pc + 1].type);
case OP_TYPEOF:
case OP_DECLTYPE:
gdb_assert_not_reached ("missed return?");
}
\f
+/* Helper for evaluate_subexp_for_address. */
+
+static value *
+evaluate_subexp_for_address_base (struct expression *exp, enum noside noside,
+ value *x)
+{
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct type *type = check_typedef (value_type (x));
+
+ if (TYPE_IS_REFERENCE (type))
+ return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+ not_lval);
+ else if (VALUE_LVAL (x) == lval_memory || value_must_coerce_to_target (x))
+ return value_zero (lookup_pointer_type (value_type (x)),
+ not_lval);
+ else
+ error (_("Attempt to take address of "
+ "value not located in memory."));
+ }
+ return value_addr (x);
+}
+
/* Evaluate a subexpression of EXP, at index *POS,
and return the address of that subexpression.
Advance *POS over the subexpression.
default_case:
x = evaluate_subexp (nullptr, exp, pos, noside);
default_case_after_eval:
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- struct type *type = check_typedef (value_type (x));
+ return evaluate_subexp_for_address_base (exp, noside, x);
+ }
+}
- if (TYPE_IS_REFERENCE (type))
- return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
- not_lval);
- else if (VALUE_LVAL (x) == lval_memory || value_must_coerce_to_target (x))
- return value_zero (lookup_pointer_type (value_type (x)),
- not_lval);
- else
- error (_("Attempt to take address of "
- "value not located in memory."));
- }
- return value_addr (x);
+namespace expr
+{
+
+value *
+operation::evaluate_for_cast (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ value *val = evaluate (expect_type, exp, noside);
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ return value_cast (expect_type, val);
+}
+
+value *
+operation::evaluate_for_address (struct expression *exp, enum noside noside)
+{
+ value *val = evaluate (nullptr, exp, noside);
+ return evaluate_subexp_for_address_base (exp, noside, val);
+}
+
+value *
+scope_operation::evaluate_for_address (struct expression *exp,
+ enum noside noside)
+{
+ value *x = value_aggregate_elt (std::get<0> (m_storage),
+ std::get<1> (m_storage).c_str (),
+ NULL, 1, noside);
+ if (x == NULL)
+ error (_("There is no field named %s"), std::get<1> (m_storage).c_str ());
+ return x;
+}
+
+value *
+var_msym_value_operation::evaluate_for_address (struct expression *exp,
+ enum noside noside)
+{
+ value *val = evaluate_var_msym_value (noside,
+ std::get<1> (m_storage),
+ std::get<0> (m_storage));
+ 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);
+}
+
}
/* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
}
}
+/* Helper function for evaluating the size of a type. */
+
+static value *
+evaluate_subexp_for_sizeof_base (struct expression *exp, struct type *type)
+{
+ /* FIXME: This should be size_t. */
+ struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
+ /* $5.3.3/2 of the C++ Standard (n3290 draft) says of sizeof:
+ "When applied to a reference or a reference type, the result is
+ the size of the referenced type." */
+ type = check_typedef (type);
+ if (exp->language_defn->la_language == language_cplus
+ && (TYPE_IS_REFERENCE (type)))
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ 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
break;
}
- /* $5.3.3/2 of the C++ Standard (n3290 draft) says of sizeof:
- "When applied to a reference or a reference type, the result is
- the size of the referenced type." */
- type = check_typedef (type);
- if (exp->language_defn->la_language == language_cplus
- && (TYPE_IS_REFERENCE (type)))
- type = check_typedef (TYPE_TARGET_TYPE (type));
- return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
+ return evaluate_subexp_for_sizeof_base (exp, type);
+}
+
+namespace expr
+{
+
+value *
+operation::evaluate_for_sizeof (struct expression *exp, enum noside noside)
+{
+ value *val = evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS);
+ return evaluate_subexp_for_sizeof_base (exp, value_type (val));
+}
+
+value *
+var_msym_value_operation::evaluate_for_sizeof (struct expression *exp,
+ enum noside noside)
+
+{
+ minimal_symbol *msymbol = std::get<0> (m_storage);
+ value *mval = evaluate_var_msym_value (noside,
+ std::get<1> (m_storage),
+ msymbol);
+
+ struct type *type = value_type (mval);
+ if (type->code () == TYPE_CODE_ERROR)
+ error_unknown_type (msymbol->print_name ());
+
+ /* FIXME: This should be size_t. */
+ struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
+ return value_from_longest (size_type, TYPE_LENGTH (type));
+}
+
}
/* Evaluate a subexpression of EXP, at index *POS, and return a value
return value_cast (to_type, val);
}
+namespace expr
+{
+
+value *
+var_msym_value_operation::evaluate_for_cast (struct type *to_type,
+ struct expression *exp,
+ enum noside noside)
+{
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (to_type, not_lval);
+
+ value *val = evaluate_var_msym_value (noside,
+ std::get<1> (m_storage),
+ std::get<0> (m_storage));
+
+ 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;
+}
+
+}
+
/* Parse a type expression in the string [P..P+LENGTH). */
struct type *