From 98751a4113ee63e980f4a6fa199151f7da617f1f Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Mon, 28 Jun 2010 20:39:30 +0000 Subject: [PATCH] gdb/ * c-typeprint.c (c_type_print_base): For no fields check include also TYPE_TYPEDEF_FIELD_COUNT. Print new typedefs section. * dwarf2read.c (struct typedef_field_list) (struct field_info) : New. (dwarf2_add_typedef): New. (read_structure_type): Call dwarf2_add_typedef for DW_TAG_typedef. Copy also FI.TYPEDEF_FIELD_LIST. * gdbtypes.h (struct typedef_field) (struct cplus_struct_type) (TYPE_TYPEDEF_FIELD_ARRAY, TYPE_TYPEDEF_FIELD, TYPE_TYPEDEF_FIELD_NAME) (TYPE_TYPEDEF_FIELD_TYPE, TYPE_TYPEDEF_FIELD_COUNT): New. gdb/testsuite/ * gdb.cp/namespace.exp (ptype OtherFileClass typedefs) (ptype ::C::OtherFileClass typedefs): New. * gdb.cp/namespace1.cc (C::OtherFileClass::cOtherFileClassType2) (C::OtherFileClass::cOtherFileClassVar2): New. (C::OtherFileClass::cOtherFileClassVar_use): Use also cOtherFileClassVar2. (C::cOtherFileType2, C::cOtherFileVar2): New. (C::cOtherFileVar_use): use also cOtherFileVar2. * gdb.cp/userdef.exp (ptype &*c): Permit arbitrary trailing text. --- gdb/ChangeLog | 14 +++++++ gdb/c-typeprint.c | 26 +++++++++++- gdb/dwarf2read.c | 67 ++++++++++++++++++++++++++++++ gdb/gdbtypes.h | 24 +++++++++++ gdb/testsuite/ChangeLog | 12 ++++++ gdb/testsuite/gdb.cp/namespace.exp | 15 +++++++ gdb/testsuite/gdb.cp/namespace1.cc | 8 +++- gdb/testsuite/gdb.cp/userdef.exp | 2 +- 8 files changed, 164 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 39ae349525..b18b598254 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2010-06-28 Jan Kratochvil + + * c-typeprint.c (c_type_print_base): For no fields check include also + TYPE_TYPEDEF_FIELD_COUNT. Print new typedefs section. + * dwarf2read.c (struct typedef_field_list) + (struct field_info) : New. + (dwarf2_add_typedef): New. + (read_structure_type): Call dwarf2_add_typedef for DW_TAG_typedef. + Copy also FI.TYPEDEF_FIELD_LIST. + * gdbtypes.h (struct typedef_field) + (struct cplus_struct_type) + (TYPE_TYPEDEF_FIELD_ARRAY, TYPE_TYPEDEF_FIELD, TYPE_TYPEDEF_FIELD_NAME) + (TYPE_TYPEDEF_FIELD_TYPE, TYPE_TYPEDEF_FIELD_COUNT): New. + 2010-06-28 Jan Kratochvil * cp-namespace.c (cp_lookup_nested_type): New variable diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index f7a305cead..926ae2fc5e 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -768,7 +768,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, cp_type_print_derivation_info (stream, type); fprintf_filtered (stream, "{\n"); - if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) + if (TYPE_NFIELDS (type) == 0 && TYPE_NFN_FIELDS (type) == 0 + && TYPE_TYPEDEF_FIELD_COUNT (type) == 0) { if (TYPE_STUB (type)) fprintfi_filtered (level + 4, stream, _("\n")); @@ -1058,6 +1059,29 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, } } + /* Print typedefs defined in this class. */ + + if (TYPE_TYPEDEF_FIELD_COUNT (type) != 0) + { + if (TYPE_NFIELDS (type) != 0 || TYPE_NFN_FIELDS (type) != 0) + fprintf_filtered (stream, "\n"); + + for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++) + { + struct type *target = TYPE_TYPEDEF_FIELD_TYPE (type, i); + + /* Dereference the typedef declaration itself. */ + gdb_assert (TYPE_CODE (target) == TYPE_CODE_TYPEDEF); + target = TYPE_TARGET_TYPE (target); + + print_spaces_filtered (level + 4, stream); + fprintf_filtered (stream, "typedef "); + c_print_type (target, TYPE_TYPEDEF_FIELD_NAME (type, i), + stream, show - 1, level + 4); + fprintf_filtered (stream, ";\n"); + } + } + fprintfi_filtered (level, stream, "}"); if (TYPE_LOCALTYPE_PTR (type) && show >= 0) diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 6893e08ac7..7febcab6b4 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -645,6 +645,16 @@ struct field_info /* Number of entries in the fnfieldlists array. */ int nfnfields; + + /* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of + a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */ + struct typedef_field_list + { + struct typedef_field field; + struct typedef_field_list *next; + } + *typedef_field_list; + unsigned typedef_field_list_count; }; /* One item on the queue of compilation units to read in full symbols @@ -4668,6 +4678,39 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, } } +/* Add a typedef defined in the scope of the FIP's class. */ + +static void +dwarf2_add_typedef (struct field_info *fip, struct die_info *die, + struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct typedef_field_list *new_field; + struct attribute *attr; + struct typedef_field *fp; + char *fieldname = ""; + + /* Allocate a new field list entry and link it in. */ + new_field = xzalloc (sizeof (*new_field)); + make_cleanup (xfree, new_field); + + gdb_assert (die->tag == DW_TAG_typedef); + + fp = &new_field->field; + + /* Get name of field. */ + fp->name = dwarf2_name (die, cu); + if (fp->name == NULL) + return; + + fp->type = read_type_die (die, cu); + + new_field->next = fip->typedef_field_list; + fip->typedef_field_list = new_field; + fip->typedef_field_list_count++; +} + /* Create the vector of fields, and attach it to the type. */ static void @@ -5202,6 +5245,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) /* C++ base class field. */ dwarf2_add_field (&fi, child_die, cu); } + else if (child_die->tag == DW_TAG_typedef) + dwarf2_add_typedef (&fi, child_die, cu); child_die = sibling_die (child_die); } @@ -5275,6 +5320,28 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) } } } + + /* Copy fi.typedef_field_list linked list elements content into the + allocated array TYPE_TYPEDEF_FIELD_ARRAY (type). */ + if (fi.typedef_field_list) + { + int i = fi.typedef_field_list_count; + + TYPE_TYPEDEF_FIELD_ARRAY (type) + = TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i); + TYPE_TYPEDEF_FIELD_COUNT (type) = i; + + /* Reverse the list order to keep the debug info elements order. */ + while (--i >= 0) + { + struct typedef_field *dest, *src; + + dest = &TYPE_TYPEDEF_FIELD (type, i); + src = &fi.typedef_field_list->field; + fi.typedef_field_list = fi.typedef_field_list->next; + *dest = *src; + } + } } quirk_gcc_member_function_pointer (type, cu->objfile); diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index ce79dc228f..61c7f9ae86 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -820,6 +820,19 @@ struct cplus_struct_type int line; } *localtype_ptr; + + /* typedefs defined inside this class. TYPEDEF_FIELD points to an array of + TYPEDEF_FIELD_COUNT elements. */ + struct typedef_field + { + /* Unqualified name to be prefixed by owning class qualified name. */ + const char *name; + + /* Type this typedef named NAME represents. */ + struct type *type; + } + *typedef_field; + unsigned typedef_field_count; }; /* Struct used in computing virtual base list */ @@ -1047,6 +1060,17 @@ extern void allocate_gnat_aux_type (struct type *); #define TYPE_LOCALTYPE_FILE(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr->file) #define TYPE_LOCALTYPE_LINE(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr->line) +#define TYPE_TYPEDEF_FIELD_ARRAY(thistype) \ + TYPE_CPLUS_SPECIFIC (thistype)->typedef_field +#define TYPE_TYPEDEF_FIELD(thistype, n) \ + TYPE_CPLUS_SPECIFIC (thistype)->typedef_field[n] +#define TYPE_TYPEDEF_FIELD_NAME(thistype, n) \ + TYPE_TYPEDEF_FIELD (thistype, n).name +#define TYPE_TYPEDEF_FIELD_TYPE(thistype, n) \ + TYPE_TYPEDEF_FIELD (thistype, n).type +#define TYPE_TYPEDEF_FIELD_COUNT(thistype) \ + TYPE_CPLUS_SPECIFIC (thistype)->typedef_field_count + #define TYPE_IS_OPAQUE(thistype) (((TYPE_CODE (thistype) == TYPE_CODE_STRUCT) || \ (TYPE_CODE (thistype) == TYPE_CODE_UNION)) && \ (TYPE_NFIELDS (thistype) == 0) && \ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 9f89500d62..dd618c9a00 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2010-06-28 Jan Kratochvil + + * gdb.cp/namespace.exp (ptype OtherFileClass typedefs) + (ptype ::C::OtherFileClass typedefs): New. + * gdb.cp/namespace1.cc (C::OtherFileClass::cOtherFileClassType2) + (C::OtherFileClass::cOtherFileClassVar2): New. + (C::OtherFileClass::cOtherFileClassVar_use): Use also + cOtherFileClassVar2. + (C::cOtherFileType2, C::cOtherFileVar2): New. + (C::cOtherFileVar_use): use also cOtherFileVar2. + * gdb.cp/userdef.exp (ptype &*c): Permit arbitrary trailing text. + 2010-06-28 Jan Kratochvil * gdb.cp/namespace.exp (whatis C::cOtherFileType) diff --git a/gdb/testsuite/gdb.cp/namespace.exp b/gdb/testsuite/gdb.cp/namespace.exp index 452dcdce78..1eae62f2d6 100644 --- a/gdb/testsuite/gdb.cp/namespace.exp +++ b/gdb/testsuite/gdb.cp/namespace.exp @@ -268,6 +268,21 @@ gdb_test "ptype OtherFileClass" "type = (class C::OtherFileClass \{\r\n public: gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n public:\r\n int z;\r\n.*\}" gdb_test "ptype C::OtherFileClass" "No symbol \"OtherFileClass\" in namespace \"C::C\"." +# Test class typedefs printing. +set expect "type = class C::OtherFileClass \{\r\n.*\r\n *typedef short cOtherFileClassType;\r\n *typedef long cOtherFileClassType2;\r\n\}" +if {[test_compiler_info {gcc-[0-3]-*}] + || [test_compiler_info {gcc-4-[0-4]-*}]} { + # The type in class is missing in older GCCs. + setup_xfail *-*-* +} +gdb_test "ptype OtherFileClass" $expect "ptype OtherFileClass typedefs" +if {[test_compiler_info {gcc-[0-3]-*}] + || [test_compiler_info {gcc-4-[0-4]-*}]} { + # The type in class is missing in older GCCs. + setup_xfail *-*-* +} +gdb_test "ptype ::C::OtherFileClass" $expect "ptype ::C::OtherFileClass typedefs" + # Some anonymous namespace tests. gdb_test "print cX" "\\$\[0-9\].* = 6" diff --git a/gdb/testsuite/gdb.cp/namespace1.cc b/gdb/testsuite/gdb.cp/namespace1.cc index 928e357411..aad55e5ede 100644 --- a/gdb/testsuite/gdb.cp/namespace1.cc +++ b/gdb/testsuite/gdb.cp/namespace1.cc @@ -23,12 +23,14 @@ namespace C int z; typedef short cOtherFileClassType; + typedef long cOtherFileClassType2; static const cOtherFileClassType cOtherFileClassVar = 318; + static const cOtherFileClassType2 cOtherFileClassVar2 = 320; cOtherFileClassType cOtherFileClassVar_use (); }; OtherFileClass::cOtherFileClassType OtherFileClass::cOtherFileClassVar_use () { - return cOtherFileClassVar; + return cOtherFileClassVar + cOtherFileClassVar2; } namespace { @@ -45,10 +47,12 @@ namespace C } typedef short cOtherFileType; + typedef long cOtherFileType2; static const cOtherFileType cOtherFileVar = 319; + static const cOtherFileType2 cOtherFileVar2 = 321; cOtherFileType cOtherFileVar_use () { - return cOtherFileVar; + return cOtherFileVar + cOtherFileVar2; } } diff --git a/gdb/testsuite/gdb.cp/userdef.exp b/gdb/testsuite/gdb.cp/userdef.exp index 1a6fd2e32c..050775a3d2 100644 --- a/gdb/testsuite/gdb.cp/userdef.exp +++ b/gdb/testsuite/gdb.cp/userdef.exp @@ -148,7 +148,7 @@ gdb_test "break A2::'operator +'" ".*Breakpoint $decimal at.*" gdb_test "print c" "\\\$\[0-9\]* = {m = {z = .*}}" gdb_test "print *c" "\\\$\[0-9\]* = \\(Member &\\) @$hex: {z = .*}" gdb_test "print &*c" "\\\$\[0-9\]* = \\(Member \\*\\) $hex" -gdb_test "ptype &*c" "type = (struct|class) Member {(\[\r\n \]+public:)?\[\r\n \]+int z;\[\r\n\]+} &\\*" +gdb_test "ptype &*c" "type = (struct|class) Member {(\[\r\n \]+public:)?\[\r\n \]+int z;\[\r\n\].*} &\\*" gdb_test "print operator== (mem1, mem2)" " = false" gdb_test "print operator== (mem1, mem1)" " = true" -- 2.34.1