Re: [RFC PATCH 0/3] Pretty-printing for errno

Pedro Alves
2017-06-29T16:53:31Z

On 06/29/2017 04:48 PM, Phil Muldoon wrote:
>
> (gdb) p (test_i) i
> $2 = ('typename: ', 'int')
>
> Which is most puzzling.

Indeed. No need for printers to see this, actually.

With this code:

typedef int zzz;
zzz z;

gdb:

(gdb) whatis z
type = zzz
(gdb) whatis (zzz) z
type = int

Eh.

I suspect this is the result of a bogus implementation of
only stripping one level of typedef if the argument to
whatis is a type name. From the manual:

If @var{arg} is a variable or an expression, @code{whatis} prints its
literal type as it is used in the source code. If the type was
defined using a @code{typedef}, @code{whatis} will @emph{not} print
the data type underlying the @code{typedef}.
(...)
If @var{arg} is a type name that was defined using @code{typedef},
@code{whatis} @dfn{unrolls} only one level of that @code{typedef}.

That one-level stripping comes from here, in
gdb/eval.c:evaluate_subexp_standard, handling OP_TYPE:

...
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type = exp->elts[pc + 1].type;

/* If this is a typedef, then find its immediate target. We
use check_typedef to resolve stubs, but we ignore its
result because we do not want to dig past all
typedefs. */
check_typedef (type);
if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
type = TYPE_TARGET_TYPE (type);
return allocate_value (type);
}

However, this is reachable in both:

#1 - (gdb) whatis (zzz)0
#2 - (gdb) whatis zzz

While only case #2 should strip the typedef. Removing that "find immediate
target" code above help with fixing #1. We then run into the fact that
value_cast also drops typedefs. Fixing that (see patch below) makes
whatis (zzz)0 work as expected:

(gdb) whatis (zzz)0
type = zzz

however, we'd need to still make "whatis" strip one level of
typedefs when the argument is a type, somehow, because we now
get this:

(gdb) whatis zzz
type = zzz
From 21f3a88611fad22f73aff2217c93d99971dd076f Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Thu, 29 Jun 2017 17:18:32 +0100
Subject: [PATCH] whatis

---
gdb/eval.c | 2 ++
gdb/valops.c | 28 +++++++++++++++-------------
2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/gdb/eval.c b/gdb/eval.c
index 2a39774..6aa2499 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -2735,8 +2735,10 @@ evaluate_subexp_standard (struct type *expect_type,
result because we do not want to dig past all
typedefs. */
check_typedef (type);
+#if 0
if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
type = TYPE_TARGET_TYPE (type);
+#endif
return allocate_value (type);
}
else
diff --git a/gdb/valops.c b/gdb/valops.c
index 8675e6c..058fe1e 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -378,6 +378,8 @@ value_cast (struct type *type, struct value *arg2)
/* We deref the value and then do the cast. */
return value_cast (type, coerce_ref (arg2));

+ struct type *org_type = type;
+
type = check_typedef (type);
code1 = TYPE_CODE (type);
arg2 = coerce_ref (arg2);
@@ -452,14 +454,14 @@ value_cast (struct type *type, struct value *arg2)
&& (code2 == TYPE_CODE_STRUCT || code2 == TYPE_CODE_UNION)
&& TYPE_NAME (type) != 0)
{
- struct value *v = value_cast_structs (type, arg2);
+ struct value *v = value_cast_structs (org_type, arg2);

if (v)
return v;
}

if (code1 == TYPE_CODE_FLT && scalar)
- return value_from_double (type, value_as_double (arg2));
+ return value_from_double (org_type, value_as_double (arg2));
else if (code1 == TYPE_CODE_DECFLOAT && scalar)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -475,7 +477,7 @@ value_cast (struct type *type, struct value *arg2)
/* The only option left is an integral type. */
decimal_from_integral (arg2, dec, dec_len, byte_order);

- return value_from_decfloat (type, dec);
+ return value_from_decfloat (org_type, dec);
}
else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
|| code1 == TYPE_CODE_RANGE)
@@ -496,7 +498,7 @@ value_cast (struct type *type, struct value *arg2)
gdbarch_byte_order (get_type_arch (type2)));
else
longest = value_as_long (arg2);
- return value_from_longest (type, convert_to_boolean ?
+ return value_from_longest (org_type, convert_to_boolean ?
(LONGEST) (longest ? 1 : 0) : longest);
}
else if (code1 == TYPE_CODE_PTR && (code2 == TYPE_CODE_INT
@@ -522,14 +524,14 @@ value_cast (struct type *type, struct value *arg2)
|| longest <= -((LONGEST) 1 << addr_bit))
warning (_("value truncated"));
}
- return value_from_longest (type, longest);
+ return value_from_longest (org_type, longest);
}
else if (code1 == TYPE_CODE_METHODPTR && code2 == TYPE_CODE_INT
&& value_as_long (arg2) == 0)
{
- struct value *result = allocate_value (type);
+ struct value *result = allocate_value (org_type);

- cplus_make_method_ptr (type, value_contents_writeable (result), 0, 0);
+ cplus_make_method_ptr (org_type, value_contents_writeable (result), 0, 0);
return result;
}
else if (code1 == TYPE_CODE_MEMBERPTR && code2 == TYPE_CODE_INT
@@ -537,7 +539,7 @@ value_cast (struct type *type, struct value *arg2)
{
/* The Itanium C++ ABI represents NULL pointers to members as
minus one, instead of biasing the normal case. */
- return value_from_longest (type, -1);
+ return value_from_longest (org_type, -1);
}
else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
&& code2 == TYPE_CODE_ARRAY && TYPE_VECTOR (type2)
@@ -548,21 +550,21 @@ value_cast (struct type *type, struct value *arg2)
error (_("can only cast scalar to vector of same size"));
else if (code1 == TYPE_CODE_VOID)
{
- return value_zero (type, not_lval);
+ return value_zero (org_type, not_lval);
}
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
{
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
- return value_cast_pointers (type, arg2, 0);
+ return value_cast_pointers (org_type, arg2, 0);

arg2 = value_copy (arg2);
- deprecated_set_value_type (arg2, type);
- set_value_enclosing_type (arg2, type);
+ deprecated_set_value_type (arg2, org_type);
+ set_value_enclosing_type (arg2, org_type);
set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */
return arg2;
}
else if (VALUE_LVAL (arg2) == lval_memory)
- return value_at_lazy (type, value_address (arg2));
+ return value_at_lazy (org_type, value_address (arg2));
else
{
error (_("Invalid cast."));
--
2.5.5