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]

FYI: fix PR 10309


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


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