public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-8286] 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: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:a849584587c317e47f7581df2181efabb948d08f

commit r12-8286-ga849584587c317e47f7581df2181efabb948d08f
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Apr 27 14:29:34 2022 +0100

    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.

Diff:
---
 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(-)

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
 }


^ 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 [gcc r12-8286] 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).