diff options
Diffstat (limited to 'gdb')
-rwxr-xr-x | gdb/contrib/check-gnu-style-pre-commit.sh | 42 | ||||
-rw-r--r-- | gdb/cp-support.c | 9 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/pretty-print.cc | 80 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/pretty-print.exp | 53 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/pretty-print.py | 82 |
5 files changed, 262 insertions, 4 deletions
diff --git a/gdb/contrib/check-gnu-style-pre-commit.sh b/gdb/contrib/check-gnu-style-pre-commit.sh new file mode 100755 index 0000000..ab4b5e7 --- /dev/null +++ b/gdb/contrib/check-gnu-style-pre-commit.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# Copyright (C) 2025 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/>. + +set -e + +scriptdir=$(cd "$(dirname "$0")" || exit 1; pwd -P) + +tmp="" + +cleanup() +{ + if [ "$tmp" != "" ]; then + rm -f "$tmp" + fi +} + +# Schedule cleanup. +trap cleanup EXIT + +# Get temporary file. +tmp=$(mktemp) + +# Generate patch. +git diff --staged "$@" \ + > "$tmp" + +# Verify patch. Ignore exit status. +"$scriptdir"/../../contrib/check_GNU_style.py "$tmp" \ + || true diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 7cfb545..5d459da 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -165,7 +165,7 @@ inspect_type (struct demangle_parse_info *info, { const char *new_name = (*finder) (otype, data); - if (new_name != NULL) + if (new_name != nullptr && strcmp (new_name, name) != 0) { ret_comp->u.s_name.s = new_name; ret_comp->u.s_name.len = strlen (new_name); @@ -378,9 +378,10 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info, struct demangle_component newobj; buf.write (d_left (comp)->u.s_name.s, d_left (comp)->u.s_name.len); - newobj.type = DEMANGLE_COMPONENT_NAME; - newobj.u.s_name.s = obstack_strdup (&info->obstack, buf.string ()); - newobj.u.s_name.len = buf.size (); + cplus_demangle_fill_name (&newobj, + obstack_strdup (&info->obstack, + buf.string ()), + buf.size ()); if (inspect_type (info, &newobj, finder, data)) { char *s; diff --git a/gdb/testsuite/gdb.cp/pretty-print.cc b/gdb/testsuite/gdb.cp/pretty-print.cc new file mode 100644 index 0000000..9065e15 --- /dev/null +++ b/gdb/testsuite/gdb.cp/pretty-print.cc @@ -0,0 +1,80 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025 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/>. */ + +namespace std +{ + +inline namespace __cxx11 {} + +template <typename> struct allocator {}; + +template <class> struct char_traits; + +inline namespace __cxx11 { + +template <typename _CharT, typename = char_traits<_CharT>, + typename = allocator<_CharT>> + +class basic_string; + +} // namespace __cx11 + +typedef basic_string<char> string; + +template <typename> struct allocator_traits; + +template <typename _Tp> struct allocator_traits<allocator<_Tp>> { + using pointer = _Tp *; +}; + +} // namespace std + +struct __alloc_traits : std::allocator_traits<std::allocator<char>> {}; + +namespace std +{ + +inline namespace __cxx11 +{ + +template <typename, typename, typename> struct basic_string +{ + typedef long size_type; + + size_type npos; + + struct _Alloc_hider + { + _Alloc_hider(__alloc_traits::pointer, const allocator<char> &); + } _M_dataplus; + + basic_string(char *, allocator<char> __a = allocator<char>()) + : _M_dataplus(0, __a) {} +}; + +} // namespace __cxx11 + +} // namespace std + +static char bar[] = "bar"; + +int +main (void) +{ + std::string foo = bar; + return 0; +} diff --git a/gdb/testsuite/gdb.cp/pretty-print.exp b/gdb/testsuite/gdb.cp/pretty-print.exp new file mode 100644 index 0000000..e1f0475 --- /dev/null +++ b/gdb/testsuite/gdb.cp/pretty-print.exp @@ -0,0 +1,53 @@ +# Copyright 2025 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/>. + +# Print std::string::npos using c++ pretty-printer. Todo: convert this to a +# DWARF assembly test-case, such that the regression test also works for clang. + +standard_testfile .cc + +set opts {} +lappend opts debug +lappend opts c++ +if {[have_compile_flag -fno-eliminate-unused-debug-symbols]} { + lappend opts additional_flags=-fno-eliminate-unused-debug-symbols + # Work around clang warning -Wunused-command-line-argument. + lappend opts nowarnings +} + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile $opts]} { + return +} + +gdb_test_no_output "source $srcdir/$subdir/pretty-print.py" \ + "load libstdc++ pretty printers" + +gdb_test_no_output \ + "python register_type_printers(gdb.current_objfile())" \ + "register libstdc++ pretty printers" + +gdb_test "whatis std::string" \ + "std::string" + +# Regression test for PR c++/33480. GDB used to hang, at least if the GDB +# build optimization flags triggered some uninitialized variables in the right +# way. I was not able to reproduce the hang with clang, due to different +# debug info. +# +# Prints different strings due to different debug info: +# - std::string::size_type with gcc, and +# - size_type with clang +gdb_test "whatis std::string::npos" \ + "(std::string::)?size_type" diff --git a/gdb/testsuite/gdb.cp/pretty-print.py b/gdb/testsuite/gdb.cp/pretty-print.py new file mode 100644 index 0000000..6ee8d71 --- /dev/null +++ b/gdb/testsuite/gdb.cp/pretty-print.py @@ -0,0 +1,82 @@ +# Copyright (C) 2008-2025 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/>. + +# Reduced copy of /usr/share/gcc-15/python/libstdcxx/v6/printers.py. + +import gdb +import gdb.printing +import gdb.types + + +class FilteringTypePrinter(object): + + def __init__(self, template, name, targ1=None): + self._template = template + self.name = name + self._targ1 = targ1 + self.enabled = True + + class _recognizer(object): + def __init__(self, template, name, targ1): + self._template = template + self.name = name + self._targ1 = targ1 + self._type_obj = None + + def recognize(self, type_obj): + if type_obj.tag is None: + return None + + if self._type_obj is None: + if self._targ1 is not None: + s = "{}<{}".format(self._template, self._targ1) + if not type_obj.tag.startswith(s): + return None + elif not type_obj.tag.startswith(self._template): + return None + + try: + self._type_obj = gdb.lookup_type(self.name).strip_typedefs() + except: + pass + + if self._type_obj is None: + return None + + t1 = gdb.types.get_basic_type(self._type_obj) + t2 = gdb.types.get_basic_type(type_obj) + if t1 == t2: + return self.name + + if self._template.split("::")[-1] == "basic_string": + s1 = self._type_obj.tag.replace("__cxx11::", "") + s2 = type_obj.tag.replace("__cxx11::", "") + if s1 == s2: + return self.name + + return None + + def instantiate(self): + return self._recognizer(self._template, self.name, self._targ1) + + +def add_one_type_printer(obj, template, name, targ1=None): + printer = FilteringTypePrinter("std::" + template, "std::" + name, targ1) + gdb.types.register_type_printer(obj, printer) + + +def register_type_printers(obj): + for ch in (("", "char"),): + add_one_type_printer(obj, "__cxx11::basic_string", ch[0] + "string", ch[1]) |