From 92163a10dcb34785a2fc74a05c3e890fbe700731 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 15 Oct 2010 17:48:48 +0000 Subject: [PATCH] gdb/ PR exp/12117 * gdbtypes.c (check_typedef): Clean up function comment. Keep track of instance flags as we strip typedefs and create a new type to preserve them if necessary. * gdbtypes.h (type) : Extend the comment. gdb/testsuite/ PR exp/12117 * gdb.cp/ptype-cv-cp.cc: New file. * gdb.cp/ptype-cv-cp.exp: New file. --- gdb/ChangeLog | 9 +++ gdb/gdbtypes.c | 87 +++++++++++++++++++--------- gdb/gdbtypes.h | 9 ++- gdb/testsuite/ChangeLog | 7 +++ gdb/testsuite/gdb.cp/ptype-cv-cp.cc | 34 +++++++++++ gdb/testsuite/gdb.cp/ptype-cv-cp.exp | 41 +++++++++++++ 6 files changed, 159 insertions(+), 28 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/ptype-cv-cp.cc create mode 100644 gdb/testsuite/gdb.cp/ptype-cv-cp.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bcfe2b777f..a7029cfd68 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2010-10-15 Doug Evans + Jan Kratochvil + + PR exp/12117 + * gdbtypes.c (check_typedef): Clean up function comment. + Keep track of instance flags as we strip typedefs and create a new + type to preserve them if necessary. + * gdbtypes.h (type) : Extend the comment. + 2010-10-15 Pierre Muller * p-lang.c (is_pascal_string_type): Use TYPE_FIELD_NAME accessor. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index e983fe70bc..204bab5963 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1347,7 +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. +/* 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. + + Instance flags (e.g. const/volatile) are preserved as typedefs are + stripped. If necessary a new qualified form of the underlying type + is created. + + 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 @@ -1355,26 +1369,15 @@ stub_noname_complaint (void) (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. - - 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. */ + 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; + /* While we're removing typedefs, we don't want to lose qualifiers. + E.g., const/volatile. */ + int instance_flags = TYPE_INSTANCE_FLAGS (type); gdb_assert (type); @@ -1388,7 +1391,7 @@ check_typedef (struct type *type) /* It is dangerous to call lookup_symbol if we are currently reading a symtab. Infinite recursion is one danger. */ if (currently_reading_symtab) - return type; + return make_qualified_type (type, instance_flags, NULL); name = type_name_no_tag (type); /* FIXME: shouldn't we separately check the TYPE_NAME and @@ -1398,7 +1401,7 @@ check_typedef (struct type *type) if (name == NULL) { stub_noname_complaint (); - return type; + return make_qualified_type (type, instance_flags, NULL); } sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0); if (sym) @@ -1407,10 +1410,33 @@ check_typedef (struct type *type) TYPE_TARGET_TYPE (type) = alloc_type_arch (get_type_arch (type)); } type = TYPE_TARGET_TYPE (type); - } - is_const = TYPE_CONST (type); - is_volatile = TYPE_VOLATILE (type); + /* Preserve the instance flags as we traverse down the typedef chain. + + Handling address spaces/classes is nasty, what do we do if there's a + conflict? + E.g., what if an outer typedef marks the type as class_1 and an inner + typedef marks the type as class_2? + This is the wrong place to do such error checking. We leave it to + the code that created the typedef in the first place to flag the + error. We just pick the outer address space (akin to letting the + outer cast in a chain of casting win), instead of assuming + "it can't happen". */ + { + const int ALL_SPACES = (TYPE_INSTANCE_FLAG_CODE_SPACE + | TYPE_INSTANCE_FLAG_DATA_SPACE); + const int ALL_CLASSES = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL; + int new_instance_flags = TYPE_INSTANCE_FLAGS (type); + + /* Treat code vs data spaces and address classes separately. */ + if ((instance_flags & ALL_SPACES) != 0) + new_instance_flags &= ~ALL_SPACES; + if ((instance_flags & ALL_CLASSES) != 0) + new_instance_flags &= ~ALL_CLASSES; + + instance_flags |= new_instance_flags; + } + } /* If this is a struct/class/union with no fields, then check whether a full definition exists somewhere else. This is for @@ -1428,7 +1454,7 @@ check_typedef (struct type *type) if (name == NULL) { stub_noname_complaint (); - return type; + return make_qualified_type (type, instance_flags, NULL); } newtype = lookup_transparent_type (name); @@ -1445,7 +1471,9 @@ check_typedef (struct type *type) move over any other types NEWTYPE refers to, which could be an unbounded amount of stuff. */ if (TYPE_OBJFILE (newtype) == TYPE_OBJFILE (type)) - make_cv_type (is_const, is_volatile, newtype, &type); + type = make_qualified_type (newtype, + TYPE_INSTANCE_FLAGS (type), + type); else type = newtype; } @@ -1464,17 +1492,18 @@ check_typedef (struct type *type) if (name == NULL) { stub_noname_complaint (); - return type; + return make_qualified_type (type, instance_flags, NULL); } sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0); if (sym) { /* Same as above for opaque types, we can replace the stub - with the complete type only if they are int the same + with the complete type only if they are in the same objfile. */ if (TYPE_OBJFILE (SYMBOL_TYPE(sym)) == TYPE_OBJFILE (type)) - make_cv_type (is_const, is_volatile, - SYMBOL_TYPE (sym), &type); + type = make_qualified_type (SYMBOL_TYPE (sym), + TYPE_INSTANCE_FLAGS (type), + type); else type = SYMBOL_TYPE (sym); } @@ -1534,8 +1563,12 @@ check_typedef (struct type *type) TYPE_TARGET_STUB (type) = 0; } } + + type = make_qualified_type (type, instance_flags, NULL); + /* Cache TYPE_LENGTH for future use. */ TYPE_LENGTH (orig_type) = TYPE_LENGTH (type); + return type; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 87defcd0a8..e4dac492ea 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -623,7 +623,14 @@ struct type struct type *chain; /* Flags specific to this instance of the type, indicating where - on the ring we are. */ + on the ring we are. + + For TYPE_CODE_TYPEDEF the flags of the typedef type should be binary + or-ed with the target type, with a special case for address class and + space class. For example if this typedef does not specify any new + qualifiers, TYPE_INSTANCE_FLAGS is 0 and the instance flags are + completely inherited from the target type. No qualifiers can be cleared + by the typedef. See also check_typedef. */ int instance_flags; /* Length of storage for a value of this type. This is what diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 7e3f170ad7..442a65a8fc 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-10-13 Doug Evans + Jan Kratochvil + + PR exp/12117 + * gdb.cp/ptype-cv-cp.cc: New file. + * gdb.cp/ptype-cv-cp.exp: New file. + 2010-10-14 Sami Wagiaalla * gdb.cp/converts.cc: New test program. diff --git a/gdb/testsuite/gdb.cp/ptype-cv-cp.cc b/gdb/testsuite/gdb.cp/ptype-cv-cp.cc new file mode 100644 index 0000000000..560a7db6e7 --- /dev/null +++ b/gdb/testsuite/gdb.cp/ptype-cv-cp.cc @@ -0,0 +1,34 @@ +/* This testcase is part of GDB, the GNU debugger. + + 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 . */ + +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; +} diff --git a/gdb/testsuite/gdb.cp/ptype-cv-cp.exp b/gdb/testsuite/gdb.cp/ptype-cv-cp.exp new file mode 100644 index 0000000000..c1926d92bb --- /dev/null +++ b/gdb/testsuite/gdb.cp/ptype-cv-cp.exp @@ -0,0 +1,41 @@ +# 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 . + +# This file is part of the gdb testsuite. + +if { [skip_cplus_tests] } { continue } + +set testfile "ptype-cv-cp" +set srcfile ${testfile}.cc + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug c++}] } { + return -1 +} + +gdb_test "whatis v_my_int" "type = my_int" +gdb_test "ptype v_my_int" "type = int" + +gdb_test "whatis v_const_my_int" "type = const_my_int" +gdb_test "ptype v_const_my_int" "type = const int" + +gdb_test "whatis v_volatile_my_int" "type = volatile_my_int" +gdb_test "ptype v_volatile_my_int" "type = volatile int" + +gdb_test "whatis v_const_volatile_my_int" "type = const_volatile_my_int" +gdb_test "ptype v_const_volatile_my_int" "type = const volatile int" + +gdb_test "whatis v_volatile_const_my_int" "type = volatile_const_my_int" +setup_kfail "gcc/45997" *-*-* +gdb_test "ptype v_volatile_const_my_int" "type = const volatile int"