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:
Piotr Rudnicki
2025-05-30 15:21:49 +02:00
parent 7b91a240d6
commit a8f4696286
3 changed files with 23 additions and 1 deletions

View File

@@ -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."));

View File

@@ -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 */
}

View File

@@ -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()"