diff options
author | Keith Seitz <keiths@redhat.com> | 2017-12-07 15:01:30 -0800 |
---|---|---|
committer | Keith Seitz <keiths@redhat.com> | 2017-12-07 15:01:30 -0800 |
commit | 883fd55ab1049333364479a7f5b0c7e61a310bac (patch) | |
tree | 7e62acd5cb4951e9b8faf934771e6c7a65b169c7 /gdb/dwarf2read.c | |
parent | ec72db3ef415ebdcedaf36a1d83bd6624ec063e0 (diff) | |
download | gdb-883fd55ab1049333364479a7f5b0c7e61a310bac.zip gdb-883fd55ab1049333364479a7f5b0c7e61a310bac.tar.gz gdb-883fd55ab1049333364479a7f5b0c7e61a310bac.tar.bz2 |
Record nested types
GDB currently does not track types defined in classes. Consider:
class A
{
public:
class B
{
public:
class C { };
};
};
(gdb) ptype A
type = class A {
<no data fields>
}
This patch changes this behavior so that GDB records these nested types
and displays them to the user when he has set the (new) "print type"
option "nested-type-limit."
Example:
(gdb) set print type nested-type-limit 1
(gdb) ptype A
type = class A {
<no data fields>
class A::B {
<no data fields>
};
}
(gdb) set print type nested-type-limit 2
type = class A {
<no data fields>
class A::B {
<no data fields>
class A::B::C {
<no data fields>
};
};
}
By default, the code maintains the status quo, that is, it will not print
any nested type definitions at all.
Testing is carried out via cp_ptype_class which required quite a bit of
modification to permit recursive calling (for the nested types). This
was most easily facilitated by turning the ptype command output into a
queue. Upshot: the test suite now has stack and queue data structures that
may be used by test writers.
gdb/ChangeLog
* NEWS (New commands): Mention set/show print type nested-type-limit.
* c-typeprint.c (c_type_print_base): Print out nested types.
* dwarf2read.c (struct typedef_field_list): Rename to ...
(struct decl_field_list): ... this. Change all uses.
(struct field_info) <nested_types_list, nested_types_list_count>:
New fields.
(add_partial_symbol): Look for nested type definitions in C++, too.
(dwarf2_add_typedef): Rename to ...
(dwarf2_add_type_defn): ... this.
(type_can_define_types): New function.
Update assertion to use type_can_define_types.
Permit NULL for a field's name.
(process_structure_scope): Handle child DIEs of types that can
define types.
Copy the list of nested types into the type struct.
* gdbtypes.h (struct typedef_field): Rename to ...
(struct decl_field): ... this. Change all uses.
[is_protected, is_private]: New fields.
(struct cplus_struct_type) <nested_types, nested_types_count>: New
fields.
(TYPE_NESTED_TYPES_ARRAY, TYPE_NESTED_TYPES_FIELD)
(TYPE_NESTED_TYPES_FIELD_NAME, TYPE_NESTED_TYPES_FIELD_TYPE)
(TYPE_NESTED_TYPES_COUNT, TYPE_NESTED_TYPES_FIELD_PROTECTED)
(TYPE_NESTED_TYPES_FIELD_PRIVATE): New macros.
* typeprint.c (type_print_raw_options, default_ptype_flags): Add
default value for print_nested_type_limit.
(print_nested_type_limit): New static variable.
(set_print_type_nested_types, show_print_type_nested_types): New
functions.
(_initialize_typeprint): Register new commands for set/show
`print-nested-type-limit'.
* typeprint.h (struct type_print_options) [print_nested_type_limit]:
New field.
gdb/testsuite/ChangeLog
* gdb.cp/nested-types.cc: New file.
* gdb.cp/nested-types.exp: New file.
* lib/cp-support.exp: Load data-structures.exp library.
(debug_cp_test_ptype_class): New global.
(cp_ptype_class_verbose, next_line): New procedures.
(cp_test_ptype_class): Add and document new parameter `recursive_qid'.
Add and document new return value.
Switch the list of lines to a queue.
Add support for new `type' key for nested type definitions.
Add debugging/troubleshooting messages.
* lib/data-structures.exp: New file.
gdb/doc/ChangeLog
* gdb.texinfo (Symbols): Document "set print type nested-type-limit"
and "show print type nested-type-limit".
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 98 |
1 files changed, 76 insertions, 22 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 287de7b..68ddbb1 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1529,10 +1529,10 @@ struct fnfieldlist struct nextfnfield *head; }; -struct typedef_field_list +struct decl_field_list { - struct typedef_field field; - struct typedef_field_list *next; + struct decl_field field; + struct decl_field_list *next; }; /* The routines that read and process dies for a C struct or C++ class @@ -1562,8 +1562,13 @@ struct field_info /* 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 *typedef_field_list; + struct decl_field_list *typedef_field_list; unsigned typedef_field_list_count; + + /* Nested types defined by this class and the number of elements in this + list. */ + struct decl_field_list *nested_types_list; + unsigned nested_types_list_count; }; /* One item on the queue of compilation units to read in full symbols @@ -13988,28 +13993,44 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, } } -/* Add a typedef defined in the scope of the FIP's class. */ +/* Can the type given by DIE define another type? */ + +static bool +type_can_define_types (const struct die_info *die) +{ + switch (die->tag) + { + case DW_TAG_typedef: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + return true; + + default: + return false; + } +} + +/* Add a type definition 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) +dwarf2_add_type_defn (struct field_info *fip, struct die_info *die, + struct dwarf2_cu *cu) { - struct typedef_field_list *new_field; - struct typedef_field *fp; + struct decl_field_list *new_field; + struct decl_field *fp; /* Allocate a new field list entry and link it in. */ - new_field = XCNEW (struct typedef_field_list); + new_field = XCNEW (struct decl_field_list); make_cleanup (xfree, new_field); - gdb_assert (die->tag == DW_TAG_typedef); + gdb_assert (type_can_define_types (die)); fp = &new_field->field; - /* Get name of field. */ + /* Get name of field. NULL is okay here, meaning an anonymous type. */ fp->name = dwarf2_name (die, cu); - if (fp->name == NULL) - return; - fp->type = read_type_die (die, cu); /* Save accessibility. */ @@ -14035,9 +14056,18 @@ dwarf2_add_typedef (struct field_info *fip, struct die_info *die, _("Unhandled DW_AT_accessibility value (%x)"), accessibility); } - new_field->next = fip->typedef_field_list; - fip->typedef_field_list = new_field; - fip->typedef_field_list_count++; + if (die->tag == DW_TAG_typedef) + { + new_field->next = fip->typedef_field_list; + fip->typedef_field_list = new_field; + fip->typedef_field_list_count++; + } + else + { + new_field->next = fip->nested_types_list; + fip->nested_types_list = new_field; + fip->nested_types_list_count++; + } } /* Create the vector of fields, and attach it to the type. */ @@ -14660,8 +14690,8 @@ process_structure_scope (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); + else if (type_can_define_types (child_die)) + dwarf2_add_type_defn (&fi, child_die, cu); else if (child_die->tag == DW_TAG_template_type_param || child_die->tag == DW_TAG_template_value_param) { @@ -14768,14 +14798,14 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_TYPEDEF_FIELD_ARRAY (type) - = ((struct typedef_field *) + = ((struct decl_field *) 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; + struct decl_field *dest, *src; dest = &TYPE_TYPEDEF_FIELD (type, i); src = &fi.typedef_field_list->field; @@ -14784,6 +14814,30 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) } } + /* Copy fi.nested_types_list linked list elements content into the + allocated array TYPE_NESTED_TYPES_ARRAY (type). */ + if (fi.nested_types_list != NULL && cu->language != language_ada) + { + int i = fi.nested_types_list_count; + + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_NESTED_TYPES_ARRAY (type) + = ((struct decl_field *) + TYPE_ALLOC (type, sizeof (struct decl_field) * i)); + TYPE_NESTED_TYPES_COUNT (type) = i; + + /* Reverse the list order to keep the debug info elements order. */ + while (--i >= 0) + { + struct decl_field *dest, *src; + + dest = &TYPE_NESTED_TYPES_FIELD (type, i); + src = &fi.nested_types_list->field; + fi.nested_types_list = fi.nested_types_list->next; + *dest = *src; + } + } + do_cleanups (back_to); } |