forked from Imagelibrary/binutils-gdb
gdb: handle struct and union types in evaluate_subexp_for_address_base
Suppose a function returns a struct and a method of that struct is
called. E.g.:
struct S
{
int a;
int get () { return a; }
};
S f ()
{
S s;
s.a = 42;
return s;
}
...
int z = f().get();
...
GDB is able to evaluate the expression:
(gdb) print f().get()
$1 = 42
However, type-checking the expression fails:
(gdb) ptype f().get()
Attempt to take address of value not located in memory.
This happens because the `get` function takes an implicit `this`
pointer, which in this case is the value returned by `f()`, and GDB
wants to get an address for that value, as if passing the implicit
this pointer. However, during type-checking, the struct value
returned by `f()` is a `not_lval`.
A similar issue exists for union types, where methods called on
temporary union objects would fail type-checking in the same way.
Address the problems by handling `TYPE_CODE_STRUCT` and
`TYPE_CODE_UNION` in `evaluate_subexp_for_address_base`.
With this change, for struct's method call, we get
(gdb) ptype f().get()
type = int
Add new test cases to file gdb.cp/chained-calls.exp to test this change.
Regression-tested in X86-64 Linux.
This commit is contained in:
@@ -2566,11 +2566,13 @@ evaluate_subexp_for_address_base (enum noside noside, value *x)
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
{
|
||||
struct type *type = check_typedef (x->type ());
|
||||
enum type_code typecode = type->code ();
|
||||
|
||||
if (TYPE_IS_REFERENCE (type))
|
||||
return value::zero (lookup_pointer_type (type->target_type ()),
|
||||
not_lval);
|
||||
else if (x->lval () == lval_memory || value_must_coerce_to_target (x))
|
||||
else if (x->lval () == lval_memory || value_must_coerce_to_target (x)
|
||||
|| typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
|
||||
return value::zero (lookup_pointer_type (x->type ()), not_lval);
|
||||
else
|
||||
error (_("Attempt to take address of value not located in memory."));
|
||||
|
||||
@@ -23,6 +23,8 @@ public:
|
||||
|
||||
S operator+ (const S &s);
|
||||
|
||||
int get ();
|
||||
|
||||
int a;
|
||||
};
|
||||
|
||||
@@ -41,6 +43,12 @@ S::operator+ (const S &s)
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
S::get ()
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
S
|
||||
f (int i)
|
||||
{
|
||||
@@ -162,6 +170,8 @@ public:
|
||||
U (type t);
|
||||
type get_type ();
|
||||
|
||||
int get ();
|
||||
|
||||
int a;
|
||||
char c;
|
||||
type tp[2];
|
||||
@@ -190,6 +200,12 @@ U::get_type ()
|
||||
return tp[TYPE_INDEX];
|
||||
}
|
||||
|
||||
int
|
||||
U::get ()
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
@@ -198,6 +214,7 @@ main ()
|
||||
|
||||
B b = makeb ();
|
||||
C c;
|
||||
int z = f (42).get ();
|
||||
|
||||
return i + getb(b, 0); /* Break here */
|
||||
}
|
||||
|
||||
@@ -42,3 +42,6 @@ gdb_test "p *c" ".* = {a = 5678}" "*c"
|
||||
gdb_test "p *c + *c" ".* = {a = 11356}" "*c + *c"
|
||||
gdb_test "p q(*c + *c)" ".* = {a = 11356}" "q(*c + *c)"
|
||||
gdb_test "p make_int().get_type ()" ".* = INT" "make_int().get_type ()"
|
||||
gdb_test "p f(42).get()" " = 42" "f().get()"
|
||||
gdb_test "ptype f(42).get()" "type = int" "ptype f().get()"
|
||||
gdb_test "ptype make_int().get()" "type = int" "make_int().get()"
|
||||
|
||||
Reference in New Issue
Block a user