gdb
authorTom Tromey <tromey@redhat.com>
Tue, 23 Jun 2009 16:26:05 +0000 (16:26 +0000)
committerTom Tromey <tromey@redhat.com>
Tue, 23 Jun 2009 16:26:05 +0000 (16:26 +0000)
PR gdb/10309:
* c-lang.c (classify_type): Iterate over typedefs.
* c-valprint.c (textual_element_type): Iterate over typedefs.
gdb/testsuite
* gdb.base/charset.exp (test_combination): Regression test.
* gdb.base/charset.c (my_wchar_t): New typedef.
(myvar): New global.
(main): Set myvar.

gdb/ChangeLog
gdb/c-lang.c
gdb/c-valprint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/charset.c
gdb/testsuite/gdb.base/charset.exp

index ecb49bb..e6d9f2e 100644 (file)
@@ -1,3 +1,9 @@
+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-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        PR gdb/9988:
index 898ae8d..5718143 100644 (file)
@@ -77,9 +77,12 @@ classify_type (struct type *elttype, const char **encoding)
   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 @@ classify_type (struct type *elttype, const char **encoding)
          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 3433da2..b2020f3 100644 (file)
@@ -81,23 +81,42 @@ textual_name (const char *name)
 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 f7572b3..1a442a5 100644 (file)
@@ -1,3 +1,10 @@
+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.
+
 2009-06-18  Pierre Muller  <muller@ics.u-strasbg.fr>
 
        * lib/gdb.exp (gdb_compile): Also force unbuffered mode for DJGPP
index 55a50ce..b61e047 100644 (file)
@@ -65,6 +65,10 @@ typedef unsigned int char32_t;
 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 @@ int main ()
 
   init_ucs4 ();
 
+  myvar = ucs_4_string[7];
+
   return 0;            /* all strings initialized */
 }
index 8c23848..85885c8 100644 (file)
@@ -599,6 +599,9 @@ if {$wchar_ok && $ucs2_ok} {
 }
 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