This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[pushed] Fix gdb.base/whatis-ptype-typedefs.exp on 32-bit archs (Re: [PATCH] Fix type casts losing typedefs and reimplement "whatis" typedef stripping)


On 11/20/2017 10:34 PM, Yao Qi wrote:
> On 17-11-20 16:42:48, Pedro Alves wrote:
>>
>> So in that spirit, I propose starting my making the testcase adjust
>> itself, like below, and also test floats of different sizes, leaving
>> changing GDB's behavior for a separate consideration/change (using
>> the fixed/extended test as baseline).
>>
> 
> I agree.  Some tests fail on 32-bit at the point when they were added,
> so tests should match gdb's behaviour.  As usual, we can gdb behaviour
> after we are sure the behaviour is incorrect.
> 
> Beside Simon's review, patch is good to me.

Thanks guys.  Here's what I checked in.

>From 73fcf6418ddce47ead4ffde4fc9fea8e8bd1f4af Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 20 Nov 2017 23:03:17 +0000
Subject: [PATCH] Fix gdb.base/whatis-ptype-typedefs.exp on 32-bit archs

The gdb.base/whatis-ptype-typedefs.exp testcase has several tests that
fail on 32-bit architectures.  E.g., on 'x86-64 -m32', I see:

 ...
 FAIL: gdb.base/whatis-ptype-typedefs.exp: lang=c: cast: whatis (float_typedef) v_uchar_array_t_struct_typedef (invalid)
 FAIL: gdb.base/whatis-ptype-typedefs.exp: lang=c: cast: ptype (float_typedef) v_uchar_array_t_struct_typedef (invalid)
 ...

gdb.log:

 (gdb) whatis (float_typedef) v_uchar_array_t_struct_typedef
 type = float_typedef
 (gdb) FAIL: gdb.base/whatis-ptype-typedefs.exp: lang=c: cast: whatis (float_typedef) v_uchar_array_t_struct_typedef (invalid)

As Simon explained [1], the issue boils down to the fact that on
64-bit, this is an invalid cast:

 (gdb) p (float_typedef) v_uchar_array_t_struct_typedef
 Invalid cast.

while on 32 bits it is valid:

 (gdb) p (float_typedef) v_uchar_array_t_struct_typedef
 $1 = 1.16251721e-41

The expression basically tries to cast an array (which decays to a
pointer) to a float.  The cast works on 32 bits because a float and a
pointer are of the same size, and value_cast works in that case:

~~~
   More general than a C cast: accepts any two types of the same length,
   and if ARG2 is an lvalue it can be cast into anything at all.  */
~~~

On 64 bits, they are not the same size, so it ends throwing the
"Invalid cast" error.

The testcase is expecting the invalid cast behavior, thus the FAILs.

A point of these tests was to cover as many code paths in value_cast
as possible, as a sort of documentation of the current behavior:

    # The main idea here is testing all the different paths in the
    # value casting code in GDB (value_cast), making sure typedefs are
    # preserved.
...
    # We try all combinations, even those that don't parse, or are
    # invalid, to catch the case of a regression making them
    # inadvertently valid.  For example, these convertions are
    # invalid:
...

In that spirit, this commit makes the testcase adjust itself depending
on size of floats and pointers, and also test floats of different
sizes.

Passes cleanly on x86-64 GNU/Linux both -m64/-m32.

[1] - https://sourceware.org/ml/gdb-patches/2017-11/msg00382.html

gdb/ChangeLog:
2017-11-20  Pedro Alves  <palves@redhat.com>

	* gdb.base/whatis-ptype-typedefs.c (double_typedef)
	(long_double_typedef): New typedefs.
	Use DEF on double and long double.
	* gdb.base/whatis-ptype-typedefs.exp: Add double and long double
	cases.
	(run_tests): New 'float_ptr_same_size', 'double_ptr_same_size',
	and 'long_double_ptr_same_size' locals.  Use them to decide
	whether cast from array/function to float is valid/invalid.
---
 gdb/testsuite/ChangeLog                          | 11 +++++++
 gdb/testsuite/gdb.base/whatis-ptype-typedefs.c   | 10 ++++++
 gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp | 39 ++++++++++++++++++++++--
 3 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 12938e7..fa329b4 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2017-11-20  Pedro Alves  <palves@redhat.com>
+
+	* gdb.base/whatis-ptype-typedefs.c (double_typedef)
+	(long_double_typedef): New typedefs.
+	Use DEF on double and long double.
+	* gdb.base/whatis-ptype-typedefs.exp: Add double and long double
+	cases.
+	(run_tests): New 'float_ptr_same_size', 'double_ptr_same_size',
+	and 'long_double_ptr_same_size' locals.  Use them to decide
+	whether cast from array/function to float is valid/invalid.
+
 2017-11-17  Tom Tromey  <tom@tromey.com>
 
 	* gdb.rust/traits.rs: New file.
diff --git a/gdb/testsuite/gdb.base/whatis-ptype-typedefs.c b/gdb/testsuite/gdb.base/whatis-ptype-typedefs.c
index 5711a96..35c7279 100644
--- a/gdb/testsuite/gdb.base/whatis-ptype-typedefs.c
+++ b/gdb/testsuite/gdb.base/whatis-ptype-typedefs.c
@@ -56,6 +56,16 @@ DEF (int);
 typedef float float_typedef;
 DEF (float);
 
+/* Double floats.  */
+
+typedef double double_typedef;
+DEF (double);
+
+/* Long doubles.  */
+
+typedef long double long_double_typedef;
+DEF (long_double);
+
 /* Enums.  */
 
 typedef enum colors {red, green, blue} colors_typedef;
diff --git a/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp b/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp
index d333d81..ea0ef6c 100644
--- a/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp
+++ b/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp
@@ -92,6 +92,16 @@ set table {
     {"v_float_typedef"    "float_typedef"    "float"}
     {"v_float_typedef2"   "float_typedef2"   "float"}
 
+    {"double_typedef"     "double"           "double"}
+    {"double_typedef2"    "double_typedef"   "double"}
+    {"v_double_typedef"   "double_typedef"   "double"}
+    {"v_double_typedef2"  "double_typedef2"  "double"}
+
+    {"long_double_typedef"    "long double"           "long double"}
+    {"long_double_typedef2"   "long_double_typedef"   "long double"}
+    {"v_long_double_typedef"  "long_double_typedef"   "long double"}
+    {"v_long_double_typedef2" "long_double_typedef2"  "long double"}
+
     {"colors_typedef"     "(enum )?colors"   "enum colors( : unsigned int)? {red, green, blue}"}
     {"colors_typedef2"    "colors_typedef"   "enum colors( : unsigned int)? {red, green, blue}"}
     {"v_colors_typedef"   "colors_typedef"   "enum colors( : unsigned int)? {red, green, blue}"}
@@ -199,6 +209,22 @@ proc run_tests {lang} {
 	}
     }
 
+    # If floats and pointers have the same size on this architecture,
+    # then casting from array/function to float works, because
+    # arrays/functions first decay to pointers, and then GDB's cast is
+    # more general than a C cast and accepts any two types of the same
+    # length.
+    set float_ptr_same_size \
+	[get_integer_valueof "sizeof (float) == sizeof (void *)" -1]
+
+    # Ditto double.
+    set double_ptr_same_size \
+	[get_integer_valueof "sizeof (double) == sizeof (void *)" -1]
+
+    # Ditto long double.
+    set long_double_ptr_same_size \
+	[get_integer_valueof "sizeof (long double) == sizeof (void *)" -1]
+
     # Test converting/casting all variables in the first column of the
     # table to all types (found in the first column of the table).
     # The aggregates are all defined to be the same size so that
@@ -230,7 +256,7 @@ proc run_tests {lang} {
 		# regression making them inadvertently valid.  For
 		# example, these convertions are invalid:
 		#
-		#  float <-> array
+		#  float <-> array   [iff sizeof pointer != sizeof float]
 		#  array -> function (not function pointer)
 		#  array -> member_ptr
 		#
@@ -247,8 +273,15 @@ proc run_tests {lang} {
 		    gdb_test "whatis ($to) $from" "syntax error.*" "whatis ($to) $from (syntax)"
 		    gdb_test "ptype ($to) $from" "syntax error.*" "ptype ($to) $from (syntax)"
 		} elseif {([string match "*float*" $from] && [string match "*array*" $to])
-			  || ([string match "float*" $to] && [string match "*array*" $from])
-			  || ([string match "float*" $to] && [string match "*method" $from])
+			  || (!$float_ptr_same_size
+			      && ([string match "float*" $to] && [string match "*array*" $from]
+				  || [string match "float*" $to] && [string match "*method" $from]))
+			  || (!$double_ptr_same_size
+			      && ([string match "double*" $to] && [string match "*array*" $from]
+				  || [string match "double*" $to] && [string match "*method" $from]))
+			  || (!$long_double_ptr_same_size
+			      && ([string match "long_double*" $to] && [string match "*array*" $from]
+				  || [string match "long_double*" $to] && [string match "*method" $from]))
 			  || ([string match "*ftype" $to] && [string match "*array*" $from])
 			  || ([string match "*ftype2" $to] && [string match "*array*" $from])
 			  || ([string match "*ftype" $to] && [string match "*method" $from])
-- 
2.5.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]