aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/c-lang.c27
-rw-r--r--gdb/c-valprint.c31
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.base/charset.c6
-rw-r--r--gdb/testsuite/gdb.base/charset.exp3
6 files changed, 68 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ecb49bb..e6d9f2e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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:
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 898ae8d..5718143 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -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;
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index 3433da2..b2020f3 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -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')
{
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index f7572b3..1a442a5 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
diff --git a/gdb/testsuite/gdb.base/charset.c b/gdb/testsuite/gdb.base/charset.c
index 55a50ce..b61e047 100644
--- a/gdb/testsuite/gdb.base/charset.c
+++ b/gdb/testsuite/gdb.base/charset.c
@@ -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 */
}
diff --git a/gdb/testsuite/gdb.base/charset.exp b/gdb/testsuite/gdb.base/charset.exp
index 8c23848..85885c8 100644
--- a/gdb/testsuite/gdb.base/charset.exp
+++ b/gdb/testsuite/gdb.base/charset.exp
@@ -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