https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/174218

>From 686be087caaa3433b46278113f965c1f8bf3b51f Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Wed, 19 Nov 2025 18:14:43 +0000
Subject: [PATCH 1/4] [lldb] update the representation

This patch adds a new synthetic child provider and a summary formatter
for the libstdc++ implementation of std::atomic<>.

[lldb] add test cases

[lldb] add review changes

# Conflicts:
#       lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
#       lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
---
 .../Plugins/Language/CPlusPlus/CMakeLists.txt |   1 +
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  |  31 ++++-
 .../Plugins/Language/CPlusPlus/LibStdcpp.h    |   7 +
 .../Language/CPlusPlus/LibStdcppAtomic.cpp    | 124 ++++++++++++++++++
 .../atomic/TestDataFormatterStdAtomic.py      |  48 +++++++
 .../generic/atomic/main.cpp                   |  13 ++
 6 files changed, 217 insertions(+), 7 deletions(-)
 create mode 100644 lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp

diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt 
b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 79c0cc14ec644..ca1387ea94117 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -31,6 +31,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
   LibCxxValarray.cpp
   LibCxxVector.cpp
   LibStdcpp.cpp
+  LibStdcppAtomic.cpp
   LibStdcppSpan.cpp
   LibStdcppTuple.cpp
   LibStdcppUniquePointer.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index bdc67a004b06c..c685707e2fc4f 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1525,6 +1525,24 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       eTypeOptionHideChildren | eTypeOptionHideValue, false);
 }
 
+static lldb_private::SyntheticChildrenFrontEnd *
+GenericAtomicSyntheticFrontEndCreator(CXXSyntheticChildren *children,
+                                      const lldb::ValueObjectSP &valobj_sp) {
+  if (!valobj_sp)
+    return nullptr;
+
+  if (IsMsvcStlAtomic(*valobj_sp))
+    return MsvcStlAtomicSyntheticFrontEndCreator(children, valobj_sp);
+  return LibStdcppAtomicSyntheticFrontEndCreator(children, valobj_sp);
+}
+
+static bool GenericAtomicSummaryProvider(ValueObject &valobj, Stream &stream,
+                                         const TypeSummaryOptions &options) {
+  if (IsMsvcStlAtomic(valobj))
+    return MsvcStlAtomicSummaryProvider(valobj, stream, options);
+  return LibStdcppAtomicSummaryProvider(valobj, stream, options);
+}
+
 static lldb_private::SyntheticChildrenFrontEnd *
 GenericSmartPointerSyntheticFrontEndCreator(CXXSyntheticChildren *children,
                                             lldb::ValueObjectSP valobj_sp) {
@@ -1797,6 +1815,9 @@ static void 
LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
           },
           "MSVC STL/libstdc++ std::wstring_view summary provider"));
 
+  AddCXXSynthetic(cpp_category_sp, GenericAtomicSyntheticFrontEndCreator,
+                  "std::atomic synthetic children", "^std::atomic<.+>$",
+                  stl_synth_flags, true);
   // NOTE: it is loaded as a common formatter because the libc++ version is not
   // in the `__1` namespace, hence we need to dispatch based on the class
   // layout.
@@ -1854,6 +1875,9 @@ static void 
LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
                 "std::initializer_list summary provider",
                 "^std::initializer_list<.+>$", stl_summary_flags, true);
+  AddCXXSummary(cpp_category_sp, GenericAtomicSummaryProvider,
+                "std::atomic summary provider", "^std::atomic<.+>$",
+                stl_summary_flags, true);
   AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider,
                 "MSVC STL/libstdc++ std::shared_ptr summary provider",
                 "^std::shared_ptr<.+>(( )?&)?$", stl_summary_flags, true);
@@ -1941,13 +1965,6 @@ static void 
LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
 
   stl_summary_flags.SetDontShowChildren(false);
 
-  AddCXXSynthetic(cpp_category_sp, MsvcStlAtomicSyntheticFrontEndCreator,
-                  "MSVC STL std::atomic synthetic children",
-                  "^std::atomic<.+>$", stl_synth_flags, true);
-
-  AddCXXSummary(cpp_category_sp, MsvcStlAtomicSummaryProvider,
-                "MSVC STL std::atomic summary provider", "^std::atomic<.+>$",
-                stl_summary_flags, true);
   AddCXXSynthetic(cpp_category_sp, MsvcStlTreeIterSyntheticFrontEndCreator,
                   "MSVC STL tree iterator synthetic children",
                   "^std::_Tree(_const)?_iterator<.+>(( )?&)?$", 
stl_synth_flags,
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
index bc67885787bc2..f3b2408589e46 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -44,6 +44,9 @@ bool LibStdcppVariantSummaryProvider(
     ValueObject &valobj, Stream &stream,
     const TypeSummaryOptions &options); // libstdc++ std::variant<>
 
+bool LibStdcppAtomicSummaryProvider(ValueObject &valobj, Stream &stream,
+                                    const TypeSummaryOptions &options);
+
 bool LibStdcppPartialOrderingSummaryProvider(
     ValueObject &valobj, Stream &stream,
     const TypeSummaryOptions &options); // libstdc++ std::partial_ordering
@@ -56,6 +59,10 @@ bool LibStdcppStrongOrderingSummaryProvider(
     ValueObject &valobj, Stream &stream,
     const TypeSummaryOptions &options); // libstdc++ std::strong_ordering
 
+SyntheticChildrenFrontEnd *
+LibStdcppAtomicSyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                        const lldb::ValueObjectSP &);
+
 SyntheticChildrenFrontEnd *
 LibstdcppMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                              lldb::ValueObjectSP);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
new file mode 100644
index 0000000000000..d2e6b82ffb8b9
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
@@ -0,0 +1,124 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibStdcpp.h"
+
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/Support/Error.h"
+
+using namespace lldb;
+
+namespace lldb_private::formatters {
+
+class LibStdcppAtomicSyntheticFrontEnd final
+    : public SyntheticChildrenFrontEnd {
+public:
+  explicit LibStdcppAtomicSyntheticFrontEnd(ValueObject &valobj_sp)
+      : SyntheticChildrenFrontEnd(valobj_sp),
+        m_inner_name(ConstString("Value")) {}
+
+  llvm::Expected<uint32_t> CalculateNumChildren() final {
+    if (!m_inner)
+      return llvm::createStringError("invalide atomic ValueObject");
+    return 1;
+  }
+
+  ValueObjectSP GetChildAtIndex(uint32_t idx) final {
+    if (idx == 0 && m_inner)
+      return m_inner->GetSP()->Clone(m_inner_name);
+
+    return {};
+  }
+
+  lldb::ChildCacheState Update() final {
+    if (ValueObjectSP value = ContainerFieldName(m_backend)) {
+      // show the Type, instead of std::__atomic_base<Type>::__Type_type.
+      value = value->Cast(value->GetCompilerType().GetCanonicalType());
+      m_inner = value.get();
+    }
+
+    return lldb::ChildCacheState::eRefetch;
+  }
+
+  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) final {
+    if (name == m_inner_name)
+      return 0;
+
+    return llvm::createStringError("Type has no child named '%s'",
+                                   name.AsCString());
+  }
+
+  static ValueObjectSP ContainerFieldName(ValueObject &backend_syn) {
+    const ValueObjectSP non_synthetic = backend_syn.GetNonSyntheticValue();
+    if (!non_synthetic)
+      return {};
+    ValueObject &backend = *non_synthetic;
+
+    const CompilerType type = backend.GetCompilerType();
+    if (!type.IsValid() || type.GetNumTemplateArguments() < 1)
+      return {};
+
+    const CompilerType first_type = type.GetTypeTemplateArgument(0);
+    const lldb::BasicType basic_type = first_type.GetBasicTypeEnumeration();
+    if (basic_type == eBasicTypeBool)
+      return backend.GetChildAtNamePath({"_M_base", "_M_i"});
+
+    const uint32_t float_mask = lldb::eTypeIsFloat | lldb::eTypeIsBuiltIn;
+    if (first_type.GetTypeInfo() & float_mask) {
+      // added float types specialization in c++17
+      if (const auto child = backend.GetChildMemberWithName("_M_fp"))
+        return child;
+
+      return backend.GetChildMemberWithName("_M_i");
+    }
+
+    if (first_type.IsPointerType())
+      return backend.GetChildAtNamePath({"_M_b", "_M_p"});
+
+    return backend.GetChildMemberWithName("_M_i");
+  }
+
+private:
+  ConstString m_inner_name;
+  ValueObject *m_inner = nullptr;
+};
+
+SyntheticChildrenFrontEnd *
+LibStdcppAtomicSyntheticFrontEndCreator(CXXSyntheticChildren * /*unused*/,
+                                        const lldb::ValueObjectSP &valobj_sp) {
+  if (!valobj_sp)
+    return nullptr;
+
+  const lldb::ValueObjectSP member =
+      LibStdcppAtomicSyntheticFrontEnd::ContainerFieldName(*valobj_sp);
+  if (!member)
+    return nullptr;
+
+  return new LibStdcppAtomicSyntheticFrontEnd(*valobj_sp);
+}
+
+bool LibStdcppAtomicSummaryProvider(ValueObject &valobj, Stream &stream,
+                                    const TypeSummaryOptions &options) {
+
+  if (const ValueObjectSP atomic_value =
+          LibStdcppAtomicSyntheticFrontEnd::ContainerFieldName(valobj)) {
+    std::string summary;
+    if (atomic_value->GetSummaryAsCString(summary, options) &&
+        !summary.empty()) {
+      stream << summary;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+} // namespace lldb_private::formatters
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
index 67c2c359c9afb..ddad85b095362 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
@@ -56,6 +56,35 @@ def do_test(self):
         self.assertEqual(s.GetChildAtIndex(0).GetValueAsUnsigned(0), 1, "s.x 
== 1")
         self.assertEqual(s.GetChildAtIndex(1).GetValueAsUnsigned(0), 2, "s.y 
== 2")
 
+        # float
+        atomic_float = self.get_variable("atomic_float")
+        val_float = atomic_float.child[0]
+        self.assertIsNotNone(val_float, msg="atomic_float child is None.")
+        self.assertAlmostEqual(float(val_float.value), 3.14, places=2)
+        # double
+        atomic_double = self.get_variable("atomic_double")
+        val_float = atomic_double.child[0]
+        self.assertIsNotNone(val_float, msg="atomic_double child is None.")
+        self.assertAlmostEqual(float(val_float.value), 6.28, places=2)
+
+        # bool
+        atomic_bool = self.get_variable("atomic_bool")
+        val_bool = atomic_bool.child[0]
+        self.assertIsNotNone(val_bool, msg="atomic_bool child is None.")
+        self.assertEqual(bool(val_bool.unsigned), True)
+
+        # func
+        atomic_func = self.get_variable("atomic_func")
+        val_func = atomic_func.child[0]
+        self.assertIsNotNone(val_func, msg="atomic_func child is None.")
+        self.assertNotEqual(val_func.unsigned, 0)
+
+        # pointer
+        atomic_pointer = self.get_variable("atomic_pointer")
+        val_pointer = atomic_pointer.child[0]
+        self.assertIsNotNone(val_pointer, msg="atomic_pointer child is None.")
+        self.assertNotEqual(val_pointer.unsigned, 0)
+
         # Try printing the child that points to its own parent object.
         # This should just treat the atomic pointer as a normal pointer.
         self.expect("frame var p.child", substrs=["Value = 0x"])
@@ -64,12 +93,31 @@ def do_test(self):
             "frame var p.child.parent", substrs=["p.child.parent = {\n  Value 
= 0x"]
         )
 
+    def verify_floating_point_equal(self, value: str, expected: float):
+        self.assertAlmostEqual(float(value), float(expected), places=4)
+
     @skipIf(compiler=["gcc"])
     @add_test_categories(["libc++"])
     def test_libcxx(self):
         self.build(dictionary={"USE_LIBCPP": 1})
         self.do_test()
 
+    @add_test_categories(["libstdcxx"])
+    def test_libstdcxx(self):
+        self.build(dictionary={"USE_LIBSTDCPP": 1})
+        self.do_test()
+
+    # the data layout is different in new libstdc++ versions
+    @add_test_categories(["libstdcxx"])
+    def test_libstdcxx_11(self):
+        self.build(dictionary={"USE_LIBSTDCPP": 1, "CXXFLAGS_EXTRAS": 
"-std=c++11"})
+        self.do_test()
+
+    @add_test_categories(["libstdcxx"])
+    def test_libstdcxx_17(self):
+        self.build(dictionary={"USE_LIBSTDCPP": 1, "CXXFLAGS_EXTRAS": 
"-std=c++17"})
+        self.do_test()
+
     @add_test_categories(["msvcstl"])
     def test_msvcstl(self):
         # No flags, because the "msvcstl" category checks that the MSVC STL is 
used by default.
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
index ee77a880a0c5d..01d5db0a8d8c9 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
@@ -17,6 +17,9 @@ struct S {
   int y = 2;
 };
 
+static void func() {}
+using func_t = void (*)();
+
 int main() {
   std::atomic<S> s;
   s.store(S());
@@ -27,5 +30,15 @@ int main() {
   // Let the child node know what its parent is.
   p.child.parent = &p;
 
+  // libstdcpp has different layout depending on the data structure
+  std::atomic<bool> atomic_bool{true};
+  std::atomic<float> atomic_float{3.14};
+  std::atomic<double> atomic_double{6.28};
+
+  std::atomic<func_t> atomic_func(func);
+
+  S data;
+  std::atomic<S *> atomic_pointer{&data};
+
   return 0; // Set break point at this line.
 }

>From 4fc23c17e9c54876490c5bc4467e5c5872819c52 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Thu, 22 Jan 2026 23:01:37 +0000
Subject: [PATCH 2/4] add review changes and shared pointer version

---
 .../Plugins/Language/CPlusPlus/LibStdcpp.cpp  | 53 ++++++++++++++++---
 .../Plugins/Language/CPlusPlus/LibStdcpp.h    |  6 +--
 .../Language/CPlusPlus/LibStdcppAtomic.cpp    | 16 +++++-
 .../atomic/TestDataFormatterStdAtomic.py      | 22 +++++++-
 .../generic/atomic/main.cpp                   | 12 +++++
 5 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index c06f50c1ca65d..c54c24cf5c5dc 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -403,9 +403,49 @@ 
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
   return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp)
                     : nullptr);
 }
+static ValueObjectSP GetReferenceCountPointer(ValueObject &parent,
+                                              bool is_atomic_child) {
+  auto refcount = parent.GetChildMemberWithName("_M_refcount");
+  if (!refcount)
+    return nullptr;
+
+  if (!is_atomic_child)
+    return refcount->GetChildMemberWithName("_M_pi");
+
+  auto val = refcount->GetChildMemberWithName("_M_val");
+  if (!val || !val->GetCompilerType())
+    return nullptr;
+
+  // May be a scalar value depending on libstdc++ version
+  if (!val->GetCompilerType().IsScalarType()) {
+    val = val->GetChildMemberWithName("_M_i");
+    if (!val)
+      return nullptr;
+  }
+
+  // Extract and align the raw value
+  bool is_success = false;
+  uint64_t raw_val = val->GetValueAsUnsigned(0, &is_success);
+  if (!is_success || raw_val == 0)
+    return nullptr;
+  // Clear the least significant bit. See
+  // 
https://github.com/gcc-mirror/gcc/blob/releases/gcc-15.2.0/libstdc%2B%2B-v3/include/bits/shared_ptr_atomic.h#L465
+  raw_val &= ~1ULL;
+
+  // Get the pointer type
+  auto ref_count_ptr =
+      refcount->GetCompilerType().GetDirectNestedTypeWithName("pointer");
+  if (!ref_count_ptr)
+    return nullptr;
+
+  return ValueObject::CreateValueObjectFromAddress(
+      "", raw_val, parent.GetExecutionContextRef(), ref_count_ptr,
+      /*do_deref=*/false);
+}
 
 bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
-    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options,
+    bool is_atomic_child) {
   ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
   if (!valobj_sp)
     return false;
@@ -416,11 +456,10 @@ bool 
lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
 
   DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
 
-  ValueObjectSP pi_sp = valobj_sp->GetChildAtNamePath({"_M_refcount", 
"_M_pi"});
+  auto pi_sp = GetReferenceCountPointer(*valobj_sp, is_atomic_child);
   if (!pi_sp)
     return false;
-
-  bool success;
+  bool success = false;
   uint64_t pi_addr = pi_sp->GetValueAsUnsigned(0, &success);
   // Empty control field. We're done.
   if (!success || pi_addr == 0)
@@ -428,7 +467,7 @@ bool 
lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
 
   int64_t shared_count = 0;
   if (auto count_sp = pi_sp->GetChildMemberWithName("_M_use_count")) {
-    bool success;
+    bool success = false;
     shared_count = count_sp->GetValueAsSigned(0, &success);
     if (!success)
       return false;
@@ -438,8 +477,8 @@ bool 
lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
 
   // _M_weak_count is the number of weak references + (_M_use_count != 0).
   if (auto weak_count_sp = pi_sp->GetChildMemberWithName("_M_weak_count")) {
-    bool success;
-    int64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);
+    bool success = false;
+    uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);
     if (!success)
       return false;
 
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
index f3b2408589e46..6b538805b2cdb 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -32,9 +32,9 @@ bool LibStdcppWStringViewSummaryProvider(
     const TypeSummaryOptions &options); // libstdc++ std::wstring_view
 
 bool LibStdcppSmartPointerSummaryProvider(
-    ValueObject &valobj, Stream &stream,
-    const TypeSummaryOptions
-        &options); // libstdc++ std::shared_ptr<> and std::weak_ptr<>
+    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options,
+    bool is_atomic_child =
+        false); // libstdc++ std::shared_ptr<> and std::weak_ptr<>
 
 bool LibStdcppUniquePointerSummaryProvider(
     ValueObject &valobj, Stream &stream,
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
index d2e6b82ffb8b9..3e7c03bcaa7b1 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
@@ -63,10 +63,13 @@ class LibStdcppAtomicSyntheticFrontEnd final
     ValueObject &backend = *non_synthetic;
 
     const CompilerType type = backend.GetCompilerType();
-    if (!type.IsValid() || type.GetNumTemplateArguments() < 1)
+    if (!type || type.GetNumTemplateArguments() < 1)
       return {};
 
     const CompilerType first_type = type.GetTypeTemplateArgument(0);
+    if (!first_type)
+      return {};
+
     const lldb::BasicType basic_type = first_type.GetBasicTypeEnumeration();
     if (basic_type == eBasicTypeBool)
       return backend.GetChildAtNamePath({"_M_base", "_M_i"});
@@ -83,6 +86,11 @@ class LibStdcppAtomicSyntheticFrontEnd final
     if (first_type.IsPointerType())
       return backend.GetChildAtNamePath({"_M_b", "_M_p"});
 
+    const auto first_typename = first_type.GetDisplayTypeName().GetStringRef();
+    if (first_typename.starts_with("std::shared_ptr<") ||
+        first_typename.starts_with("std::weak_ptr<"))
+      return backend.GetChildAtNamePath({"_M_impl", "_M_ptr"});
+
     return backend.GetChildMemberWithName("_M_i");
   }
 
@@ -116,6 +124,12 @@ bool LibStdcppAtomicSummaryProvider(ValueObject &valobj, 
Stream &stream,
       stream << summary;
       return true;
     }
+
+    auto aparent = atomic_value->GetParent();
+    if (aparent && aparent->GetName().GetStringRef() == "_M_impl") {
+      return LibStdcppSmartPointerSummaryProvider(*aparent, stream, options,
+                                                  /*is_atomic_child=*/true);
+    }
   }
 
   return false;
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
index ddad85b095362..f10517cb6b8f3 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py
@@ -18,7 +18,7 @@ def get_variable(self, name):
         var.SetPreferSyntheticValue(True)
         return var
 
-    def do_test(self):
+    def do_test(self, test_smart_pointers: bool = False):
         """Test that std::atomic is correctly printed by LLDB"""
         self.runCmd("file " + self.getBuildArtifact("a.out"), 
CURRENT_EXECUTABLE_SET)
 
@@ -73,7 +73,7 @@ def do_test(self):
         self.assertIsNotNone(val_bool, msg="atomic_bool child is None.")
         self.assertEqual(bool(val_bool.unsigned), True)
 
-        # func
+        # function
         atomic_func = self.get_variable("atomic_func")
         val_func = atomic_func.child[0]
         self.assertIsNotNone(val_func, msg="atomic_func child is None.")
@@ -93,6 +93,19 @@ def do_test(self):
             "frame var p.child.parent", substrs=["p.child.parent = {\n  Value 
= 0x"]
         )
 
+        if test_smart_pointers:
+            # shared_pointer
+            atomic_shared = self.get_variable("atomic_shared")
+            val_shared = atomic_shared.child[0]
+            self.assertIsNotNone(val_shared, msg="atomic_shared child is 
None.")
+            self.assertEqual(300, val_shared.deref.unsigned)
+
+            # weak_pointer
+            atomic_weak = self.get_variable("atomic_weak")
+            val_weak = atomic_weak.child[0]
+            self.assertIsNotNone(val_weak, msg="atomic_weak child is None.")
+            self.assertEqual(300, val_weak.deref.unsigned)
+
     def verify_floating_point_equal(self, value: str, expected: float):
         self.assertAlmostEqual(float(value), float(expected), places=4)
 
@@ -118,6 +131,11 @@ def test_libstdcxx_17(self):
         self.build(dictionary={"USE_LIBSTDCPP": 1, "CXXFLAGS_EXTRAS": 
"-std=c++17"})
         self.do_test()
 
+    @add_test_categories(["libstdcxx"])
+    def test_libstdcxx_20(self):
+        self.build(dictionary={"USE_LIBSTDCPP": 1, "CXXFLAGS_EXTRAS": 
"-std=c++20"})
+        self.do_test(test_smart_pointers=True)
+
     @add_test_categories(["msvcstl"])
     def test_msvcstl(self):
         # No flags, because the "msvcstl" category checks that the MSVC STL is 
used by default.
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
index 01d5db0a8d8c9..0b449c5879e45 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/main.cpp
@@ -1,4 +1,9 @@
 #include <atomic>
+#include <version>
+
+#if __cpp_lib_atomic_shared_ptr
+#include <memory>
+#endif // __cpp_lib_atomic_shared_ptr
 
 // Define a Parent and Child struct that can point to each other.
 class Parent;
@@ -40,5 +45,12 @@ int main() {
   S data;
   std::atomic<S *> atomic_pointer{&data};
 
+  // smart atomic shared pointer was added in c++20
+#if __cpp_lib_atomic_shared_ptr
+  std::shared_ptr<int> s_value = std::make_shared<int>(300);
+  std::atomic<std::shared_ptr<int>> atomic_shared{s_value};
+  std::atomic<std::weak_ptr<int>> atomic_weak{s_value};
+#endif // __cpp_lib_atomic_shared_ptr
+
   return 0; // Set break point at this line.
 }

>From 1a51a2944b21209ef17fa127042c2114fe025867 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Tue, 27 Jan 2026 09:31:15 +0000
Subject: [PATCH 3/4] add review changes

---
 .../Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp    | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
index 3e7c03bcaa7b1..8f8f79d7040c9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
@@ -21,13 +21,12 @@ namespace lldb_private::formatters {
 class LibStdcppAtomicSyntheticFrontEnd final
     : public SyntheticChildrenFrontEnd {
 public:
-  explicit LibStdcppAtomicSyntheticFrontEnd(ValueObject &valobj_sp)
-      : SyntheticChildrenFrontEnd(valobj_sp),
-        m_inner_name(ConstString("Value")) {}
+  explicit LibStdcppAtomicSyntheticFrontEnd(ValueObject &valobj)
+      : SyntheticChildrenFrontEnd(valobj), m_inner_name(ConstString("Value")) 
{}
 
   llvm::Expected<uint32_t> CalculateNumChildren() final {
     if (!m_inner)
-      return llvm::createStringError("invalide atomic ValueObject");
+      return llvm::createStringError("Invalid atomic ValueObject.");
     return 1;
   }
 
@@ -75,7 +74,7 @@ class LibStdcppAtomicSyntheticFrontEnd final
       return backend.GetChildAtNamePath({"_M_base", "_M_i"});
 
     const uint32_t float_mask = lldb::eTypeIsFloat | lldb::eTypeIsBuiltIn;
-    if (first_type.GetTypeInfo() & float_mask) {
+    if ((first_type.GetTypeInfo() & float_mask) == float_mask) {
       // added float types specialization in c++17
       if (const auto child = backend.GetChildMemberWithName("_M_fp"))
         return child;
@@ -125,7 +124,7 @@ bool LibStdcppAtomicSummaryProvider(ValueObject &valobj, 
Stream &stream,
       return true;
     }
 
-    auto aparent = atomic_value->GetParent();
+    ValueObject *aparent = atomic_value->GetParent();
     if (aparent && aparent->GetName().GetStringRef() == "_M_impl") {
       return LibStdcppSmartPointerSummaryProvider(*aparent, stream, options,
                                                   /*is_atomic_child=*/true);

>From 905cb37e3ac8485ed6830d88a7faef9b1a0d1f35 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Tue, 27 Jan 2026 11:56:45 +0000
Subject: [PATCH 4/4] add review changes

---
 lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp   |  1 +
 .../Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp     | 10 +++++-----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index c54c24cf5c5dc..028b27d866473 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -403,6 +403,7 @@ 
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
   return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp)
                     : nullptr);
 }
+
 static ValueObjectSP GetReferenceCountPointer(ValueObject &parent,
                                               bool is_atomic_child) {
   auto refcount = parent.GetChildMemberWithName("_M_refcount");
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
index 8f8f79d7040c9..ec274993702ea 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppAtomic.cpp
@@ -22,7 +22,7 @@ class LibStdcppAtomicSyntheticFrontEnd final
     : public SyntheticChildrenFrontEnd {
 public:
   explicit LibStdcppAtomicSyntheticFrontEnd(ValueObject &valobj)
-      : SyntheticChildrenFrontEnd(valobj), m_inner_name(ConstString("Value")) 
{}
+      : SyntheticChildrenFrontEnd(valobj) {}
 
   llvm::Expected<uint32_t> CalculateNumChildren() final {
     if (!m_inner)
@@ -32,7 +32,7 @@ class LibStdcppAtomicSyntheticFrontEnd final
 
   ValueObjectSP GetChildAtIndex(uint32_t idx) final {
     if (idx == 0 && m_inner)
-      return m_inner->GetSP()->Clone(m_inner_name);
+      return m_inner->GetSP()->Clone(k_inner_name);
 
     return {};
   }
@@ -48,7 +48,7 @@ class LibStdcppAtomicSyntheticFrontEnd final
   }
 
   llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) final {
-    if (name == m_inner_name)
+    if (name == k_inner_name)
       return 0;
 
     return llvm::createStringError("Type has no child named '%s'",
@@ -94,7 +94,7 @@ class LibStdcppAtomicSyntheticFrontEnd final
   }
 
 private:
-  ConstString m_inner_name;
+  inline static const ConstString k_inner_name = ConstString("Value");
   ValueObject *m_inner = nullptr;
 };
 
@@ -104,7 +104,7 @@ 
LibStdcppAtomicSyntheticFrontEndCreator(CXXSyntheticChildren * /*unused*/,
   if (!valobj_sp)
     return nullptr;
 
-  const lldb::ValueObjectSP member =
+  const ValueObjectSP member =
       LibStdcppAtomicSyntheticFrontEnd::ContainerFieldName(*valobj_sp);
   if (!member)
     return nullptr;

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to