binutils-gdb/gdb/testsuite/lib/data-structures.exp
Keith Seitz 883fd55ab1 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".
2017-12-07 15:01:30 -08:00

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
}