aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/gdb.cp/pretty-print.cc80
-rw-r--r--gdb/testsuite/gdb.cp/pretty-print.exp53
-rw-r--r--gdb/testsuite/gdb.cp/pretty-print.py82
3 files changed, 215 insertions, 0 deletions
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])