From a849584587c317e47f7581df2181efabb948d08f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 27 Apr 2022 14:29:34 +0100 Subject: libstdc++: Add pretty printer for std::atomic For the atomic specializations for shared_ptr and weak_ptr we can reuse the existing SharedPointerPrinter, with a small tweak. libstdc++-v3/ChangeLog: * python/libstdcxx/v6/printers.py (SharedPointerPrinter): Add support for atomic> and atomic>. (StdAtomicPrinter): New printer. (build_libstdcxx_dictionary): Register new printer. * testsuite/libstdc++-prettyprinters/cxx11.cc: Test std::atomic. * testsuite/libstdc++-prettyprinters/cxx20.cc: Test atomic smart pointers. --- libstdc++-v3/python/libstdcxx/v6/printers.py | 53 ++++++++++++++++++++-- .../testsuite/libstdc++-prettyprinters/cxx11.cc | 10 ++++ .../testsuite/libstdc++-prettyprinters/cxx20.cc | 9 ++++ 3 files changed, 69 insertions(+), 3 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index c31134b..0bd793c 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -218,7 +218,7 @@ class SmartPtrIterator(Iterator): return ('get()', val) class SharedPointerPrinter: - "Print a shared_ptr or weak_ptr" + "Print a shared_ptr, weak_ptr, atomic, or atomic" def __init__ (self, typename, val): self.typename = strip_versioned_namespace(typename) @@ -228,9 +228,21 @@ class SharedPointerPrinter: def children (self): return SmartPtrIterator(self.pointer) + # Return the _Sp_counted_base<>* that holds the refcounts. + 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'] + 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) + return self.val['_M_refcount']['_M_pi'] + def to_string (self): state = 'empty' - refcounts = self.val['_M_refcount']['_M_pi'] + refcounts = self._get_refcounts() + targ = self.val.type.template_argument(0) + if refcounts != 0: usecount = refcounts['_M_use_count'] weakcount = refcounts['_M_weak_count'] @@ -238,7 +250,7 @@ class SharedPointerPrinter: state = 'expired, weak count %d' % weakcount else: state = 'use count %d, weak count %d' % (usecount, weakcount - 1) - return '%s<%s> (%s)' % (self.typename, str(self.val.type.template_argument(0)), state) + return '%s<%s> (%s)' % (self.typename, str(targ), state) def _tuple_impl_get(val): "Return the tuple element stored in a _Tuple_impl base class." @@ -1708,6 +1720,40 @@ class StdInitializerListPrinter: def display_hint(self): return 'array' +class StdAtomicPrinter: + "Print a std:atomic" + + def __init__(self, typename, val): + self.typename = typename + self.val = val + self.shptr_printer = None + self.value_type = self.val.type.template_argument(0) + if self.value_type.tag is not None: + typ = strip_versioned_namespace(self.value_type.tag) + if typ.startswith('std::shared_ptr<') or typ.startswith('std::weak_ptr<'): + impl = val['_M_impl'] + self.shptr_printer = SharedPointerPrinter(typename, impl) + self.children = self._shptr_children + + def _shptr_children(self): + return SmartPtrIterator(self.shptr_printer.pointer) + + def to_string(self): + if self.shptr_printer is not None: + return self.shptr_printer.to_string() + + if self.value_type.code == gdb.TYPE_CODE_INT: + val = self.val['_M_i'] + elif self.value_type.code == gdb.TYPE_CODE_FLT: + val = self.val['_M_fp'] + elif self.value_type.code == gdb.TYPE_CODE_PTR: + val = self.val['_M_b']['_M_p'] + elif self.value_type.code == gdb.TYPE_CODE_BOOL: + val = self.val['_M_base']['_M_i'] + else: + val = self.val['_M_i'] + return '%s<%s> = { %s }' % (self.typename, str(self.value_type), val) + # A "regular expression" printer which conforms to the # "SubPrettyPrinter" protocol from gdb.printing. class RxPrinter(object): @@ -2175,6 +2221,7 @@ def build_libstdcxx_dictionary (): libstdcxx_printer.add_version('std::', 'initializer_list', StdInitializerListPrinter) + libstdcxx_printer.add_version('std::', 'atomic', StdAtomicPrinter) # std::regex components libstdcxx_printer.add_version('std::__detail::', '_State', diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc index 621d13b..f97640a 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "../util/testsuite_allocator.h" // NullablePointer typedef std::tuple ExTuple; @@ -197,6 +198,15 @@ main() std::initializer_list il = {3, 4}; // { dg-final { note-test il {std::initializer_list of length 2 = {3, 4}} } } + std::atomic ai{100}; + // { dg-final { note-test ai {std::atomic = { 100 }} } } + long l{}; + std::atomic ap{&l}; + // { dg-final { regexp-test ap {std::atomic.long \*. = { 0x.* }} } } + struct Value { int i, j; }; + std::atomic av{{8, 9}}; + // { dg-final { note-test av {std::atomic = { {i = 8, j = 9} }} } } + placeholder(""); // Mark SPOT use(efl); use(fl); diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc index 76023df..f027d0e 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include struct X @@ -65,6 +66,14 @@ main() static_assert(s2.extent == std::size_t(2)); // { dg-final { note-test s2 {std::span of length 2 = {3, 4}} } } + std::atomic> spe; +// { dg-final { note-test spe {std::atomic> (empty) = {get() = 0x0}} } } + std::atomic> sp1 = std::make_shared(1); + std::atomic> sp2 = sp1.load(); + std::atomic> wp{sp2.load()}; +// { dg-final { regexp-test sp1 {std::atomic.std::shared_ptr.int.. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } } +// { dg-final { regexp-test wp {std::atomic.std::weak_ptr.int.. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } } + std::cout << "\n"; return 0; // Mark SPOT } -- cgit v1.1