summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.cp
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2017-12-07 15:01:30 -0800
committerKeith Seitz <keiths@redhat.com>2017-12-07 15:01:30 -0800
commit883fd55ab1049333364479a7f5b0c7e61a310bac (patch)
tree7e62acd5cb4951e9b8faf934771e6c7a65b169c7 /gdb/testsuite/gdb.cp
parentec72db3ef415ebdcedaf36a1d83bd6624ec063e0 (diff)
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/testsuite/gdb.cp')
-rw-r--r--gdb/testsuite/gdb.cp/nested-types.cc628
-rw-r--r--gdb/testsuite/gdb.cp/nested-types.exp322
2 files changed, 950 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.cp/nested-types.cc b/gdb/testsuite/gdb.cp/nested-types.cc
new file mode 100644
index 0000000000..43beb577d7
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/nested-types.cc
@@ -0,0 +1,628 @@
+/* Code in this file is generated. -*- buffer-read-only: t -*- vi:set ro:
+ See the procedure `make_source' in nested-types.exp. */
+
+/* This testcase is part of GDB, the GNU debugger.
+
+ 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/>. */
+
+struct S10 {
+ enum E10 {A10, B10, C10};
+ union U10 {
+ int a;
+ char c;
+ };
+
+ int i10;
+ E10 e10;
+ U10 u10;
+
+ struct S11 {
+ enum E11 {A11, B11, C11};
+ union U11 {
+ int a;
+ char c;
+ };
+
+ int i11;
+ E11 e11;
+ U11 u11;
+
+ struct S12 {
+ enum E12 {A12, B12, C12};
+ union U12 {
+ int a;
+ char c;
+ };
+
+ int i12;
+ E12 e12;
+ U12 u12;
+
+ struct S13 {
+ enum E13 {A13, B13, C13};
+ union U13 {
+ int a;
+ char c;
+ };
+
+ int i13;
+ E13 e13;
+ U13 u13;
+
+ struct S14 {
+ enum E14 {A14, B14, C14};
+ union U14 {
+ int a;
+ char c;
+ };
+
+ int i14;
+ E14 e14;
+ U14 u14;
+
+ struct S15 {
+ enum E15 {A15, B15, C15};
+ union U15 {
+ int a;
+ char c;
+ };
+
+ int i15;
+ E15 e15;
+ U15 u15;
+
+ struct S16 {
+ enum E16 {A16, B16, C16};
+ union U16 {
+ int a;
+ char c;
+ };
+
+ int i16;
+ E16 e16;
+ U16 u16;
+
+ struct S17 {
+ enum E17 {A17, B17, C17};
+ union U17 {
+ int a;
+ char c;
+ };
+
+ int i17;
+ E17 e17;
+ U17 u17;
+
+ struct S18 {
+ enum E18 {A18, B18, C18};
+ union U18 {
+ int a;
+ char c;
+ };
+
+ int i18;
+ E18 e18;
+ U18 u18;
+
+ struct S19 {
+ enum E19 {A19, B19, C19};
+ union U19 {
+ int a;
+ char c;
+ };
+
+ int i19;
+ E19 e19;
+ U19 u19;
+
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ struct S21 {
+ enum E21 {A21, B21, C21};
+ union U21 {
+ int a;
+ char c;
+ };
+
+ int i21;
+ E21 e21;
+ U21 u21;
+
+ struct S22 {
+ enum E22 {A22, B22, C22};
+ union U22 {
+ int a;
+ char c;
+ };
+
+ int i22;
+ E22 e22;
+ U22 u22;
+
+ struct S23 {
+ enum E23 {A23, B23, C23};
+ union U23 {
+ int a;
+ char c;
+ };
+
+ int i23;
+ E23 e23;
+ U23 u23;
+
+ struct S24 {
+ enum E24 {A24, B24, C24};
+ union U24 {
+ int a;
+ char c;
+ };
+
+ int i24;
+ E24 e24;
+ U24 u24;
+
+ struct S25 {
+ enum E25 {A25, B25, C25};
+ union U25 {
+ int a;
+ char c;
+ };
+
+ int i25;
+ E25 e25;
+ U25 u25;
+
+ struct S26 {
+ enum E26 {A26, B26, C26};
+ union U26 {
+ int a;
+ char c;
+ };
+
+ int i26;
+ E26 e26;
+ U26 u26;
+
+ struct S27 {
+ enum E27 {A27, B27, C27};
+ union U27 {
+ int a;
+ char c;
+ };
+
+ int i27;
+ E27 e27;
+ U27 u27;
+
+ struct S28 {
+ enum E28 {A28, B28, C28};
+ union U28 {
+ int a;
+ char c;
+ };
+
+ int i28;
+ E28 e28;
+ U28 u28;
+
+ struct S29 {
+ enum E29 {A29, B29, C29};
+ union U29 {
+ int a;
+ char c;
+ };
+
+ int i29;
+ E29 e29;
+ U29 u29;
+
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ struct S31 {
+ enum E31 {A31, B31, C31};
+ union U31 {
+ int a;
+ char c;
+ };
+
+ int i31;
+ E31 e31;
+ U31 u31;
+
+ struct S32 {
+ enum E32 {A32, B32, C32};
+ union U32 {
+ int a;
+ char c;
+ };
+
+ int i32;
+ E32 e32;
+ U32 u32;
+
+ struct S33 {
+ enum E33 {A33, B33, C33};
+ union U33 {
+ int a;
+ char c;
+ };
+
+ int i33;
+ E33 e33;
+ U33 u33;
+
+ struct S34 {
+ enum E34 {A34, B34, C34};
+ union U34 {
+ int a;
+ char c;
+ };
+
+ int i34;
+ E34 e34;
+ U34 u34;
+
+ struct S35 {
+ enum E35 {A35, B35, C35};
+ union U35 {
+ int a;
+ char c;
+ };
+
+ int i35;
+ E35 e35;
+ U35 u35;
+
+ struct S36 {
+ enum E36 {A36, B36, C36};
+ union U36 {
+ int a;
+ char c;
+ };
+
+ int i36;
+ E36 e36;
+ U36 u36;
+
+ struct S37 {
+ enum E37 {A37, B37, C37};
+ union U37 {
+ int a;
+ char c;
+ };
+
+ int i37;
+ E37 e37;
+ U37 u37;
+
+ struct S38 {
+ enum E38 {A38, B38, C38};
+ union U38 {
+ int a;
+ char c;
+ };
+
+ int i38;
+ E38 e38;
+ U38 u38;
+
+ struct S39 {
+ enum E39 {A39, B39, C39};
+ union U39 {
+ int a;
+ char c;
+ };
+
+ int i39;
+ E39 e39;
+ U39 u39;
+
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ struct S41 {
+ enum E41 {A41, B41, C41};
+ union U41 {
+ int a;
+ char c;
+ };
+
+ int i41;
+ E41 e41;
+ U41 u41;
+
+ struct S42 {
+ enum E42 {A42, B42, C42};
+ union U42 {
+ int a;
+ char c;
+ };
+
+ int i42;
+ E42 e42;
+ U42 u42;
+
+ struct S43 {
+ enum E43 {A43, B43, C43};
+ union U43 {
+ int a;
+ char c;
+ };
+
+ int i43;
+ E43 e43;
+ U43 u43;
+
+ struct S44 {
+ enum E44 {A44, B44, C44};
+ union U44 {
+ int a;
+ char c;
+ };
+
+ int i44;
+ E44 e44;
+ U44 u44;
+
+ struct S45 {
+ enum E45 {A45, B45, C45};
+ union U45 {
+ int a;
+ char c;
+ };
+
+ int i45;
+ E45 e45;
+ U45 u45;
+
+ struct S46 {
+ enum E46 {A46, B46, C46};
+ union U46 {
+ int a;
+ char c;
+ };
+
+ int i46;
+ E46 e46;
+ U46 u46;
+
+ struct S47 {
+ enum E47 {A47, B47, C47};
+ union U47 {
+ int a;
+ char c;
+ };
+
+ int i47;
+ E47 e47;
+ U47 u47;
+
+ struct S48 {
+ enum E48 {A48, B48, C48};
+ union U48 {
+ int a;
+ char c;
+ };
+
+ int i48;
+ E48 e48;
+ U48 u48;
+
+ struct S49 {
+ enum E49 {A49, B49, C49};
+ union U49 {
+ int a;
+ char c;
+ };
+
+ int i49;
+ E49 e49;
+ U49 u49;
+
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ struct S51 {
+ enum E51 {A51, B51, C51};
+ union U51 {
+ int a;
+ char c;
+ };
+
+ int i51;
+ E51 e51;
+ U51 u51;
+
+ struct S52 {
+ enum E52 {A52, B52, C52};
+ union U52 {
+ int a;
+ char c;
+ };
+
+ int i52;
+ E52 e52;
+ U52 u52;
+
+ struct S53 {
+ enum E53 {A53, B53, C53};
+ union U53 {
+ int a;
+ char c;
+ };
+
+ int i53;
+ E53 e53;
+ U53 u53;
+
+ struct S54 {
+ enum E54 {A54, B54, C54};
+ union U54 {
+ int a;
+ char c;
+ };
+
+ int i54;
+ E54 e54;
+ U54 u54;
+
+ struct S55 {
+ enum E55 {A55, B55, C55};
+ union U55 {
+ int a;
+ char c;
+ };
+
+ int i55;
+ E55 e55;
+ U55 u55;
+
+ struct S56 {
+ enum E56 {A56, B56, C56};
+ union U56 {
+ int a;
+ char c;
+ };
+
+ int i56;
+ E56 e56;
+ U56 u56;
+
+ struct S57 {
+ enum E57 {A57, B57, C57};
+ union U57 {
+ int a;
+ char c;
+ };
+
+ int i57;
+ E57 e57;
+ U57 u57;
+
+ struct S58 {
+ enum E58 {A58, B58, C58};
+ union U58 {
+ int a;
+ char c;
+ };
+
+ int i58;
+ E58 e58;
+ U58 u58;
+
+ struct S59 {
+ enum E59 {A59, B59, C59};
+ union U59 {
+ int a;
+ char c;
+ };
+
+ int i59;
+ E59 e59;
+ U59 u59;
+
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+};
+
+int
+main ()
+{
+ S10 s10;
+ S10::S11 s11;
+ S10::S11::S12 s12;
+ S10::S11::S12::S13 s13;
+ S10::S11::S12::S13::S14 s14;
+ S10::S11::S12::S13::S14::S15 s15;
+ S10::S11::S12::S13::S14::S15::S16 s16;
+ S10::S11::S12::S13::S14::S15::S16::S17 s17;
+ S10::S11::S12::S13::S14::S15::S16::S17::S18 s18;
+ S10::S11::S12::S13::S14::S15::S16::S17::S18::S19 s19;
+
+ S10::S21 s21;
+ S10::S21::S22 s22;
+ S10::S21::S22::S23 s23;
+ S10::S21::S22::S23::S24 s24;
+ S10::S21::S22::S23::S24::S25 s25;
+ S10::S21::S22::S23::S24::S25::S26 s26;
+ S10::S21::S22::S23::S24::S25::S26::S27 s27;
+ S10::S21::S22::S23::S24::S25::S26::S27::S28 s28;
+ S10::S21::S22::S23::S24::S25::S26::S27::S28::S29 s29;
+
+ S10::S31 s31;
+ S10::S31::S32 s32;
+ S10::S31::S32::S33 s33;
+ S10::S31::S32::S33::S34 s34;
+ S10::S31::S32::S33::S34::S35 s35;
+ S10::S31::S32::S33::S34::S35::S36 s36;
+ S10::S31::S32::S33::S34::S35::S36::S37 s37;
+ S10::S31::S32::S33::S34::S35::S36::S37::S38 s38;
+ S10::S31::S32::S33::S34::S35::S36::S37::S38::S39 s39;
+
+ S10::S41 s41;
+ S10::S41::S42 s42;
+ S10::S41::S42::S43 s43;
+ S10::S41::S42::S43::S44 s44;
+ S10::S41::S42::S43::S44::S45 s45;
+ S10::S41::S42::S43::S44::S45::S46 s46;
+ S10::S41::S42::S43::S44::S45::S46::S47 s47;
+ S10::S41::S42::S43::S44::S45::S46::S47::S48 s48;
+ S10::S41::S42::S43::S44::S45::S46::S47::S48::S49 s49;
+
+ S10::S51 s51;
+ S10::S51::S52 s52;
+ S10::S51::S52::S53 s53;
+ S10::S51::S52::S53::S54 s54;
+ S10::S51::S52::S53::S54::S55 s55;
+ S10::S51::S52::S53::S54::S55::S56 s56;
+ S10::S51::S52::S53::S54::S55::S56::S57 s57;
+ S10::S51::S52::S53::S54::S55::S56::S57::S58 s58;
+ S10::S51::S52::S53::S54::S55::S56::S57::S58::S59 s59;
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.cp/nested-types.exp b/gdb/testsuite/gdb.cp/nested-types.exp
new file mode 100644
index 0000000000..46edc30d5a
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/nested-types.exp
@@ -0,0 +1,322 @@
+# 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/>.
+
+# Test nested class definitions with the type printer.
+#
+# This test works by constructing a tree to represent "struct S10" in
+# the corresponding source file. It then walks the nodes of this tree
+# to construct input suitable for passing to cp_test_ptype_class.
+
+if {[skip_cplus_tests]} { continue }
+
+load_lib "cp-support.exp"
+
+standard_testfile .cc
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
+ {debug c++}]} {
+ return -1
+}
+
+# Build the node given by ID (a number representing the struct S[ID] in
+# the source file).
+#
+# For each node, stored as ::nodes(ID,ARG), where ARG is
+#
+# fields - list of fields [no children]
+# children - list of types [children]
+
+proc build_node {id} {
+ global nodes
+
+ # For any node, FIELDS is always the types i(N), e(N), u(N)
+ # CHILDREN is a list of nodes called [E(N), U(N)] S(N+1)
+ #
+ # The root (10) also has S(N+11), S(N+21), S(N+31), S(N+41)
+
+ set nodes($id,fields) [list "int i$id" "E$id e$id" "U$id u$id"]
+ set nodes($id,children) {}
+ if {$id == 10} {
+ set limit 5
+ } else {
+ set limit 1
+ }
+ for {set i 0} {$i < $limit} {incr i} {
+ set n [expr {1 + $id + $i * 10}]
+
+ # We don't build nodes which are multiples of 10
+ # (the source only uses that at the root struct).
+ # We also don't create nodes not in the source file
+ # (id >= 60).
+ if {[expr {$n % 10}] != 0 && $n < 60} {
+ lappend nodes($id,children) $n
+ }
+ }
+}
+
+# A helper procedure to indent the log output by LVL. This is used for
+# debugging the tree, if ever necessary.
+
+proc indent {lvl} {
+ for {set i 0} {$i < $lvl} {incr i} {
+ send_log " "
+ }
+}
+
+# For the given CHILD name and PARENT_LIST, return the fully qualified
+# name of the child type.
+
+proc qual_name {child parent_list} {
+ if {[string range $child 0 2] != "int" && [llength $parent_list]} {
+ return "[join $parent_list ::]::$child"
+ } else {
+ return "$child"
+ }
+}
+
+# Output the test source to the log.
+
+proc make_source {} {
+ # Output the structure.
+ test_nested_limit 10 true
+
+ # Output main().
+ send_log "int\nmain \(\)\n\{\n"
+ set plist {}
+ for {set i 10} {$i < 60} {incr i} {
+ if {$i > 10 && [expr {$i % 10}] == 0} {
+ incr i
+ set plist {"S10"}
+ send_log "\n"
+ }
+ send_log " [qual_name S$i $plist] s$i;\n"
+ lappend plist "S$i"
+ }
+
+ send_log " return 0;\n"
+ send_log "\}\n"
+}
+
+# Output to the log and/or create the result list for the fields of node ID.
+
+proc make_fields {result_var id parent_list indent_lvl log} {
+ upvar $result_var result
+ global nodes
+
+ foreach type $nodes($id,fields) {
+ set s "[qual_name $type $parent_list];"
+ if {$log} {
+ indent $indent_lvl
+ send_log "$s\n"
+ }
+ lappend result [list "field" "public" "$s"]
+ }
+}
+
+# Output to the log and/or create the result list for the union type in
+# node ID.
+
+proc make_union {result_var id parent_list indent_lvl log} {
+ upvar $result_var result
+
+ set s "[qual_name U$id $parent_list]"
+ set a "int a;"
+ set c "char c;"
+ lappend result [list "type" "public" "union" $s [list $a $c]]
+ if {$log} {
+ indent $indent_lvl
+ send_log "union $s \{\n"
+ indent [expr {$indent_lvl + 1}]
+ send_log "$a\n"
+ indent [expr {$indent_lvl + 1}]
+ send_log "$c\n"
+ indent $indent_lvl
+ send_log "\};\n"
+ }
+}
+
+# Output to the log and/or create the result list for the enum type in
+# node ID.
+
+proc make_enum {result_var id parent_list indent_lvl log} {
+ upvar $result_var result
+
+ set s "[qual_name E$id $parent_list]"
+ set a "[qual_name A$id $parent_list]"
+ set b "[qual_name B$id $parent_list]"
+ set c "[qual_name C$id $parent_list]"
+ lappend result [list "type" "public" "enum" $s [list $a $b $c]]
+
+ if {$log} {
+ indent $indent_lvl
+ send_log "enum $s \{$a, $b, $c\};\n"
+ }
+}
+
+# Output to the log and/or create the result list for the node given by ID.
+#
+# LIMIT describes the number of nested types to output (corresponding to
+# the "set print type nested-type-limit" command).
+# PARENT_LIST is the list of parent nodes already seen.
+# INDENT_LVL is the indentation level (used when LOG is true).
+
+proc node_result {result_var id limit parent_list indent_lvl log} {
+ upvar $result_var result
+
+ # Start a new type list.
+ set my_name "S$id"
+ set s "[qual_name $my_name $parent_list]"
+ set my_result [list "type" "public" "struct" $s]
+
+ if {$log} {
+ indent $indent_lvl
+ send_log "struct $my_name \{\n"
+ } else {
+ # Add this node to the parent list so that its name appears in
+ # qualified names, but only if we are not logging. [See immediately
+ # below.]
+ lappend parent_list "$my_name"
+ }
+
+ # `ptype' outputs fields before type definitions, but in order to
+ # output compile-ready code, these must be output in reverse.
+
+ if {!$log} {
+ # Output field list to a local children list.
+ set children_list {}
+ make_fields children_list $id $parent_list \
+ [expr {$indent_lvl + 1}] $log
+
+ # Output type definitions to the local children list.
+ # The first number of ID gives us the depth of the node.
+ if {[string index $id 1] < $limit || $limit < 0} {
+ make_enum children_list $id $parent_list \
+ [expr {$indent_lvl + 1}] $log
+ make_union children_list $id $parent_list \
+ [expr {$indent_lvl + 1}] $log
+ }
+ } else {
+ # Output type definitions to the local children list.
+ # The first number of ID gives us the depth of the node.
+ if {[string index $id 1] < $limit || $limit < 0} {
+ make_enum children_list $id $parent_list \
+ [expr {$indent_lvl + 1}] $log
+ make_union children_list $id $parent_list \
+ [expr {$indent_lvl + 1}] $log
+ send_log "\n"
+ }
+
+ # Output field list to a local children list.
+ set children_list {}
+ make_fields children_list $id $parent_list \
+ [expr {$indent_lvl + 1}] $log
+ send_log "\n"
+ }
+
+ # Output the children to the local children list.
+ global nodes
+ if {[info exists nodes($id,children)]} {
+ foreach c $nodes($id,children) {
+ if {[string index $c 1] <= $limit || $limit < 0} {
+ node_result children_list $c $limit $parent_list \
+ [expr {$indent_lvl + 1}] $log
+ }
+ }
+ }
+
+ # Add this node's children to its result and add its result to
+ # its parent's results.
+ lappend my_result $children_list
+ lappend result $my_result
+
+ if {$log} {
+ indent $indent_lvl
+ send_log "\};\n"
+ }
+}
+
+# Test nested type definitions. LIMIT specifies how many nested levels
+# of definitions to test. If LOG is true, output the tree to the log in
+# a human-readable format mimicing the source code.
+#
+# Only test when not logging. Generating source code usable by the
+# test is not quite the same as how GDB outputs it.
+
+proc test_nested_limit {limit log} {
+ set result {}
+
+ if {!$log} {
+ # Set the number of nested definitions to print.
+ gdb_test_no_output "set print type nested-type-limit $limit"
+
+ # Check the output of "show type print nested-type-limit"
+ if {$limit < 0} {
+ set lstr "unlimited"
+ } else {
+ set lstr $limit
+ }
+ gdb_test "show print type nested-type-limit" \
+ "Will print $lstr nested types defined in a class" \
+ "show print type nested-type-limit ($limit)"
+ } else {
+ send_log "Tree to $limit levels:\n"
+ }
+
+ # Generate the result list.
+ node_result result 10 $limit {} 0 $log
+
+ if {!$log} {
+ # The only output we check for is the contents of the struct,
+ # ignoring the leading "type = struct S10 {" and trailing "}" of
+ # the outermost node.
+ set result [lindex $result 0]
+ lassign $result type access key name children
+ cp_test_ptype_class $name "ptype $name (limit = $limit)" $key \
+ $name $children
+ }
+}
+
+# Build a tree of nodes describing the structures in the source file.
+
+# An array holding all the nodes
+array set nodes {}
+build_node 10
+for {set i 1} {$i < 6} {incr i} {
+ for {set j 1} {$j < 10} {incr j} {
+ build_node $i$j
+ }
+}
+
+# Check relevant commands.
+
+# By default, we do not print nested type definitions.
+gdb_test "show print type nested-type-limit" \
+ "Will not print nested types defined in a class" \
+ "show default print type nested-type-limit"
+
+# -1 means we print all nested types
+test_nested_limit -1 false
+
+# Test the output of "show print type nested-type-limit" and
+# ptype on the test source.
+
+for {set i 1} {$i < 9} {incr i} {
+ test_nested_limit $i false
+}
+
+# To output the test code to the log, uncomment the following line:
+#make_source
+
+unset -nocomplain nodes result