+ 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 (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 (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 (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);