gdb: resolve type to target_type in expression evaluation
If an expression is evaluated with 'EVAL_AVOID_SIDE_EFFECTS', we're
essentially interested in compatibility of the operands. If there is an
operand of reference type, this would give us a memory value that would
cause a failure if GDB attempts to access the contents.
GDB fails to evaluate binary expressions for the following example:
Expression evaluation uses helper functions such as 'value_equal',
'value_logical_not', etc. These helper functions do not take a 'noside'
argument and if one of their value arguments was created from a function
call that returns a reference type when noside == EVAL_AVOID_SIDE_EFFECTS,
GDB attempts to read from an invalid memory location. Consider the
following call stack of the 'ptype v_struct.get () + 1' command at the time
of assertion when the memory error is raised:
#0 memory_error (err=TARGET_XFER_E_IO, memaddr=0) at gdb/corefile.c:114
#1 read_value_memory (val=.., bit_offset=0, stack=false, memaddr=0,
buffer=.. "", length=4) at gdb/valops.c:1075
#2 value::fetch_lazy_memory (this=..) at gdb/value.c:3996
#3 value::fetch_lazy (this=..) at gdb/value.c:4135
#4 value::contents_writeable (this=..) at gdb/value.c:1329
#5 value::contents (this=..) at gdb/value.c:1319
#6 value_as_mpz (val=..) at gdb/value.c:2685
#7 scalar_binop (arg1=.., arg2=.., op=BINOP_ADD) at gdb/valarith.c:1240
#8 value_binop (arg1=.., arg2=.., op=BINOP_ADD) at gdb/valarith.c:1489
#9 eval_op_add (expect_type=0x0, exp=.., noside=EVAL_AVOID_SIDE_EFFECTS,
arg1=.., arg2=..) at gdb/eval.c:1333
#10 expr::add_operation::evaluate (this=.., expect_type=0x0, exp=..,
noside=EVAL_AVOID_SIDE_EFFECTS) at gdb/expop.h:1209
#11 expression::evaluate (this=.., expect_type=0x0,
noside=EVAL_AVOID_SIDE_EFFECTS) at gdb/eval.c:110
#12 expression::evaluate_type (this=..) at gdb/expression.h:242
'add_operation::evaluate' calls the helper 'eval_op_add' which attempts
to read from the unresolved memory location. Convert to the target type
to avoid such problems. The patch is implemented in 'expop.h' for the
following reasons:
* Support templated classes without explicit helpers, e.g.,
'binop_operation' and 'comparison_operation'.
* Stripping references in 'binop_promote' requires additional
refactoring beyond this patch as we would need to carry on the
'noside' parameter.
The above failures are resolved with the patch:
(gdb) print v_struct.get () == 1 && v_struct3.get () == 2
$1 = false
(gdb) print v_struct.get () == 1 || v_struct3.get () == 2
$2 = true
(gdb) ptype v_struct.get ()
type = int &
(gdb) ptype v_struct.get () == 1
type = bool
(gdb) ptype v_struct.get () + 1
type = int
(gdb) ptype v_struct.get () && 1
type = bool
(gdb) ptype v_struct.get () || 1
type = bool
(gdb) ptype !v_struct.get ()
type = bool
(gdb) ptype v_struct.get () ? 2 : 3
type = int
(gdb) ptype v_struct.get () | 1
type = int
Co-Authored-By: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com> Approved-By: Tom Tromey <tom@tromey.com>