]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: handle struct and union types in evaluate_subexp_for_address_base
authorPiotr Rudnicki <piotr.rudnicki@intel.com>
Fri, 30 May 2025 13:21:49 +0000 (15:21 +0200)
committerPiotr Rudnicki <piotr.rudnicki@intel.com>
Tue, 3 Jun 2025 07:50:03 +0000 (09:50 +0200)
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.

gdb/eval.c
gdb/testsuite/gdb.cp/chained-calls.cc
gdb/testsuite/gdb.cp/chained-calls.exp

index 7601c3b0dddb94f9326cc85ce998c13caeacc871..539b700ad8ff08206efde54e6365fe5296aa7b05 100644 (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."));
index 9d12c988b4d2f515a2b7226f6fb4fc5793139312..9358c716b4433cd6353fffa8471474ee1bc2629e 100644 (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  */
 }
index 4f0597a0005e127e62e1ce5445ebff877c92a9ed..d34162c355b136c313a1d48fcc58816351f834a6 100644 (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()"