aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2022-04-27 14:29:34 +0100
committerJonathan Wakely <jwakely@redhat.com>2022-04-27 15:48:32 +0100
commita849584587c317e47f7581df2181efabb948d08f (patch)
tree25e717b9a3eecc1afebb29cbe0aee70ee9967a54 /libstdc++-v3
parente07ea03fce26197d31a9654f4ba217e842049d65 (diff)
downloadgcc-a849584587c317e47f7581df2181efabb948d08f.zip
gcc-a849584587c317e47f7581df2181efabb948d08f.tar.gz
gcc-a849584587c317e47f7581df2181efabb948d08f.tar.bz2
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<shared_ptr<T>> and atomic<weak_ptr<T>>. (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.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py53
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc10
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc9
3 files changed, 69 insertions, 3 deletions
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<shared_ptr>, or atomic<weak_ptr>"
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<N, T> 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 <iostream>
#include <future>
#include <initializer_list>
+#include <atomic>
#include "../util/testsuite_allocator.h" // NullablePointer
typedef std::tuple<int, int> ExTuple;
@@ -197,6 +198,15 @@ main()
std::initializer_list<int> il = {3, 4};
// { dg-final { note-test il {std::initializer_list of length 2 = {3, 4}} } }
+ std::atomic<int> ai{100};
+ // { dg-final { note-test ai {std::atomic<int> = { 100 }} } }
+ long l{};
+ std::atomic<long*> ap{&l};
+ // { dg-final { regexp-test ap {std::atomic.long \*. = { 0x.* }} } }
+ struct Value { int i, j; };
+ std::atomic<Value> av{{8, 9}};
+ // { dg-final { note-test av {std::atomic<Value> = { {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 <array>
#include <compare>
#include <iostream>
+#include <memory>
#include <span>
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<std::shared_ptr<int>> spe;
+// { dg-final { note-test spe {std::atomic<std::shared_ptr<int>> (empty) = {get() = 0x0}} } }
+ std::atomic<std::shared_ptr<int>> sp1 = std::make_shared<int>(1);
+ std::atomic<std::shared_ptr<int>> sp2 = sp1.load();
+ std::atomic<std::weak_ptr<int>> 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
}