This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
FYI: fix PR 10309
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 23 Jun 2009 10:25:30 -0600
- Subject: FYI: fix PR 10309
- Reply-to: tromey at redhat dot com
I'm checking this in.
This fixes PR 10309. The bug is that gdb will not correctly print a
string whose underlying char type is a typedef to wchar_t, when the
program is written in C. This is because, in C, wchar_t is itself a
typedef, and check_typedef strips all typedefs. The fix is to strip a
single typedef at a time.
Built and regtested on x86-64 (compile farm).
Regression test included.
Tom
2009-06-23 Tom Tromey <tromey@redhat.com>
PR gdb/10309:
* c-lang.c (classify_type): Iterate over typedefs.
* c-valprint.c (textual_element_type): Iterate over typedefs.
2009-06-23 Tom Tromey <tromey@redhat.com>
* gdb.base/charset.exp (test_combination): Regression test.
* gdb.base/charset.c (my_wchar_t): New typedef.
(myvar): New global.
(main): Set myvar.
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.71
diff -u -r1.71 c-lang.c
--- c-lang.c 17 Jun 2009 18:47:35 -0000 1.71
+++ c-lang.c 23 Jun 2009 16:23:14 -0000
@@ -77,9 +77,12 @@
struct type *saved_type;
enum c_string_type result;
- /* We do one or two passes -- one on ELTTYPE, and then maybe a
- second one on a typedef target. */
- do
+ /* We loop because ELTTYPE may be a typedef, and we want to
+ successively peel each typedef until we reach a type we
+ understand. We don't use CHECK_TYPEDEF because that will strip
+ all typedefs at once -- but in C, wchar_t is itself a typedef, so
+ that would do the wrong thing. */
+ while (elttype)
{
char *name = TYPE_NAME (elttype);
@@ -107,10 +110,22 @@
goto done;
}
- saved_type = elttype;
- CHECK_TYPEDEF (elttype);
+ if (TYPE_CODE (elttype) != TYPE_CODE_TYPEDEF)
+ break;
+
+ /* Call for side effects. */
+ check_typedef (elttype);
+
+ if (TYPE_TARGET_TYPE (elttype))
+ elttype = TYPE_TARGET_TYPE (elttype);
+ else
+ {
+ /* Perhaps check_typedef did not update the target type. In
+ this case, force the lookup again and hope it works out.
+ It never will for C, but it might for C++. */
+ CHECK_TYPEDEF (elttype);
+ }
}
- while (elttype != saved_type);
/* Punt. */
result = C_CHAR;
Index: c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.57
diff -u -r1.57 c-valprint.c
--- c-valprint.c 28 May 2009 00:53:51 -0000 1.57
+++ c-valprint.c 23 Jun 2009 16:23:14 -0000
@@ -81,23 +81,42 @@
static int
textual_element_type (struct type *type, char format)
{
- struct type *true_type = check_typedef (type);
+ struct type *true_type, *iter_type;
if (format != 0 && format != 's')
return 0;
+ /* We also rely on this for its side effect of setting up all the
+ typedef pointers. */
+ true_type = check_typedef (type);
+
/* TYPE_CODE_CHAR is always textual. */
if (TYPE_CODE (true_type) == TYPE_CODE_CHAR)
return 1;
+
/* Any other character-like types must be integral. */
if (TYPE_CODE (true_type) != TYPE_CODE_INT)
return 0;
- /* Check the names of the type and the typedef. */
- if (TYPE_NAME (type) && textual_name (TYPE_NAME (type)))
- return 1;
- if (TYPE_NAME (true_type) && textual_name (TYPE_NAME (true_type)))
- return 1;
+ /* We peel typedefs one by one, looking for a match. */
+ iter_type = type;
+ while (iter_type)
+ {
+ /* Check the name of the type. */
+ if (TYPE_NAME (iter_type) && textual_name (TYPE_NAME (iter_type)))
+ return 1;
+
+ if (TYPE_CODE (iter_type) != TYPE_CODE_TYPEDEF)
+ break;
+
+ /* Peel a single typedef. If the typedef doesn't have a target
+ type, we use check_typedef and hope the result is ok -- it
+ might be for C++, where wchar_t is a built-in type. */
+ if (TYPE_TARGET_TYPE (iter_type))
+ iter_type = TYPE_TARGET_TYPE (iter_type);
+ else
+ iter_type = check_typedef (iter_type);
+ }
if (format == 's')
{
Index: testsuite/gdb.base/charset.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/charset.c,v
retrieving revision 1.9
diff -u -r1.9 charset.c
--- testsuite/gdb.base/charset.c 20 Mar 2009 23:04:39 -0000 1.9
+++ testsuite/gdb.base/charset.c 23 Jun 2009 16:23:15 -0000
@@ -65,6 +65,10 @@
char16_t uvar;
char32_t Uvar;
+/* A typedef to a typedef should also work. */
+typedef wchar_t my_wchar_t;
+my_wchar_t myvar;
+
void
init_string (char string[],
char x,
@@ -169,5 +173,7 @@
init_ucs4 ();
+ myvar = ucs_4_string[7];
+
return 0; /* all strings initialized */
}
Index: testsuite/gdb.base/charset.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/charset.exp,v
retrieving revision 1.14
diff -u -r1.14 charset.exp
--- testsuite/gdb.base/charset.exp 15 Apr 2009 21:55:04 -0000 1.14
+++ testsuite/gdb.base/charset.exp 23 Jun 2009 16:23:15 -0000
@@ -599,6 +599,9 @@
}
if {$wchar_ok && $ucs4_ok} {
test_combination L wide U UCS-4
+ # Regression test for a typedef to a typedef.
+ gdb_test "print myvar" "= \[0-9\]+ L'A'" \
+ "typedef to wchar_t"
}
if {$ucs2_ok && $ucs4_ok} {
test_combination u UCS-2 U UCS-4