Update libstdc++ pretty printers from GCC 16 GTS

Add incremental prettyprinter update patches from GTS 15 to GTS 16.

Resolves: RHEL-169098

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Siddhesh Poyarekar 2026-07-09 15:25:59 -04:00
parent d5165908bb
commit 62cd20ee1a
3 changed files with 419 additions and 1 deletions

View File

@ -5,7 +5,7 @@
%global gcc_major 11
# Note, gcc_release must be integer, if you want to add suffixes to
# %%{release}, append them after %%{gcc_release} on Release: line.
%global gcc_release 14
%global gcc_release 15
%global nvptx_tools_gitrev 5f6f343a302d620b0868edab376c00b15741e39e
%global newlib_cygwin_gitrev 50e2a63b04bdd018484605fbb954fd1bd5147fa0
%global _unpackaged_files_terminate_build 0
@ -347,6 +347,8 @@ Patch109: gcc11-fortran-fdec-add-missing-indexes.patch
Patch1000: gcc11-libstdc++-prettyprinter-update-15.patch
Patch1001: gcc11-libstdc++-prettyprinter-update-15-tests.patch
Patch1002: gcc11-libstdc++-prettyprinter-update-15-tests-48362.patch
Patch1003: gcc11-libstdc++-prettyprinter-update-16.patch
Patch1004: gcc11-libstdc++-prettyprinter-update-16-tests.patch
# Backports
Patch2000: gcc11-fix-failures-with-default-SSP.patch
@ -1071,6 +1073,8 @@ mark them as cross compiled.
%patch1000 -p1 -b .libstdc++-prettyprinter-update-15
%patch1001 -p1 -b .libstdc++-prettyprinter-update-15-tests
%patch1002 -p1 -b .libstdc++-prettyprinter-update-15-tests-48362
%patch1003 -p1 -b .libstdc++-prettyprinter-update-16
%patch1004 -p1 -b .libstdc++-prettyprinter-update-16-tests
%patch2000 -p1 -b .fix-failures-with-default-SSP
%patch2001 -p1 -b .disable-stack-protector-for-tests-relying-on-stack-offset
@ -3871,6 +3875,9 @@ end
%endif
%changelog
* Thu Jul 09 2026 Siddhesh Poyarekar <siddhesh@redhat.com> - 11.5.0-15
- Update libstdc++ pretty printers from GCC 16 GTS (RHEL-169098)
* Thu Oct 30 2025 David Malcolm <dmalcolm@redhat.com> - 11.5.0-14
- Add backport of upstream r15-8946-g580664d1b66a5d to gcc 11, adding
branches and calls to gcov output, but not conditions (RHEL-105416).

View File

@ -0,0 +1,120 @@
.../testsuite/libstdc++-prettyprinters/compat.cc | 36 +++++++++++++++++++++-
.../testsuite/libstdc++-prettyprinters/cxx11.cc | 2 +-
.../testsuite/libstdc++-prettyprinters/cxx17.cc | 2 +-
.../libstdc++-prettyprinters/filesystem-ts.cc | 2 +-
.../libstdc++-prettyprinters/libfundts.cc | 2 +-
5 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
index 2ef5979834f..35ec5cf2398 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
@@ -1,7 +1,7 @@
// { dg-options "-g -O0" }
// { dg-do run { target c++11 } }
-// Copyright (C) 2014-2025 Free Software Foundation, Inc.
+// Copyright (C) 2014-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -88,6 +88,30 @@ namespace std
this->_M_payload._M_engaged = true;
}
};
+
+ using uintptr_t = __UINTPTR_TYPE__;
+ template<typename T> struct shared_ptr;
+ template<typename T> struct atomic;
+ template<> struct atomic<uintptr_t> { uintptr_t _M_i; };
+ template<typename T> struct sp_atomic;
+ struct sp_counts { int _M_use_count; int _M_weak_count; };
+
+ // Old representation of std::atomic<std::shared_ptr<T>>, before GCC 16
+ template<typename T>
+ struct sp_atomic<shared_ptr<T>>
+ {
+ T* _M_ptr = nullptr;
+ struct Impl {
+ atomic<uintptr_t> _M_val;
+ using pointer = sp_counts*;
+ } _M_refcount;
+ };
+ template<typename T>
+ struct atomic<shared_ptr<T>>
+ {
+ sp_atomic<shared_ptr<T>> _M_impl;
+ };
+
} // namespace std
int
@@ -110,6 +134,16 @@ main()
optional<void*> op{nullptr};
// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } }
+ std::atomic<std::shared_ptr<int>> aspe{};
+// { dg-final { note-test aspe {std::atomic<std::shared_ptr<int>> (empty) = {get() = 0x0}} } }
+
+ std::sp_counts counts{ 1, 3 };
+ std::sp_atomic<std::shared_ptr<int>>::Impl::pointer p = &counts;
+ std::atomic<std::shared_ptr<int>> asp{};
+ asp._M_impl._M_ptr = reinterpret_cast<int*>(0x1234abcd);
+ asp._M_impl._M_refcount._M_val._M_i = reinterpret_cast<std::uintptr_t>(p);
+// { dg-final { note-test asp {std::atomic<std::shared_ptr<int>> (use count 1, weak count 2) = {get() = 0x1234abcd}} } }
+
__builtin_puts("");
return 0; // Mark SPOT
}
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index 23f6d97ddd4..61ea24e7bb2 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -1,7 +1,7 @@
// { dg-do run { target c++11 } }
// { dg-options "-g -O0" }
-// Copyright (C) 2011-2025 Free Software Foundation, Inc.
+// Copyright (C) 2011-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
index 6dd2b60c0a5..3a8dd925dd6 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
@@ -1,7 +1,7 @@
// { dg-options "-g -O0" }
// { dg-do run { target c++17 } }
-// Copyright (C) 2014-2025 Free Software Foundation, Inc.
+// Copyright (C) 2014-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc
index 3221f2df90d..0bae706c9a3 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc
@@ -2,7 +2,7 @@
// { dg-do run { target c++11 } }
// { dg-require-filesystem-ts "" }
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+// Copyright (C) 2020-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
index bfb86885457..265fd6ffafe 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
@@ -1,7 +1,7 @@
// { dg-do run { target c++14 } }
// { dg-options "-g -O0" }
-// Copyright (C) 2014-2025 Free Software Foundation, Inc.
+// Copyright (C) 2014-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the

View File

@ -0,0 +1,291 @@
libstdc++-v3/python/libstdcxx/v6/__init__.py | 2 +-
libstdc++-v3/python/libstdcxx/v6/printers.py | 119 ++++++++++++++++++++++++---
libstdc++-v3/python/libstdcxx/v6/xmethods.py | 9 +-
3 files changed, 110 insertions(+), 20 deletions(-)
diff --git a/libstdc++-v3/python/libstdcxx/v6/__init__.py b/libstdc++-v3/python/libstdcxx/v6/__init__.py
index 5a8f2de195d..c46c92739bb 100644
--- a/libstdc++-v3/python/libstdcxx/v6/__init__.py
+++ b/libstdc++-v3/python/libstdcxx/v6/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2014-2025 Free Software Foundation, Inc.
+# Copyright (C) 2014-2026 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
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 052a99a28ed..be7e7a25606 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1,6 +1,6 @@
# Pretty-printers for libstdc++.
-# Copyright (C) 2008-2025 Free Software Foundation, Inc.
+# Copyright (C) 2008-2026 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
@@ -291,7 +291,17 @@ class SharedPointerPrinter(printer_base):
def _get_refcounts(self):
if self._typename == 'std::atomic':
# A tagged pointer is stored as uintptr_t.
- ptr_val = self._val['_M_refcount']['_M_val']['_M_i']
+ val = self._val['_M_refcount']['_M_val']
+ # GCC 16 stores it directly as uintptr_t
+ # GCC 12-15 stores std::atomic<uintptr_t>
+ if hasattr(val.type, 'is_scalar'): # Added in GDB 12.1
+ val_is_uintptr = val.type.is_scalar
+ else:
+ val_is_uintptr = val.type.tag is None
+ if val_is_uintptr:
+ ptr_val = val
+ else:
+ ptr_val = val['_M_i']
ptr_val = ptr_val - (ptr_val % 2) # clear lock bit
ptr_type = find_type(self._val['_M_refcount'].type, 'pointer')
return ptr_val.cast(ptr_type)
@@ -572,7 +582,10 @@ class StdVectorPrinter(printer_base):
self._val['_M_impl']['_M_finish'],
self._is_bool)
- def to_string(self):
+ # Helper to compute the bounds of the vector.
+ # Returns a tuple: (length, capacity, suffix)
+ # SUFFIX is a type-name suffix to print.
+ def _bounds(self):
start = self._val['_M_impl']['_M_start']
finish = self._val['_M_impl']['_M_finish']
end = self._val['_M_impl']['_M_end_of_storage']
@@ -582,13 +595,27 @@ class StdVectorPrinter(printer_base):
fo = self._val['_M_impl']['_M_finish']['_M_offset']
itype = start.dereference().type
bl = 8 * itype.sizeof
- length = bl * (finish - start) + fo
- capacity = bl * (end - start)
- return ('%s<bool> of length %d, capacity %d'
- % (self._typename, int(length), int(capacity)))
+ length = int(bl * (finish - start) + fo)
+ capacity = int(bl * (end - start))
+ suffix = '<bool>'
else:
- return ('%s of length %d, capacity %d'
- % (self._typename, int(finish - start), int(end - start)))
+ length = int(finish - start)
+ capacity = int(end - start)
+ suffix = ''
+ if length < 0:
+ # Probably uninitialized.
+ length = 0
+ capacity = 0
+ return (length, capacity, suffix)
+
+ def to_string(self):
+ (length, capacity, suffix) = self._bounds()
+ return ('%s%s of length %d, capacity %d'
+ % (self._typename, suffix, length, capacity))
+
+ def num_children(self):
+ (length, capacity, suffix) = self._bounds()
+ return length
def display_hint(self):
return 'array'
@@ -733,6 +760,11 @@ class StdStackOrQueuePrinter(printer_base):
return '%s wrapping: %s' % (self._typename,
self._visualizer.to_string())
+ def num_children(self):
+ if hasattr(self._visualizer, 'num_children'):
+ return self._visualizer.num_children()
+ return None
+
def display_hint(self):
if hasattr(self._visualizer, 'display_hint'):
return self._visualizer.display_hint()
@@ -876,6 +908,9 @@ class StdMapPrinter(printer_base):
node = lookup_node_type('_Rb_tree_node', self._val.type).pointer()
return self._iter(RbtreeIterator(self._val), node)
+ def num_children(slf):
+ return len(RbtreeIterator(self._val))
+
def display_hint(self):
return 'map'
@@ -915,6 +950,8 @@ class StdSetPrinter(printer_base):
node = lookup_node_type('_Rb_tree_node', self._val.type).pointer()
return self._iter(RbtreeIterator(self._val), node)
+ def num_children(slf):
+ return len(RbtreeIterator(self._val))
class StdBitsetPrinter(printer_base):
"""Print a std::bitset."""
@@ -1006,7 +1043,8 @@ class StdDequePrinter(printer_base):
else:
self._buffer_size = 1
- def to_string(self):
+ # Helper to compute the size.
+ def _size(self):
start = self._val['_M_impl']['_M_start']
end = self._val['_M_impl']['_M_finish']
@@ -1014,9 +1052,11 @@ class StdDequePrinter(printer_base):
delta_s = start['_M_last'] - start['_M_cur']
delta_e = end['_M_cur'] - end['_M_first']
- size = self._buffer_size * delta_n + delta_s + delta_e
+ return long(self._buffer_size * delta_n + delta_s + delta_e)
- return '%s with %s' % (self._typename, num_elements(long(size)))
+ def to_string(self):
+ size = self._size()
+ return '%s with %s' % (self._typename, num_elements(size))
def children(self):
start = self._val['_M_impl']['_M_start']
@@ -1024,6 +1064,9 @@ class StdDequePrinter(printer_base):
return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'],
end['_M_cur'], self._buffer_size)
+ def num_children(self):
+ return self._size()
+
def display_hint(self):
return 'array'
@@ -1210,6 +1253,9 @@ class Tr1UnorderedSetPrinter(printer_base):
return izip(counter, Tr1HashtableIterator(self._hashtable()))
return izip(counter, StdHashtableIterator(self._hashtable()))
+ def num_children(self):
+ return int(self._hashtable()['_M_element_count'])
+
class Tr1UnorderedMapPrinter(printer_base):
"""Print a std::unordered_map or tr1::unordered_map."""
@@ -1254,6 +1300,9 @@ class Tr1UnorderedMapPrinter(printer_base):
# Zip the two iterators together.
return izip(counter, data)
+ def num_children(self):
+ return int(self._hashtable()['_M_element_count'])
+
def display_hint(self):
return 'map'
@@ -1753,7 +1802,11 @@ class StdCmpCatPrinter(printer_base):
if self._typename == 'strong_ordering' and self._val == 0:
name = 'equal'
else:
- names = {2: 'unordered', -1: 'less', 0: 'equivalent', 1: 'greater'}
+ names = {
+ -1: 'less', 0: 'equivalent', 1: 'greater',
+ # GCC 10-15 used 2 for unordered
+ -128: 'unordered', 2: 'unordered'
+ }
name = names[int(self._val)]
return 'std::{}::{}'.format(self._typename, name)
@@ -1945,6 +1998,9 @@ class StdSpanPrinter(printer_base):
def children(self):
return self._iterator(self._val['_M_ptr'], self._size)
+ def num_children(self):
+ return int(self._size)
+
def display_hint(self):
return 'array'
@@ -2353,6 +2409,37 @@ class StdTextEncodingPrinter(printer_base):
return 'unknown'
return rep['_M_name']
+class StdStacktraceEntryPrinter(printer_base):
+ """Print a std::stacktrace_entry."""
+
+ def __init__(self, typename, val):
+ self._val = val
+ self._typename = typename
+
+ def to_string(self):
+ block = gdb.current_progspace().block_for_pc(self._val['_M_pc'])
+ if block is None or block.function is None:
+ return "<unknown>"
+ sym = block.function
+ return "{{{} at {}:{}}}".format(sym.print_name, sym.symtab.filename, sym.line)
+
+class StdStacktracePrinter(printer_base):
+ """Print a std::stacktrace."""
+
+ def __init__(self, typename, val):
+ self._val = val
+ self._typename = typename
+ self._size = self._val['_M_impl']['_M_size']
+
+ def to_string(self):
+ return '%s of length %d' % (self._typename, self._size)
+
+ def children(self):
+ return StdSpanPrinter._iterator(self._val['_M_impl']['_M_frames'], self._size)
+
+ def display_hint(self):
+ return 'array'
+
# A "regular expression" printer which conforms to the
# "SubPrettyPrinter" protocol from gdb.printing.
class RxPrinter(object):
@@ -2973,6 +3060,12 @@ def build_libstdcxx_dictionary():
# libstdcxx_printer.add_version('std::chrono::(anonymous namespace)', 'Rule',
# StdChronoTimeZoneRulePrinter)
+ # C++23 components
+ libstdcxx_printer.add_version('std::', 'stacktrace_entry',
+ StdStacktraceEntryPrinter)
+ libstdcxx_printer.add_version('std::', 'basic_stacktrace',
+ StdStacktracePrinter)
+
# C++26 components
libstdcxx_printer.add_version('std::', 'text_encoding',
StdTextEncodingPrinter)
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index 109ca10956a..5d1eb375dc3 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -1,6 +1,6 @@
# Xmethods for libstdc++.
-# Copyright (C) 2014-2025 Free Software Foundation, Inc.
+# Copyright (C) 2014-2026 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
@@ -28,8 +28,6 @@ def get_bool_type():
def get_std_size_type():
return gdb.lookup_type('std::size_t')
-_versioned_namespace = '__8::'
-
def is_specialization_of(x, template_name):
"""
Test whether a type is a specialization of the named class template.
@@ -39,8 +37,7 @@ def is_specialization_of(x, template_name):
"""
if isinstance(x, gdb.Type):
x = x.tag
- template_name = '(%s)?%s' % (_versioned_namespace, template_name)
- return re.match(r'^std::(__\d::)?%s<.*>$' % template_name, x) is not None
+ return re.match(r'^std::(__\d::|__debug::)?%s<.*>$' % template_name, x) is not None
class LibStdCxxXMethod(gdb.xmethod.XMethod):
def __init__(self, name, worker_class):
@@ -445,7 +442,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
if method is None or not method.enabled:
return None
val_type = class_type.template_argument(0)
- node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
+ node_type = gdb.lookup_type(str(class_type) + '::_Node_ptr')
return method.worker_class(val_type, node_type)
# Xmethods for std::vector