mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
883fd55ab1
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".
165 lines
4.1 KiB
Plaintext
165 lines
4.1 KiB
Plaintext
# Copyright 2017 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 implements some simple data structures in Tcl.
|
|
|
|
# A namespace/commands to support a stack.
|
|
#
|
|
# To create a stack, call ::Stack::new, recording the returned object ID
|
|
# for future calls to manipulate the stack object.
|
|
#
|
|
# Example:
|
|
#
|
|
# set sid [::Stack::new]
|
|
# stack push $sid a
|
|
# stack push $sid b
|
|
# stack empty $sid; # returns false
|
|
# stack pop $sid; # returns "b"
|
|
# stack pop $sid; # returns "a"
|
|
# stack pop $sid; # errors with "stack is empty"
|
|
# stack delete $sid1
|
|
|
|
namespace eval ::Stack {
|
|
# A counter used to create object IDs
|
|
variable num_ 0
|
|
|
|
# An array holding all object lists, indexed by object ID.
|
|
variable data_
|
|
|
|
# Create a new stack object, returning its object ID.
|
|
proc new {} {
|
|
variable num_
|
|
variable data_
|
|
|
|
set oid [incr num_]
|
|
set data_($oid) [list]
|
|
return $oid
|
|
}
|
|
|
|
# Delete the given stack ID.
|
|
proc delete {oid} {
|
|
variable data_
|
|
|
|
error_if $oid
|
|
unset data_($oid)
|
|
}
|
|
|
|
# Returns whether the given stack is empty.
|
|
proc empty {oid} {
|
|
variable data_
|
|
|
|
error_if $oid
|
|
return [expr {[llength $data_($oid)] == 0}]
|
|
}
|
|
|
|
# Push ELEM onto the stack given by OID.
|
|
proc push {oid elem} {
|
|
variable data_
|
|
|
|
error_if $oid
|
|
lappend data_($oid) $elem
|
|
}
|
|
|
|
# Return and pop the top element on OID. It is an error to pop
|
|
# an empty stack.
|
|
proc pop {oid} {
|
|
variable data_
|
|
|
|
error_if $oid
|
|
if {[llength $data_($oid)] == 0} {
|
|
::error "stack is empty"
|
|
}
|
|
set elem [lindex $data_($oid) end]
|
|
set data_($oid) [lreplace $data_($oid) end end]
|
|
return $elem
|
|
}
|
|
|
|
# Returns the depth of a given ID.
|
|
proc length {oid} {
|
|
variable data_
|
|
|
|
error_if $oid
|
|
return [llength $data_($oid)]
|
|
}
|
|
|
|
# Error handler for invalid object IDs.
|
|
proc error_if {oid} {
|
|
variable data_
|
|
|
|
if {![info exists data_($oid)]} {
|
|
::error "object ID $oid does not exist"
|
|
}
|
|
}
|
|
|
|
# Export procs to be used.
|
|
namespace export empty push pop new delete length error_if
|
|
|
|
# Create an ensemble command to use instead of requiring users
|
|
# to type namespace proc names.
|
|
namespace ensemble create -command ::stack
|
|
}
|
|
|
|
# A namespace/commands to support a queue.
|
|
#
|
|
# To create a queue, call ::Queue::new, recording the returned queue ID
|
|
# for future calls to manipulate the queue object.
|
|
#
|
|
# Example:
|
|
#
|
|
# set qid [::Queue::new]
|
|
# queue push $qid a
|
|
# queue push $qid b
|
|
# queue empty $qid; # returns false
|
|
# queue pop $qid; # returns "a"
|
|
# queue pop $qid; # returns "b"
|
|
# queue pop $qid; # errors with "queue is empty"
|
|
# queue delete $qid
|
|
|
|
namespace eval ::Queue {
|
|
|
|
# Remove and return the oldest element in the queue given by OID.
|
|
# It is an error to pop an empty queue.
|
|
proc pop {oid} {
|
|
variable ::Stack::data_
|
|
|
|
error_if $oid
|
|
if {[llength $data_($oid)] == 0} {
|
|
error "queue is empty"
|
|
}
|
|
set elem [lindex $data_($oid) 0]
|
|
set data_($oid) [lreplace $data_($oid) 0 0]
|
|
return $elem
|
|
}
|
|
|
|
# "Unpush" ELEM back to the head of the queue given by QID.
|
|
proc unpush {oid elem} {
|
|
variable ::Stack::data_
|
|
|
|
error_if $oid
|
|
set data_($oid) [linsert $data_($oid) 0 $elem]
|
|
}
|
|
|
|
# Re-use some common routines from the Stack implementation.
|
|
namespace import ::Stack::create ::Stack::new ::Stack::empty \
|
|
::Stack::delete ::Stack::push ::Stack::length ::Stack::error_if
|
|
|
|
# Export procs to be used.
|
|
namespace export new empty push pop new delete length error_if unpush
|
|
|
|
# Create an ensemble command to use instead of requiring users
|
|
# to type namespace proc names.
|
|
namespace ensemble create -command ::queue
|
|
}
|