From: Tom de Vries Date: Mon, 11 May 2020 18:36:11 +0000 (+0200) Subject: [gdb/testsuite] Fix gdb.cp/cpexprs-debug-types.exp inclusion X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=113ee09a649a5e192408a10286b95e89bc48706a;p=binutils-gdb.git [gdb/testsuite] Fix gdb.cp/cpexprs-debug-types.exp inclusion When running tests using RUNTESTFLAGS="cpexprs.exp cpexprs-debug-types.exp", we have: ... Running src/gdb/testsuite/gdb.cp/cpexprs-debug-types.exp ... Running src/gdb/testsuite/gdb.cp/cpexprs.exp ... ... In the first test-case, we have -fdebug-types-section as expected: ... Running src/gdb/testsuite/gdb.cp/cpexprs-debug-types.exp ... g++ -fno-stack-protector -fdiagnostics-color=never \ -fdebug-types-section \ -c -g \ -o outputs/gdb.cp/cpexprs-debug-types/cpexprs-debug-types0.o \ src/gdb/testsuite/gdb.cp/cpexprs.cc ... but in the second test-case, we have also have -fdebug-types-section: ... Running src/gdb/testsuite/gdb.cp/cpexprs.exp ... g++ -fno-stack-protector -fdiagnostics-color=never \ -fdebug-types-section \ -c -g -g \ -o outputs/gdb.cp/cpexprs/cpexprs0.o \ src/gdb/testsuite/gdb.cp/cpexprs.cc ... This is due to using a global variable flags, which is set in cpexprs-debug-types.exp and tested for existence in cpexprs.exp. Fix this by using a more robust inclusion mechanism, that is: - move the bulk of the test-case cpexprs.exp to cpexprs.exp.in, - include it from cpexprs.exp and cpexprs-debug-types.exp, and - set flags in both .exp files gdb/testsuite/ChangeLog: 2020-05-11 Tom de Vries * gdb.cp/cpexprs.exp: Move everything except flags setting ... * gdb.cp/cpexprs.exp.in: .. here. * gdb.cp/cpexprs-debug-types.exp: Include cpexprs.exp.in instead of cpexprs.exp. --- diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 309602cfd73..2a0d84d8146 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-05-11 Tom de Vries + + * gdb.cp/cpexprs.exp: Move everything except flags setting ... + * gdb.cp/cpexprs.exp.in: .. here. + * gdb.cp/cpexprs-debug-types.exp: Include cpexprs.exp.in instead of + cpexprs.exp. + 2020-05-11 Keith Seitz * gdb.ada/arrayparam.exp: Resolve duplicate and tail parentheses diff --git a/gdb/testsuite/gdb.cp/cpexprs-debug-types.exp b/gdb/testsuite/gdb.cp/cpexprs-debug-types.exp index 9499aecf4c6..b93f2e8c157 100644 --- a/gdb/testsuite/gdb.cp/cpexprs-debug-types.exp +++ b/gdb/testsuite/gdb.cp/cpexprs-debug-types.exp @@ -17,4 +17,4 @@ # Run cpexprs.exp with -fdebug-types-section. set flags {additional_flags=-fdebug-types-section} -source $srcdir/$subdir/cpexprs.exp +source $srcdir/$subdir/cpexprs.exp.in diff --git a/gdb/testsuite/gdb.cp/cpexprs.exp b/gdb/testsuite/gdb.cp/cpexprs.exp index 383def9fb64..b16a5ea6e38 100644 --- a/gdb/testsuite/gdb.cp/cpexprs.exp +++ b/gdb/testsuite/gdb.cp/cpexprs.exp @@ -19,750 +19,6 @@ # This file is part of the gdb testsuite. -# A helper proc which sets a breakpoint at FUNC and attempts to -# run to the breakpoint. -proc test_breakpoint {func} { - global DEC - - # Return to the top of the test function every time. - delete_breakpoints - if { ! [gdb_breakpoint test_function] } { - fail "set test_function breakpoint for $func" - } elseif { [gdb_test "continue" \ - "Continuing.\r\n\r\nBreakpoint $DEC+,.*test_function.*" \ - ""] != 0 } { - fail "continue to test_function for $func" - } else { - gdb_breakpoint "$func" - set i [expr {[string last : $func] + 1}] - set efunc [string_to_regexp [string range $func $i end]] - gdb_test "continue" \ - "Continuing.\r\n\r\nBreakpoint $DEC+,.*$efunc.*" \ - "continue to $func" - } -} - -# Add a function to the list of tested functions -# FUNC is the name of the function (which will be passed to gdb commands) -# TYPE is the type of the function, as expected from the "print" command -# PRINT is the name of the function, as expected result of the print command -# *OR* "-", indicating that FUNC should be used (needed for virtual/inherited -# funcs) -# LST is either the expected result of the list command (the comment from -# the source code) *OR* "-", in which case FUNC will be used -# -# Usage: -# add NAME TYPE PRINT LST -# add NAME TYPE PRINT - -proc add_type_regexp {func type print lst} { - global all_functions CONVAR ADDR - - set all_functions($func,type) $type - if {$print == "-"} { - set print $func - } - - # An exception: since gdb canonicalizes C++ output, - # "(void)" must be mutated to "()". - regsub {\(void\)} $print {()} print - - set all_functions($func,print) \ - "$CONVAR = {$type} $ADDR <[string_to_regexp $print].*>" - if {$lst == "-"} { - set lst "$func" - } - set all_functions($func,list) ".*// [string_to_regexp $lst]" -} - -proc add {func type print lst} { - add_type_regexp $func [string_to_regexp $type] $print $lst -} - -proc get {func cmd} { - global all_functions - return $all_functions($func,$cmd) -} - -# Returns a list of function names for a given command -proc get_functions {cmd} { - global all_functions - set result {} - foreach i [array names all_functions *,$cmd] { - if {$all_functions($i) != ""} { - set idx [string last , $i] - if {$idx != -1} { - lappend result [string range $i 0 [expr {$idx - 1}]] - } - } - } - - return [lsort $result] -} - -# Some convenience variables for this test -set DEC {[0-9]}; # a decimal number -set HEX {[0-9a-fA-F]}; # a hexidecimal number -set CONVAR "\\\$$DEC+"; # convenience variable regexp -set ADDR "0x$HEX+"; # address - -# An array of functions/methods that we are testing... -# Each element consists is indexed by NAME,COMMAND, where -# NAME is the function name and COMMAND is the gdb command that -# we are testing. The value of the array for any index pair is -# the expected result of running COMMAND with the NAME as argument. - -# The array holding all functions/methods to test. Valid subindexes -# are (none need character escaping -- "add" will take care of that): - -# add name type print_name list -# NAME,type: value is type of function -# NAME,print: value is print name of function (careful w/inherited/virtual!) -# NAME,list: value is comment in source code on first line of function -# (without the leading "//") -array set all_functions {} - -# "Normal" functions/methods -add {test_function} \ - {int (int, char **)} \ - - \ - - -add {derived::a_function} \ - {void (const derived * const)} \ - - \ - - -add {base1::a_function} \ - {void (const base1 * const)} \ - - \ - - -add {base2::a_function} \ - {void (const base2 * const)} \ - - \ - - - -# Constructors - -# On targets using the ARM EABI, the constructor is expected to return -# "this". -proc ctor_ret { type } { - if { [istarget arm*-*eabi*] || [is_aarch32_target] } { - return "$type *" - } else { - return "void " - } -} - -proc ctor_prefix { type } { - set ret [ctor_ret $type] - return "${ret}($type * const" -} - -proc ctor { type arglist } { - if { $arglist != "" } { - set arglist ", $arglist" - } - return "[ctor_prefix $type]$arglist)" -} - -add {derived::derived} \ - [ctor derived ""] \ - - \ - - -add_type_regexp {base1::base1(void)} \ - "[string_to_regexp [ctor_prefix base1]], (const )?void \\*\\*( const)?\\)" \ - - \ - - -add {base1::base1(int)} \ - [ctor base1 "int"] \ - - \ - - -add_type_regexp {base2::base2} \ - "[string_to_regexp [ctor_prefix base2]], (const )?void \\*\\*( const)?\\)" \ - - \ - - -add {base::base(void)} \ - [ctor base ""] \ - - \ - - -add {base::base(int)} \ - [ctor base "int"] \ - - \ - - - -# Destructors - -# On targets using the ARM EABI, some destructors are expected -# to return "this". Others are void. For internal reasons, -# GCC returns void * instead of $type *; RealView appears to do -# the same. -proc dtor { type } { - if { [istarget arm*-*eabi*] || [is_aarch32_target] } { - set ret "void *" - } else { - set ret "void " - } - return "${ret}($type * const)" -} - -add {base::~base} \ - [dtor base] \ - - \ - - - -# Overloaded methods (all are const) -add {base::overload(void) const} \ - {int (const base * const)} \ - - \ - {base::overload(void) const} -add {base::overload(int) const} \ - {int (const base * const, int)} \ - - \ - - -add {base::overload(short) const} \ - {int (const base * const, short)} \ - - \ - - -add {base::overload(long) const} \ - {int (const base * const, long)} \ - - \ - - -add {base::overload(char*) const} \ - {int (const base * const, char *)} \ - - \ - - -add {base::overload(base&) const} \ - {int (const base * const, base &)} \ - - \ - - - -# Operators -add {base::operator+} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator++} \ - {base (base * const)} \ - - \ - - -add {base::operator+=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator-} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator--} \ - {base (base * const)} \ - - \ - - -add {base::operator-=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator*} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator*=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator/} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator/=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator%} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator%=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator<} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator<=} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator>} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator>=} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator!=} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator==} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator!} \ - {bool (const base * const)} \ - - \ - - -add {base::operator&&} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator||} \ - {bool (const base * const, const base &)} \ - - \ - - -add {base::operator<<} \ - {int (const base * const, int)} \ - - \ - - -add {base::operator<<=} \ - {base (base * const, int)} \ - - \ - - -add {base::operator>>} \ - {int (const base * const, int)} \ - - \ - - -add {base::operator>>=} \ - {base (base * const, int)} \ - - \ - - -add {base::operator~} \ - {int (const base * const)} \ - - \ - - -add {base::operator&} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator&=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator|} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator|=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator^} \ - {int (const base * const, const base &)} \ - - \ - - -add {base::operator^=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator=} \ - {base (base * const, const base &)} \ - - \ - - -add {base::operator()} \ - {void (const base * const)} \ - - \ - - -add {base::operator[]} \ - {int (const base * const, int)} \ - - \ - - -add {base::operator new} \ - {void *(size_t)} \ - - \ - - -add {base::operator delete} \ - {void (void *)} \ - - \ - - -add {base::operator new[]} \ - {void *(size_t)} \ - - \ - - -add {base::operator delete[]} \ - {void (void *)} \ - - \ - - -add {base::operator char*} \ - {char *(const base * const)} \ - - \ - - -add {base::operator fluff*} \ - {fluff *(const base * const)} \ - - \ - - -add {base::operator fluff**} \ - {fluff **(const base * const)} \ - - \ - - -add {base::operator int} \ - {int (const base * const)} \ - - \ - - -add {base::operator fluff const* const*} \ - {const fluff * const *(const base * const)} \ - - \ - - - -# Templates -add {tclass::do_something} \ - {void (tclass * const)} \ - - \ - - -add {tclass::do_something} \ - {void (tclass * const)} \ - - \ - - -add {tclass::do_something} \ - {void (tclass * const)} \ - - \ - - -add {tclass::do_something} \ - {void (tclass * const)} \ - - \ - - -add {tclass::do_something} \ - {void (tclass * const)} \ - - \ - - -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {flubber} \ - {void (void)} \ - - \ - flubber -add {tclass::do_something} \ - {void (tclass * const)} \ - - \ - {tclass::do_something} -add {policy1::policy} \ - [ctor "policy >" "int"] \ - {policy >::policy} \ - {policy::policy} -add {policy2::policy} \ - [ctor "policy >" int] \ - {policy >::policy} \ - {policy::policy} -add {policy3::policy} \ - [ctor "policy >" "int"] \ - {policy >::policy} \ - {policy::policy} -add {policy4::policy} \ - [ctor "policy >" "int"] \ - {policy >::policy} \ - {policy::policy} -add {policy1::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policy2::function} \ - {void (void)} \ - {operation_2::function} \ - {operation_2::function} -add {policy3::function} \ - {void (void)} \ - {operation_3::function} \ - {operation_3::function} -add {policy4::function} \ - {void (void)} \ - {operation_4::function} \ - {operation_4::function} -add {policyd >::policyd} \ - [ctor "policyd >" "int"] \ - - \ - {policyd::policyd} -add {policyd1::policyd} \ - [ctor "policyd >" "int"] \ - {policyd >::policyd} \ - {policyd::policyd} -add {policyd >::~policyd} \ - [dtor "policyd >"] \ - - \ - {policyd::~policyd} -add {policyd1::~policyd} \ - [dtor "policyd >"] \ - {policyd >::~policyd} \ - {policyd::~policyd} -add {policyd >::policyd} \ - [ctor "policyd >" "long"] \ - - \ - {policyd::policyd} -add {policyd2::policyd} \ - [ctor "policyd >" "long"] \ - {policyd >::policyd} \ - {policyd::policyd} -add {policyd >::~policyd} \ - [dtor "policyd >"] \ - - \ - {policyd::~policyd} -add {policyd2::~policyd} \ - [dtor "policyd >"] \ - {policyd >::~policyd} \ - {policyd::~policyd} -add {policyd >::policyd} \ - [ctor "policyd >" "char"] \ - - \ - {policyd::policyd} -add {policyd3::policyd} \ - [ctor "policyd >" "char"] \ - {policyd >::policyd} \ - {policyd::policyd} -add {policyd >::~policyd} \ - [dtor "policyd >"] \ - - \ - {policyd::~policyd} -add {policyd3::~policyd} \ - [dtor "policyd >"] \ - {policyd >::~policyd} \ - {policyd::~policyd} -add {policyd >::policyd} \ - [ctor "policyd >" "base"] \ - - \ - {policyd::policyd} -add {policyd4::policyd} \ - [ctor "policyd >" "base"] \ - {policyd >::policyd} \ - {policyd::policyd} -add {policyd >::~policyd} \ - [dtor "policyd >"] \ - - \ - {policyd::~policyd} -add {policyd4::~policyd} \ - [dtor "policyd >"] \ - {policyd >::~policyd} \ - {policyd::~policyd} -add {policyd, operation_1 > >::policyd} \ - [ctor "policyd, operation_1 > >" "tclass"] \ - - \ - {policyd::policyd} -add {policyd5::policyd} \ - [ctor "policyd, operation_1 > >" "tclass"] \ - {policyd, operation_1 > >::policyd} \ - {policyd::policyd} -add {policyd, operation_1 > >::~policyd} \ - [dtor "policyd, operation_1 > >"] \ - - \ - {policyd::~policyd} -add {policyd5::~policyd} \ - [dtor "policyd, operation_1 > >"] \ - {policyd, operation_1 > >::~policyd} \ - {policyd::~policyd} -add {policyd >::function} \ - {void (void)} \ - {operation_1::function}\ - {operation_1::function} -add {policyd1::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policyd2::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policyd >::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policyd3::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policyd >::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policyd4::function} \ - {void (void)} \ - {operation_1::function} \ - {operation_1::function} -add {policyd, operation_1 > >::function} \ - {void (void)} \ - {operation_1 >::function} \ - {operation_1::function} -add {policyd5::function} \ - {void (void)} \ - {operation_1 >::function} \ - {operation_1::function} - -# Start the test -if {[skip_cplus_tests]} { continue } - -# -# test running programs -# - -standard_testfile cpexprs.cc - -if {[get_compiler_info "c++"]} { - return -1 -} - -if { [info exists flags] } { - # Already set externally. -} else { - # Initialize to empty. - set flags {} -} - -# Include required flags. -set flags "$flags debug c++" - -if {[prepare_for_testing "failed to prepare" $testfile $srcfile "$flags"]} { - return -1 -} - -if {![runto_main]} { - perror "couldn't run to breakpoint" - continue -} - -# Set the listsize to one. This will help with testing "list". -gdb_test "set listsize 1" - -# "print METHOD" -foreach name [get_functions print] { - gdb_test "print $name" [get $name print] -} - -# "list METHOD" -foreach name [get_functions list] { - gdb_test "list $name" [get $name list] -} - -# Running to breakpoint -- use any function we can "list" -foreach name [get_functions list] { - # Skip "test_function", since test_breakpoint uses it - if {[string compare $name "test_function"] != 0} { - test_breakpoint $name - } -} - -# Test c/v gets recognized even without quoting. -foreach cv {{} { const} { volatile} { const volatile}} { - set test "p 'CV::m(int)$cv'" - gdb_test_multiple $test $test { - -re "( = {.*} 0x\[0-9a-f\]+ )\r\n$gdb_prompt $" { - # = {void (CV * const, CV::t)} 0x400944 - set correct $expect_out(1,string) - pass $test - } - } - gdb_test "p CV::m(int)$cv" [string_to_regexp $correct] -} - -# Test TYPENAME:: gets recognized even in parentheses. -gdb_test "p CV_f(int)" { = {int \(int\)} 0x[0-9a-f]+ } -gdb_test "p CV_f(CV::t)" { = {int \(int\)} 0x[0-9a-f]+ } -gdb_test "p CV_f(CV::i)" " = 43" - -gdb_test "p CV_f('cpexprs.cc'::CV::t)" \ - { = {int \(int\)} 0x[0-9a-f]+ } - -# Make sure conversion operator names are canonicalized and properly -# "spelled." -gdb_test "p base::operator const fluff * const *" \ - [get "base::operator fluff const* const*" print] \ - "canonicalized conversion operator name 1" -gdb_test "p base::operator const fluff* const*" \ - [get "base::operator fluff const* const*" print] \ - "canonicalized conversion operator name 2" -gdb_test "p base::operator derived*" \ - "There is no field named operator derived\\*" \ - "undefined conversion operator" - -gdb_exit -return 0 +# Run cpexprs.exp. +set flags {} +source $srcdir/$subdir/cpexprs.exp.in diff --git a/gdb/testsuite/gdb.cp/cpexprs.exp.in b/gdb/testsuite/gdb.cp/cpexprs.exp.in new file mode 100644 index 00000000000..ef302157355 --- /dev/null +++ b/gdb/testsuite/gdb.cp/cpexprs.exp.in @@ -0,0 +1,761 @@ +# cpexprs.exp - C++ expressions tests +# +# Copyright 2008-2020 Free Software Foundation, Inc. +# +# Contributed by Red Hat, originally written by Keith Seitz. +# +# 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 . + +# This file is part of the gdb testsuite. + +# A helper proc which sets a breakpoint at FUNC and attempts to +# run to the breakpoint. +proc test_breakpoint {func} { + global DEC + + # Return to the top of the test function every time. + delete_breakpoints + if { ! [gdb_breakpoint test_function] } { + fail "set test_function breakpoint for $func" + } elseif { [gdb_test "continue" \ + "Continuing.\r\n\r\nBreakpoint $DEC+,.*test_function.*" \ + ""] != 0 } { + fail "continue to test_function for $func" + } else { + gdb_breakpoint "$func" + set i [expr {[string last : $func] + 1}] + set efunc [string_to_regexp [string range $func $i end]] + gdb_test "continue" \ + "Continuing.\r\n\r\nBreakpoint $DEC+,.*$efunc.*" \ + "continue to $func" + } +} + +# Add a function to the list of tested functions +# FUNC is the name of the function (which will be passed to gdb commands) +# TYPE is the type of the function, as expected from the "print" command +# PRINT is the name of the function, as expected result of the print command +# *OR* "-", indicating that FUNC should be used (needed for virtual/inherited +# funcs) +# LST is either the expected result of the list command (the comment from +# the source code) *OR* "-", in which case FUNC will be used +# +# Usage: +# add NAME TYPE PRINT LST +# add NAME TYPE PRINT - +proc add_type_regexp {func type print lst} { + global all_functions CONVAR ADDR + + set all_functions($func,type) $type + if {$print == "-"} { + set print $func + } + + # An exception: since gdb canonicalizes C++ output, + # "(void)" must be mutated to "()". + regsub {\(void\)} $print {()} print + + set all_functions($func,print) \ + "$CONVAR = {$type} $ADDR <[string_to_regexp $print].*>" + if {$lst == "-"} { + set lst "$func" + } + set all_functions($func,list) ".*// [string_to_regexp $lst]" +} + +proc add {func type print lst} { + add_type_regexp $func [string_to_regexp $type] $print $lst +} + +proc get {func cmd} { + global all_functions + return $all_functions($func,$cmd) +} + +# Returns a list of function names for a given command +proc get_functions {cmd} { + global all_functions + set result {} + foreach i [array names all_functions *,$cmd] { + if {$all_functions($i) != ""} { + set idx [string last , $i] + if {$idx != -1} { + lappend result [string range $i 0 [expr {$idx - 1}]] + } + } + } + + return [lsort $result] +} + +# Some convenience variables for this test +set DEC {[0-9]}; # a decimal number +set HEX {[0-9a-fA-F]}; # a hexidecimal number +set CONVAR "\\\$$DEC+"; # convenience variable regexp +set ADDR "0x$HEX+"; # address + +# An array of functions/methods that we are testing... +# Each element consists is indexed by NAME,COMMAND, where +# NAME is the function name and COMMAND is the gdb command that +# we are testing. The value of the array for any index pair is +# the expected result of running COMMAND with the NAME as argument. + +# The array holding all functions/methods to test. Valid subindexes +# are (none need character escaping -- "add" will take care of that): + +# add name type print_name list +# NAME,type: value is type of function +# NAME,print: value is print name of function (careful w/inherited/virtual!) +# NAME,list: value is comment in source code on first line of function +# (without the leading "//") +array set all_functions {} + +# "Normal" functions/methods +add {test_function} \ + {int (int, char **)} \ + - \ + - +add {derived::a_function} \ + {void (const derived * const)} \ + - \ + - +add {base1::a_function} \ + {void (const base1 * const)} \ + - \ + - +add {base2::a_function} \ + {void (const base2 * const)} \ + - \ + - + +# Constructors + +# On targets using the ARM EABI, the constructor is expected to return +# "this". +proc ctor_ret { type } { + if { [istarget arm*-*eabi*] || [is_aarch32_target] } { + return "$type *" + } else { + return "void " + } +} + +proc ctor_prefix { type } { + set ret [ctor_ret $type] + return "${ret}($type * const" +} + +proc ctor { type arglist } { + if { $arglist != "" } { + set arglist ", $arglist" + } + return "[ctor_prefix $type]$arglist)" +} + +add {derived::derived} \ + [ctor derived ""] \ + - \ + - +add_type_regexp {base1::base1(void)} \ + "[string_to_regexp [ctor_prefix base1]], (const )?void \\*\\*( const)?\\)" \ + - \ + - +add {base1::base1(int)} \ + [ctor base1 "int"] \ + - \ + - +add_type_regexp {base2::base2} \ + "[string_to_regexp [ctor_prefix base2]], (const )?void \\*\\*( const)?\\)" \ + - \ + - +add {base::base(void)} \ + [ctor base ""] \ + - \ + - +add {base::base(int)} \ + [ctor base "int"] \ + - \ + - + +# Destructors + +# On targets using the ARM EABI, some destructors are expected +# to return "this". Others are void. For internal reasons, +# GCC returns void * instead of $type *; RealView appears to do +# the same. +proc dtor { type } { + if { [istarget arm*-*eabi*] || [is_aarch32_target] } { + set ret "void *" + } else { + set ret "void " + } + return "${ret}($type * const)" +} + +add {base::~base} \ + [dtor base] \ + - \ + - + +# Overloaded methods (all are const) +add {base::overload(void) const} \ + {int (const base * const)} \ + - \ + {base::overload(void) const} +add {base::overload(int) const} \ + {int (const base * const, int)} \ + - \ + - +add {base::overload(short) const} \ + {int (const base * const, short)} \ + - \ + - +add {base::overload(long) const} \ + {int (const base * const, long)} \ + - \ + - +add {base::overload(char*) const} \ + {int (const base * const, char *)} \ + - \ + - +add {base::overload(base&) const} \ + {int (const base * const, base &)} \ + - \ + - + +# Operators +add {base::operator+} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator++} \ + {base (base * const)} \ + - \ + - +add {base::operator+=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator-} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator--} \ + {base (base * const)} \ + - \ + - +add {base::operator-=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator*} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator*=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator/} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator/=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator%} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator%=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator<} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator<=} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator>} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator>=} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator!=} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator==} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator!} \ + {bool (const base * const)} \ + - \ + - +add {base::operator&&} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator||} \ + {bool (const base * const, const base &)} \ + - \ + - +add {base::operator<<} \ + {int (const base * const, int)} \ + - \ + - +add {base::operator<<=} \ + {base (base * const, int)} \ + - \ + - +add {base::operator>>} \ + {int (const base * const, int)} \ + - \ + - +add {base::operator>>=} \ + {base (base * const, int)} \ + - \ + - +add {base::operator~} \ + {int (const base * const)} \ + - \ + - +add {base::operator&} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator&=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator|} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator|=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator^} \ + {int (const base * const, const base &)} \ + - \ + - +add {base::operator^=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator=} \ + {base (base * const, const base &)} \ + - \ + - +add {base::operator()} \ + {void (const base * const)} \ + - \ + - +add {base::operator[]} \ + {int (const base * const, int)} \ + - \ + - +add {base::operator new} \ + {void *(size_t)} \ + - \ + - +add {base::operator delete} \ + {void (void *)} \ + - \ + - +add {base::operator new[]} \ + {void *(size_t)} \ + - \ + - +add {base::operator delete[]} \ + {void (void *)} \ + - \ + - +add {base::operator char*} \ + {char *(const base * const)} \ + - \ + - +add {base::operator fluff*} \ + {fluff *(const base * const)} \ + - \ + - +add {base::operator fluff**} \ + {fluff **(const base * const)} \ + - \ + - +add {base::operator int} \ + {int (const base * const)} \ + - \ + - +add {base::operator fluff const* const*} \ + {const fluff * const *(const base * const)} \ + - \ + - + +# Templates +add {tclass::do_something} \ + {void (tclass * const)} \ + - \ + - +add {tclass::do_something} \ + {void (tclass * const)} \ + - \ + - +add {tclass::do_something} \ + {void (tclass * const)} \ + - \ + - +add {tclass::do_something} \ + {void (tclass * const)} \ + - \ + - +add {tclass::do_something} \ + {void (tclass * const)} \ + - \ + - +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {flubber} \ + {void (void)} \ + - \ + flubber +add {tclass::do_something} \ + {void (tclass * const)} \ + - \ + {tclass::do_something} +add {policy1::policy} \ + [ctor "policy >" "int"] \ + {policy >::policy} \ + {policy::policy} +add {policy2::policy} \ + [ctor "policy >" int] \ + {policy >::policy} \ + {policy::policy} +add {policy3::policy} \ + [ctor "policy >" "int"] \ + {policy >::policy} \ + {policy::policy} +add {policy4::policy} \ + [ctor "policy >" "int"] \ + {policy >::policy} \ + {policy::policy} +add {policy1::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policy2::function} \ + {void (void)} \ + {operation_2::function} \ + {operation_2::function} +add {policy3::function} \ + {void (void)} \ + {operation_3::function} \ + {operation_3::function} +add {policy4::function} \ + {void (void)} \ + {operation_4::function} \ + {operation_4::function} +add {policyd >::policyd} \ + [ctor "policyd >" "int"] \ + - \ + {policyd::policyd} +add {policyd1::policyd} \ + [ctor "policyd >" "int"] \ + {policyd >::policyd} \ + {policyd::policyd} +add {policyd >::~policyd} \ + [dtor "policyd >"] \ + - \ + {policyd::~policyd} +add {policyd1::~policyd} \ + [dtor "policyd >"] \ + {policyd >::~policyd} \ + {policyd::~policyd} +add {policyd >::policyd} \ + [ctor "policyd >" "long"] \ + - \ + {policyd::policyd} +add {policyd2::policyd} \ + [ctor "policyd >" "long"] \ + {policyd >::policyd} \ + {policyd::policyd} +add {policyd >::~policyd} \ + [dtor "policyd >"] \ + - \ + {policyd::~policyd} +add {policyd2::~policyd} \ + [dtor "policyd >"] \ + {policyd >::~policyd} \ + {policyd::~policyd} +add {policyd >::policyd} \ + [ctor "policyd >" "char"] \ + - \ + {policyd::policyd} +add {policyd3::policyd} \ + [ctor "policyd >" "char"] \ + {policyd >::policyd} \ + {policyd::policyd} +add {policyd >::~policyd} \ + [dtor "policyd >"] \ + - \ + {policyd::~policyd} +add {policyd3::~policyd} \ + [dtor "policyd >"] \ + {policyd >::~policyd} \ + {policyd::~policyd} +add {policyd >::policyd} \ + [ctor "policyd >" "base"] \ + - \ + {policyd::policyd} +add {policyd4::policyd} \ + [ctor "policyd >" "base"] \ + {policyd >::policyd} \ + {policyd::policyd} +add {policyd >::~policyd} \ + [dtor "policyd >"] \ + - \ + {policyd::~policyd} +add {policyd4::~policyd} \ + [dtor "policyd >"] \ + {policyd >::~policyd} \ + {policyd::~policyd} +add {policyd, operation_1 > >::policyd} \ + [ctor "policyd, operation_1 > >" "tclass"] \ + - \ + {policyd::policyd} +add {policyd5::policyd} \ + [ctor "policyd, operation_1 > >" "tclass"] \ + {policyd, operation_1 > >::policyd} \ + {policyd::policyd} +add {policyd, operation_1 > >::~policyd} \ + [dtor "policyd, operation_1 > >"] \ + - \ + {policyd::~policyd} +add {policyd5::~policyd} \ + [dtor "policyd, operation_1 > >"] \ + {policyd, operation_1 > >::~policyd} \ + {policyd::~policyd} +add {policyd >::function} \ + {void (void)} \ + {operation_1::function}\ + {operation_1::function} +add {policyd1::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policyd2::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policyd >::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policyd3::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policyd >::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policyd4::function} \ + {void (void)} \ + {operation_1::function} \ + {operation_1::function} +add {policyd, operation_1 > >::function} \ + {void (void)} \ + {operation_1 >::function} \ + {operation_1::function} +add {policyd5::function} \ + {void (void)} \ + {operation_1 >::function} \ + {operation_1::function} + +# Start the test +if {[skip_cplus_tests]} { continue } + +# +# test running programs +# + +standard_testfile cpexprs.cc + +if {[get_compiler_info "c++"]} { + return -1 +} + +# Include required flags. +set flags "$flags debug c++" + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile "$flags"]} { + return -1 +} + +if {![runto_main]} { + perror "couldn't run to breakpoint" + continue +} + +# Set the listsize to one. This will help with testing "list". +gdb_test "set listsize 1" + +# "print METHOD" +foreach name [get_functions print] { + gdb_test "print $name" [get $name print] +} + +# "list METHOD" +foreach name [get_functions list] { + gdb_test "list $name" [get $name list] +} + +# Running to breakpoint -- use any function we can "list" +foreach name [get_functions list] { + # Skip "test_function", since test_breakpoint uses it + if {[string compare $name "test_function"] != 0} { + test_breakpoint $name + } +} + +# Test c/v gets recognized even without quoting. +foreach cv {{} { const} { volatile} { const volatile}} { + set test "p 'CV::m(int)$cv'" + gdb_test_multiple $test $test { + -re "( = {.*} 0x\[0-9a-f\]+ )\r\n$gdb_prompt $" { + # = {void (CV * const, CV::t)} 0x400944 + set correct $expect_out(1,string) + pass $test + } + } + gdb_test "p CV::m(int)$cv" [string_to_regexp $correct] +} + +# Test TYPENAME:: gets recognized even in parentheses. +gdb_test "p CV_f(int)" { = {int \(int\)} 0x[0-9a-f]+ } +gdb_test "p CV_f(CV::t)" { = {int \(int\)} 0x[0-9a-f]+ } +gdb_test "p CV_f(CV::i)" " = 43" + +gdb_test "p CV_f('cpexprs.cc'::CV::t)" \ + { = {int \(int\)} 0x[0-9a-f]+ } + +# Make sure conversion operator names are canonicalized and properly +# "spelled." +gdb_test "p base::operator const fluff * const *" \ + [get "base::operator fluff const* const*" print] \ + "canonicalized conversion operator name 1" +gdb_test "p base::operator const fluff* const*" \ + [get "base::operator fluff const* const*" print] \ + "canonicalized conversion operator name 2" +gdb_test "p base::operator derived*" \ + "There is no field named operator derived\\*" \ + "undefined conversion operator" + +gdb_exit +return 0