This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch] fix exp/12117
- From: dje at google dot com (Doug Evans)
- To: gdb-patches at sourceware dot org
- Date: Wed, 13 Oct 2010 10:53:08 -0700 (PDT)
- Subject: [patch] fix exp/12117
Hi.
This patch fixes pr exp/12117.
http://sourceware.org/bugzilla/show_bug.cgi?id=12117
I will check this in in two days if there are no objections.
2010-10-13 Doug Evans <dje@google.com>
PR exp/12117
* c-typeprint.c (c_print_type): Call CHECK_TYPEDEF after calling
c_type_print_base.
(c_type_print_modifier_flags): New function.
(c_type_print_modifier): Call it.
(c_type_print_base): Collect instance_flags while we're stripping
typedefs. Change calls to c_type_print_modifier to call
c_type_print_modifier_flags instead.
(c_type_print_base, case TYPE_CODE_TYPEDEF): Verify assumptions of
when this case happens. Print "<unnamed typedef>".
* gdbtypes.h (strip_typedefs): Declare.
* gdbtypes.c (strip_typedefs): New function.
(check_typedef): Call it.
testsuite/
* gdb.cp/pr12117.cc: New file.
* gdb.cp/pr12117.exp: New file.
Index: c-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-typeprint.c,v
retrieving revision 1.62
diff -u -p -r1.62 c-typeprint.c
--- c-typeprint.c 13 Oct 2010 15:10:10 -0000 1.62
+++ c-typeprint.c 13 Oct 2010 17:29:30 -0000
@@ -53,10 +53,13 @@ c_print_type (struct type *type, const c
int demangled_args;
int need_post_space;
+ c_type_print_base (type, stream, show, level);
+
+ /* Do this *after* calling c_type_print_base so that it can see any
+ const/volatile flags that may be encoded in a typedef. */
if (show > 0)
CHECK_TYPEDEF (type);
- c_type_print_base (type, stream, show, level);
code = TYPE_CODE (type);
if ((varstring != NULL && *varstring != '\0')
/* Need a space if going to print stars or brackets;
@@ -313,23 +316,20 @@ c_type_print_varspec_prefix (struct type
/* Print out "const" and "volatile" attributes,
and address space id if present.
- TYPE is a pointer to the type being printed out.
+ FLAGS is the TYPE_INSTANCE_FLAGS flags of the type.
STREAM is the output destination.
NEED_PRE_SPACE = 1 indicates an initial white space is needed.
NEED_POST_SPACE = 1 indicates a final white space is needed. */
static void
-c_type_print_modifier (struct type *type, struct ui_file *stream,
- int need_pre_space, int need_post_space)
+c_type_print_modifier_flags (int flags, struct ui_file *stream,
+ struct gdbarch *gdbarch,
+ int need_pre_space, int need_post_space)
{
int did_print_modifier = 0;
const char *address_space_id;
- /* We don't print `const' qualifiers for references --- since all
- operators affect the thing referenced, not the reference itself,
- every reference is `const'. */
- if (TYPE_CONST (type)
- && TYPE_CODE (type) != TYPE_CODE_REF)
+ if (flags & TYPE_INSTANCE_FLAG_CONST)
{
if (need_pre_space)
fprintf_filtered (stream, " ");
@@ -337,7 +337,7 @@ c_type_print_modifier (struct type *type
did_print_modifier = 1;
}
- if (TYPE_VOLATILE (type))
+ if (flags & TYPE_INSTANCE_FLAG_VOLATILE)
{
if (did_print_modifier || need_pre_space)
fprintf_filtered (stream, " ");
@@ -345,8 +345,7 @@ c_type_print_modifier (struct type *type
did_print_modifier = 1;
}
- address_space_id = address_space_int_to_name (get_type_arch (type),
- TYPE_INSTANCE_FLAGS (type));
+ address_space_id = address_space_int_to_name (gdbarch, flags);
if (address_space_id)
{
if (did_print_modifier || need_pre_space)
@@ -359,6 +358,24 @@ c_type_print_modifier (struct type *type
fprintf_filtered (stream, " ");
}
+/* Wrapper for c_type_print_modifier_flags.
+ Print the modifier flags for TYPE. */
+
+static void
+c_type_print_modifier (struct type *type, struct ui_file *stream,
+ int need_pre_space, int need_post_space)
+{
+ int instance_flags = TYPE_INSTANCE_FLAGS (type);
+
+ /* We don't print `const' qualifiers for references --- since all
+ operators affect the thing referenced, not the reference itself,
+ every reference is `const'. */
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ instance_flags &= ~TYPE_INSTANCE_FLAG_CONST;
+
+ c_type_print_modifier_flags (instance_flags, stream, get_type_arch (type),
+ need_pre_space, need_post_space);
+}
/* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD
or TYPE_CODE_FUNC, to STREAM. Artificial arguments, such as "this"
@@ -678,6 +695,8 @@ c_type_print_base (struct type *type, st
section_type;
int need_access_label = 0;
int j, len2;
+ int instance_flags;
+ struct gdbarch *gdbarch;
QUIT;
@@ -702,11 +721,33 @@ c_type_print_base (struct type *type, st
return;
}
+ /* Handle typedefs specially because we want to strip them, but as we're
+ stripping them we need to keep track of any instance-related flags,
+ e.g., const/volatile. Furthermore, we would like to print the flags
+ once, and in a consistent order, so just accumulate them as we're
+ stripping. */
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ type = strip_typedefs (type, &instance_flags);
+ else
+ instance_flags = 0;
+
+ /* We've already stripped typedefs, but we still need to try to
+ update stubbed structs, etc. */
CHECK_TYPEDEF (type);
+ instance_flags |= TYPE_INSTANCE_FLAGS (type);
+ gdbarch = get_type_arch (type);
+
switch (TYPE_CODE (type))
{
case TYPE_CODE_TYPEDEF:
+ /* If we get here, the typedef doesn't have a name, and we couldn't
+ resolve TYPE_TARGET_TYPE. Not much we can do. */
+ gdb_assert (TYPE_NAME (type) == NULL);
+ gdb_assert (TYPE_TARGET_TYPE (type) == NULL);
+ fprintf_filtered (stream, _("<unnamed typedef>"));
+ break;
+
case TYPE_CODE_ARRAY:
case TYPE_CODE_PTR:
case TYPE_CODE_MEMBERPTR:
@@ -718,7 +759,7 @@ c_type_print_base (struct type *type, st
break;
case TYPE_CODE_STRUCT:
- c_type_print_modifier (type, stream, 0, 1);
+ c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
if (TYPE_DECLARED_CLASS (type))
fprintf_filtered (stream, "class ");
else
@@ -726,7 +767,7 @@ c_type_print_base (struct type *type, st
goto struct_union;
case TYPE_CODE_UNION:
- c_type_print_modifier (type, stream, 0, 1);
+ c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
fprintf_filtered (stream, "union ");
struct_union:
@@ -1083,7 +1124,7 @@ c_type_print_base (struct type *type, st
break;
case TYPE_CODE_ENUM:
- c_type_print_modifier (type, stream, 0, 1);
+ c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
fprintf_filtered (stream, "enum ");
/* Print the tag name if it exists.
The aCC compiler emits a spurious
@@ -1157,7 +1198,7 @@ c_type_print_base (struct type *type, st
is no type name, then complain. */
if (TYPE_NAME (type) != NULL)
{
- c_type_print_modifier (type, stream, 0, 1);
+ c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
fputs_filtered (TYPE_NAME (type), stream);
}
else
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.201
diff -u -p -r1.201 gdbtypes.c
--- gdbtypes.c 12 Oct 2010 20:58:17 -0000 1.201
+++ gdbtypes.c 13 Oct 2010 17:29:30 -0000
@@ -1347,36 +1347,21 @@ stub_noname_complaint (void)
complaint (&symfile_complaints, _("stub type has NULL name"));
}
-/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
+/* Strip all typedefs from TYPE.
+ Return the real type if possible.
- If this is a stubbed struct (i.e. declared as struct foo *), see if
- we can find a full definition in some other file. If so, copy this
- definition, so we can use it in future. There used to be a comment
- (but not any code) that if we don't find a full definition, we'd
- set a flag so we don't spend time in the future checking the same
- type. That would be a mistake, though--we might load in more
- symbols which contain a full definition for the type.
+ NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
+ not been computed and we're either in the middle of reading symbols, or
+ there was no name for the typedef in the debug info.
- This used to be coded as a macro, but I don't think it is called
- often enough to merit such treatment.
-
- Find the real type of TYPE. This function returns the real type,
- after removing all layers of typedefs and completing opaque or stub
- types. Completion changes the TYPE argument, but stripping of
- typedefs does not.
-
- If TYPE is a TYPE_CODE_TYPEDEF, its length is (also) set to the length of
- the target type instead of zero. However, in the case of TYPE_CODE_TYPEDEF
- check_typedef can still return different type than the original TYPE
- pointer. */
+ Any instance flags (e.g. const/volatile/address-space) that were stripped
+ away are stored in *INSTANCE_FLAGSP if non-NULL. */
struct type *
-check_typedef (struct type *type)
+strip_typedefs (struct type *type, int *instance_flagsp)
{
- struct type *orig_type = type;
- int is_const, is_volatile;
-
- gdb_assert (type);
+ if (instance_flagsp != NULL)
+ *instance_flagsp = 0;
while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
{
@@ -1406,9 +1391,50 @@ check_typedef (struct type *type)
else /* TYPE_CODE_UNDEF */
TYPE_TARGET_TYPE (type) = alloc_type_arch (get_type_arch (type));
}
+
+ if (instance_flagsp != NULL)
+ *instance_flagsp |= TYPE_INSTANCE_FLAGS (type);
+
type = TYPE_TARGET_TYPE (type);
}
+ return type;
+}
+
+/* Find the real type of TYPE. This function returns the real type,
+ after removing all layers of typedefs and completing opaque or stub
+ types. Completion changes the TYPE argument, but stripping of
+ typedefs does not.
+
+ NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
+ not been computed and we're either in the middle of reading symbols, or
+ there was no name for the typedef in the debug info.
+
+ If TYPE is a TYPE_CODE_TYPEDEF, its length is updated to the length of
+ the target type.
+
+ If this is a stubbed struct (i.e. declared as struct foo *), see if
+ we can find a full definition in some other file. If so, copy this
+ definition, so we can use it in future. There used to be a comment
+ (but not any code) that if we don't find a full definition, we'd
+ set a flag so we don't spend time in the future checking the same
+ type. That would be a mistake, though--we might load in more
+ symbols which contain a full definition for the type. */
+
+struct type *
+check_typedef (struct type *type)
+{
+ struct type *orig_type = type;
+ int is_const, is_volatile;
+
+ gdb_assert (type);
+
+ type = strip_typedefs (type, NULL);
+
+ /* If we still have a typedef, there's nothing more we can do. */
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ return type;
+
is_const = TYPE_CONST (type);
is_volatile = TYPE_VOLATILE (type);
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.135
diff -u -p -r1.135 gdbtypes.h
--- gdbtypes.h 6 Oct 2010 08:44:14 -0000 1.135
+++ gdbtypes.h 13 Oct 2010 17:29:30 -0000
@@ -1361,6 +1361,8 @@ extern struct type *check_typedef (struc
(TYPE) = check_typedef (TYPE); \
} while (0)
+extern struct type *strip_typedefs (struct type *, int *);
+
extern void check_stub_method_group (struct type *, int);
extern char *gdb_mangle_name (struct type *, int, int);
Index: testsuite/gdb.cp/pr12117.cc
===================================================================
RCS file: testsuite/gdb.cp/pr12117.cc
diff -N testsuite/gdb.cp/pr12117.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.cp/pr12117.cc 13 Oct 2010 17:29:31 -0000
@@ -0,0 +1,17 @@
+typedef int my_int;
+typedef const my_int const_my_int;
+typedef volatile my_int volatile_my_int;
+typedef volatile const_my_int volatile_const_my_int;
+typedef const volatile_my_int const_volatile_my_int;
+
+my_int v_my_int (0);
+const_my_int v_const_my_int (1);
+volatile_my_int v_volatile_my_int (2);
+const_volatile_my_int v_const_volatile_my_int (3);
+volatile_const_my_int v_volatile_const_my_int (4);
+
+int
+main ()
+{
+ return 0;
+}
Index: testsuite/gdb.cp/pr12117.exp
===================================================================
RCS file: testsuite/gdb.cp/pr12117.exp
diff -N testsuite/gdb.cp/pr12117.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.cp/pr12117.exp 13 Oct 2010 17:29:31 -0000
@@ -0,0 +1,55 @@
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+if { [skip_cplus_tests] } { continue }
+
+load_lib "cp-support.exp"
+
+set testfile "pr12117"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ untested ${testfile}.exp
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+gdb_test "whatis v_my_int" "my_int"
+gdb_test "ptype v_my_int" "int"
+
+gdb_test "whatis v_const_my_int" "const_my_int"
+gdb_test "ptype v_const_my_int" "const int"
+
+gdb_test "whatis v_volatile_my_int" "volatile_my_int"
+gdb_test "ptype v_volatile_my_int" "volatile int"
+
+gdb_test "whatis v_const_volatile_my_int" "const_volatile_my_int"
+gdb_test "ptype v_const_volatile_my_int" "const volatile int"
+
+gdb_test "whatis v_volatile_const_my_int" "volatile_const_my_int"
+setup_kfail "gcc/45997" *-*-*
+gdb_test "ptype v_volatile_const_my_int" "const volatile int"