https://gcc.gnu.org/g:2e4e58bb43c5769827cd7c6dde46dd1060740e55

commit r16-7321-g2e4e58bb43c5769827cd7c6dde46dd1060740e55
Author: Jonathan Wakely <[email protected]>
Date:   Wed Feb 4 22:57:34 2026 +0000

    libstdc++: Fix std::shared_ptr pretty printer for GDB 11
    
    This pretty printer was updated for GCC 16 to match a change to
    std::atomic<shared_ptr<T>>.  But the gdb.Type.is_scalar property was
    added in GDB 12.1, so we get an error for older GDB versions.
    
    This adds a workaround for older GDB versions. The gdb.Type.tag property
    is None for scalar types, and should always be defined for the
    std::atomic class template. Another option would be to use the
    is_specialization_of function defined in printers.py, but just checking
    for the tag is simpler.
    
    libstdc++-v3/ChangeLog:
    
            * python/libstdcxx/v6/printers.py (SharedPointerPrinter): Only
            use gdb.Type.is_scalar if supported.
            * testsuite/libstdc++-prettyprinters/compat.cc: Test printer for
            old implementation of std::atomic<std::shared_ptr<T>>.
    
    Reviewed-by: Tomasz KamiƄski <[email protected]>

Diff:
---
 libstdc++-v3/python/libstdcxx/v6/printers.py       | 10 +++++--
 .../testsuite/libstdc++-prettyprinters/compat.cc   | 34 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py 
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 8bb7dd2ad600..be7e7a256065 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -292,9 +292,15 @@ class SharedPointerPrinter(printer_base):
         if self._typename == 'std::atomic':
             # A tagged pointer is stored as uintptr_t.
             val = self._val['_M_refcount']['_M_val']
-            if val.type.is_scalar: # GCC 16 stores uintptr_t
+            # 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: # GCC 12-15 stores std::atomic<uintptr_t>
+            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')
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
index 142ddb09e610..35ec5cf23981 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
@@ -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
 }

Reply via email to