# Copyright 2022 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 . */ # Test setting a breakpoint at "f(std::string)". # # GDB should be able to expand the std::string typedef, and then set # the breakpoint using the resulting name. In the Itanium ABI's # mangling scheme, "std::string", "std::istream", "std::iostream", # "std::ostream" are special, though, they have corresponding standard # abbreviations. The libiberty demangler only expands these standard # abbreviations to their full non-typedef underlying type if the # DMGL_VERBOSE option is requested. By default it expands them to the # user-friendly "std::string", etc. typedefs. GDB didn't use to use # that option, and would instead prevent expansion of the # "std::string" (etc.) standard-abbreviation typedefs at # breakpoint-set type, such that the function name used for function # lookup would match the "std::string" present in the function's # non-DMGL_VERBOSE demangled name. # # For example (DMGL_VERBOSE): # # $ echo "_Z1fSs" | c++filt # f(std::basic_string, std::allocator >) # # vs (no DMGL_VERBOSE): # # $ echo "_Z1fSs" | c++filt --no-verbose # f(std::string) # # This design broke setting a breakpoint at "f(std::string)" when the # libstdc++ C++11 ABI was introduced, as the "f(std::string)" # function's mangled name no longer uses a standard substitution for # std::string... # # I.e., with the libstdc++ C++11 ABI, we now have (and DMGL_VERBOSE # makes no difference): # # $ echo _Z1fNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE | c++filt # f(std::__cxx11::basic_string, std::allocator >) # # So nowadays, GDB always uses DMGL_VERBOSE and no longer prevents # std::string (etc.) typedef expansion. This test exercises both # pre-C++11 and C++11 ABIs for this reason. On non-libstdc++ systems # where _GLIBCXX_USE_CXX11_ABI has no effect, we just end up running # the test twice with whatever ABI is used. standard_testfile .cc if { [skip_cplus_tests] } { continue } # CXX11_ABI specifies the value to define _GLIBCXX_USE_CXX11_ABI as. proc test {cxx11_abi} { global srcdir subdir srcfile binfile testfile set options \ [list c++ debug additional_flags=-D_GLIBCXX_USE_CXX11_ABI=$cxx11_abi] if { [gdb_compile \ "${srcdir}/${subdir}/${srcfile}" "${binfile}-${cxx11_abi}.o" \ object $options] != "" } { untested "failed to compile" return -1 } clean_restart ${testfile}-${cxx11_abi}.o # Since we're debugging an .o file, GDB doesn't figure out we're # debugging C++ code and the current language when auto, is # guessed as C. gdb_test_no_output "set language c++" # Get the type std::string is a typedef for. We'll try to set a # breakpoint using the expanded type too. set realtype "" set type "std::string" gdb_test_multiple "whatis /r $type" "" { -re -wrap "type = (\[^\r\n\]+)" { set realtype $expect_out(1,string) gdb_assert {![string eq "$realtype" "$type"]} \ $gdb_test_name } } # GDB should be able to expand the std::string typedef in the # function prototype using C++ logic even if the current language # is C. foreach_with_prefix lang {"c" "c++"} { gdb_test_no_output "set language $lang" gdb_test "break f($type)" "$srcfile, line $::decimal\\." if { $realtype != "" } { gdb_test "break f($realtype)" "$srcfile, line $::decimal\\." } } } foreach_with_prefix _GLIBCXX_USE_CXX11_ABI {0 1} { test $_GLIBCXX_USE_CXX11_ABI }