# Copyright (C) 1998-1999, 2001, 2004, 2007-2012 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 . # written by Elena Zannoni (ezannoni@cygnus.com) # modified by Michael Chastain (chastain@redhat.com) # This file is part of the gdb testsuite # # tests for overloaded member functions. Set breakpoints on # overloaded member functions # global timeout set timeout 15 # # test running programs # if { [skip_cplus_tests] } { continue } standard_testfile .cc if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { return -1 } # set it up at a breakpoint so we can play with the variable values # if {![runto_main]} { perror "couldn't run to breakpoint" continue } # When I ask gdb to set a breakpoint on an overloaded function, # gdb gives me a choice menu. I might get stuck in that choice menu # (for example, if C++ name mangling is not working properly). # # This procedure issues a command that works at either the menu # prompt or the command prompt to get back to the command prompt. # # Note that an empty line won't do it (it means 'repeat the previous command' # at top level). A line with a single space in it works nicely. proc take_gdb_out_of_choice_menu {} { global gdb_prompt gdb_test_multiple " " " " { -re ".*$gdb_prompt $" { } timeout { perror "could not resynchronize to command prompt (timeout)" continue } } } # This procedure sets an overloaded breakpoint. # When I ask for such a breakpoint, gdb gives me a menu of 'cancel' 'all' # and a bunch of choices. I then choose from that menu by number. proc set_bp_overloaded {name expectedmenu mychoice bpnumber linenumber} { global gdb_prompt hex srcfile # Get into the overload menu. send_gdb "break $name\n" gdb_expect { -re "$expectedmenu" { pass "bp menu for $name choice $mychoice" # Choose my choice. send_gdb "$mychoice\n" gdb_expect { -re "Breakpoint $bpnumber at $hex: file.*$srcfile, line $linenumber.\r\n$gdb_prompt $" { pass "set bp $bpnumber on $name $mychoice line $linenumber" } -re ".*$gdb_prompt $" { fail "set bp $bpnumber on $name $mychoice line $linenumber (bad bp)" } timeout { fail "set bp $bpnumber on $name $mychoice line $linenumber (timeout)" take_gdb_out_of_choice_menu } } } -re ".*\r\n> " { fail "bp menu for $name choice $mychoice (bad menu)" take_gdb_out_of_choice_menu } -re ".*$gdb_prompt $" { fail "bp menu for $name choice $mychoice (no menu)" } timeout { fail "bp menu for $name choice $mychoice (timeout)" take_gdb_out_of_choice_menu } } } # Compute the expected menu for overload1arg. # Note the arg type variations for void and integer types. # This accommodates different versions of g++. # Probe for the real types. This will do some unnecessary checking # for some simple types (like "int"), but it's just easier to loop # over all_types instead of calling out just the exceptions. # This list /must/ remain in the same order that the methods are # called in the source code. Otherwise the order in which breakpoints # are hit (tested below) will be incorrect. set all_types [list void char signed_char unsigned_char short_int \ unsigned_short_int int unsigned_int long_int \ unsigned_long_int float double] # ARGUMENTS is an array that will map from synthetic type to argument # expressions in the source code, which is of the form "arg = $decimal". # ARGUMENTS stores this decimal number. array set arguments { void "" char 2 signed_char 3 unsigned_char 4 short_int 5 unsigned_short_int 6 int 7 unsigned_int 8 long_int 9 unsigned_long_int 10 float 100(.0)? double 200(.0)? } unset -nocomplain line types foreach type $all_types { # TYPES is an array that maps the synthetic names in ALL_TYPES # to the real type used in the debugger. These will be checked # below and changed if the debugger thinks they are different from # their default values. set types($type) [join [split $type "_"] " "] # LINE is an array that will map from synthetic type to line number. # in the source code. set line($type) [gdb_get_line_number "fo1 $type"] # Probe for the actual type. gdb_test_multiple "print &foo::overload1arg($types($type))" \ "probe $types($type)" { -re ".*\.*$gdb_prompt $" { regexp {<.*>} $expect_out(0,string) func regexp {\(.*\)} $func real_type # Store the real type into TYPES. set types($type) [string trim $real_type {()}] # Create an inverse mapping of the actual type to # the synthetic type. set type_map("$types($type)") $type pass "detect $type" } } } # This is a list of the actual overloaded method arguments. set overloads {} foreach type $all_types { lappend overloads $types($type) } # Sort this list alphabetically. set overloads [lsort $overloads] # Create the menu list. set items {"cancel" "all"} foreach ovld $overloads { lappend items "$srcfile:foo::overload1arg\\($ovld\\)" } set menu_items {} set idx 0 foreach item $items { lappend menu_items ".$idx. .*$item" incr idx } set menu_overload1arg [join $menu_items {[\r\n]*}] append menu_overload1arg {[\r\n]*> $} # Set multiple-symbols to "ask", to allow us to test the use # of the multiple-choice menu when breaking on an overloaded method. gdb_test_no_output "set multiple-symbols ask" # Set breakpoints on foo::overload1arg, one by one. set bpnum 1 set method "foo::overload1arg" for {set idx 0} {$idx < [llength $overloads]} {incr idx} { set type [lindex $overloads $idx] set_bp_overloaded $method $menu_overload1arg \ [expr {$idx + 2}] [incr bpnum] $line($type_map("$type")) } # Verify the breakpoints. set bptable "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*" append bptable "\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main(\\((|void)\\))? at.*$srcfile:49\[\r\n\]+" append bptable "\[\t \]+breakpoint already hit 1 time\[\r\n\]+" foreach ovld $overloads { append bptable [format "\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(%s\\) at.*$srcfile:%d\[\r\n\]+" $ovld \ $line($type_map("$ovld"))] } gdb_test "info break" $bptable "breakpoint info (after setting one-by-one)" # Test choice "cancel". # This is copy-and-paste from set_bp_overloaded. send_gdb "break foo::overload1arg\n" gdb_expect { -re "$menu_overload1arg" { pass "bp menu for foo::overload1arg choice cancel" # Choose cancel. send_gdb "0\n" gdb_expect { -re "canceled\r\n$gdb_prompt $" { pass "set bp on overload1arg canceled" } -re "cancelled\r\n$gdb_prompt $" { pass "set bp on overload1arg canceled" } -re ".*$gdb_prompt $" { fail "set bp on overload1arg canceled (bad message)" } timeout { fail "set bp on overload1arg canceled (timeout)" take_gdb_out_of_choice_menu } } } -re ".*\r\n> " { fail "bp menu for foo::overload1arg choice cancel (bad menu)" take_gdb_out_of_choice_menu } -re ".*$gdb_prompt $" { fail "bp menu for foo::overload1arg choice cancel (no menu)" } timeout { fail "bp menu for foo::overload1arg choice cancel (timeout)" take_gdb_out_of_choice_menu } } gdb_test "info break" $bptable "breakpoint info (after cancel)" # Delete these breakpoints. send_gdb "delete breakpoints\n" gdb_expect { -re "Delete all breakpoints.* $" { send_gdb "y\n" gdb_expect { -re ".*$gdb_prompt $" { pass "delete all breakpoints" } timeout { fail "delete all breakpoints (timeout)" } } } timeout { fail "delete all breakpoints (timeout)" } } gdb_test "info breakpoints" "No breakpoints or watchpoints." "breakpoint info (after delete)" # Test choice "all". # This is copy-and-paste from set_bp_overloaded. send_gdb "break foo::overload1arg\n" gdb_expect { -re "$menu_overload1arg" { pass "bp menu for foo::overload1arg choice all" # Choose all. send_gdb "1\n" gdb_expect { -re "Breakpoint $decimal at $hex: foo::overload1arg. .12 locations.\r\n.*$gdb_prompt $" { pass "set bp on overload1arg all" } -re ".*$gdb_prompt $" { fail "set bp on overload1arg all (bad message)" } timeout { fail "set bp on overload1arg all (timeout)" take_gdb_out_of_choice_menu } } } -re ".*\r\n> " { fail "bp menu for foo::overload1arg choice all (bad menu)" take_gdb_out_of_choice_menu } -re ".*$gdb_prompt $" { fail "bp menu for foo::overload1arg choice all (no menu)" } timeout { fail "bp menu for foo::overload1arg choice all (timeout)" take_gdb_out_of_choice_menu } } # Create the breakpoint table for "info breakpoint". set bptable "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*\[\r\n]+" append bptable "\[0-9\]+\[\t \]+breakpoint\[\t \]+keep\[\t \]y\[\t \]+.*\[\r\n\]+" foreach ovld {void char signed_char unsigned_char short_int \ unsigned_short_int int unsigned_int long_int \ unsigned_long_int float double} { append bptable [format "\[0-9\]+.\[0-9\]+\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(%s\\) at.*$srcfile:%d\[\r\n\]+" \ $types($ovld) $line($ovld)] } gdb_test "info break" $bptable "breakpoint info (after setting on all)" # Run through each breakpoint. proc continue_to_bp_overloaded {bpnumber might_fail line argtype argument} { global gdb_prompt hex decimal srcfile if {$argument == ""} { set actuals "" } else { set actuals "arg=$argument" if {[regexp {char} $argtype]} { append actuals " \\'\\\\00$argument\\'" } } if {[string match $argtype "void"]} { set body "return $decimal;" } else { set body "arg = 0; return $decimal;" } gdb_test_multiple "continue" "continue to bp overloaded : $argtype" { -re "Continuing.\r\n\r\nBreakpoint $bpnumber, foo::overload1arg \\(this=${hex}(, )?$actuals\\) at .*$srcfile:$line\r\n$decimal\[\t \]+{ $body }.*$gdb_prompt $" { pass "continue to bp overloaded : $argtype" } -re "Continuing.\r\n\r\nBreakpoint $bpnumber, foo::overload1arg \\(this=${hex}, arg=.*\\) at .*$srcfile:$line\r\n$decimal\[\t \]+{ $body }.*$gdb_prompt $" { if $might_kfail { kfail "c++/8130" "continue to bp overloaded : $argtype" } else { fail "continue to bp overloaded : $argtype" } } } } # An array which describes which of these methods might be expected # to kfail on GCC 2.95. See C++/8210. array set might_fail { void 0 char 1 signed_char 1 unsigned_char 1 short_int 1 unsigned_short_int 1 int 0 unsigned_int 0 long_int 0 unsigned_long_int 0 float 0 double 1 } foreach type $all_types { continue_to_bp_overloaded 14 $might_fail($type) $line($type) \ $type $arguments($type) } # Test breaking on an overloaded function when multiple-symbols # is set to "cancel" gdb_test_no_output "set multiple-symbols cancel" gdb_test "break foo::foofunc" \ "canceled.*" # Test breaking on an overloaded function when multiple-symbols # is set to "all" gdb_test_no_output "set multiple-symbols all" gdb_test "break foo::foofunc" \ "Breakpoint \[0-9\]+ at ${hex}: foo::foofunc. .2 locations..*" # That's all, folks. unset -nocomplain line types gdb_continue_to_end "finish program"