public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Add pretty printer for std::atomic
@ 2022-04-27 14:53 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2022-04-27 14:53 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested x86_64-linux, pushed to trunk.

-- >8 --

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.
---
 libstdc++-v3/python/libstdcxx/v6/printers.py  | 53 +++++++++++++++++--
 .../libstdc++-prettyprinters/cxx11.cc         | 10 ++++
 .../libstdc++-prettyprinters/cxx20.cc         |  9 ++++
 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 c31134bcdd2..0bd793c0897 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 621d13bd062..f97640a0189 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 76023df93fa..f027d0eae38 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
 }
-- 
2.34.1


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-04-27 14:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 14:53 [committed] libstdc++: Add pretty printer for std::atomic Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).