]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/exp] Redo cast handling for indirection
authorTom de Vries <tdevries@suse.de>
Mon, 6 May 2024 12:23:25 +0000 (14:23 +0200)
committerTom de Vries <tdevries@suse.de>
Mon, 6 May 2024 12:23:25 +0000 (14:23 +0200)
In commit ed8fd0a342f ("[gdb/exp] Fix cast handling for indirection"), I
introduced the behaviour that even though we have:
...
(gdb) p *a_loc ()
'a_loc' has unknown return type; cast the call to its declared return type
...
we get:
...
(gdb) p (char)*a_loc ()
$1 = 97 'a'
...

In other words, the unknown return type of a_loc is inferred from the cast,
effectually evaluating:
...
(gdb) p (char)*(char *)a_loc ()
...

This is convient for the case that errno is defined as:
...
 #define errno (*__errno_location ())
...
and the return type of __errno_location is unknown but the macro definition is
known, such that we can use:
...
(gdb) p (int)errno
...
instead of
...
(gdb) p *(int *)__errno_location ()
...

However, as Pedro has pointed out in post-commit review [1], this makes it
harder to reason about the semantics of an expression.

For instance, this:
...
(gdb) p (long long)*a_loc ()"
...
would be evaluated without debug info as:
...
(gdb) p (long long)*(long long *)a_loc ()"
...
but with debug info as:
...
(gdb) p (long long)*(char *)a_loc ()"
...

Fix this by instead simply erroring out for this case:
...
(gdb) p (char)*a_loc ()
'a_loc' has unknown return type; cast the call to its declared return type
...

Tested on x86_64-linux.

Approved-By: Pedro Alves <pedro@palves.net>
[1] https://sourceware.org/pipermail/gdb-patches/2024-May/208821.html

gdb/expop.h
gdb/testsuite/gdb.base/cast-indirection.exp

index 1967d9779b7302fda3ee96380c0bb405b44b78ef..2d46a9dad6a75824ad5109115fad98c9a2a84770 100644 (file)
@@ -1513,11 +1513,8 @@ public:
                   struct expression *exp,
                   enum noside noside) override
   {
-    struct type *pointer_to_expect_type = (expect_type != nullptr
-                                          ? lookup_pointer_type (expect_type)
-                                          : nullptr);
     value *val
-      = std::get<0> (m_storage)->evaluate (pointer_to_expect_type, exp, noside);
+      = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
     return eval_op_ind (expect_type, exp, noside, val);
   }
 
index d2c6d58e3ca4c3e516abec2d3bf35d6060739a85..7b9b5a5d6771bd376ebb6b6b9e4d77f37e7830ff 100644 (file)
@@ -13,7 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
+# Check that "p (char)*a_loc ()" is handled correctly.
 
 standard_testfile
 
@@ -37,4 +37,5 @@ gdb_test "p *(char *)a_loc ()" " = 97 'a'"
 gdb_test "p (char)*(char *)a_loc ()" " = 97 'a'"
 
 # Regression test for PR31693.
-gdb_test "p (char)*a_loc ()" " = 97 'a'"
+gdb_test "p (char)*a_loc ()" \
+    "'a_loc' has unknown return type; cast the call to its declared return type"