[lldb] [llvm] [lldb] Add MSVC STL/libstdc++ formatters for queue, stack, and priority_queue (PR #217241)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 03:41:03 PDT 2026
https://github.com/Daedie-git updated https://github.com/llvm/llvm-project/pull/217241
>From 8ccd14da97acec8e51f7014aac1dc18c56a6fef8 Mon Sep 17 00:00:00 2001
From: Bjorn Schobben <bjorn.schobben at aimsport.com>
Date: Wed, 19 Aug 2026 10:52:59 +0200
Subject: [PATCH 1/4] [lldb] Add MSVC STL/libstdc++ formatters for queue,
stack, and priority_queue
These adaptors store the container in a member named `c` in both MSVC
STL and libstdc++. Reuse the existing adaptor frontend and register it
for the un-inlined std:: names. libc++ continues to use the inline
namespace regex.
Part of #24834
---
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 21 ++++++++
.../queue/TestDataFormatterStdQueue.py | 54 ++++++++++++++-----
.../data-formatter-stl/generic/queue/main.cpp | 10 +++-
3 files changed, 69 insertions(+), 16 deletions(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 8225c2141a84a..c28e75745dfca 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1947,6 +1947,27 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"MSVC STL/libstdc++ std::strong_ordering summary provider",
"std::strong_ordering",
eTypeOptionHideChildren | eTypeOptionHideValue, false);
+
+ // Container adaptors store the underlying container in a member named `c`
+ // in both MSVC STL and libstdc++.
+ AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ "std::queue synthetic children", "^std::queue<.+>(( )?&)?$",
+ stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ "std::stack synthetic children", "^std::stack<.+>(( )?&)?$",
+ stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ "std::priority_queue synthetic children",
+ "^std::priority_queue<.+>(( )?&)?$", stl_synth_flags, true);
+ AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
+ "std::queue summary provider", "^std::queue<.+>(( )?&)?$",
+ stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
+ "std::stack summary provider", "^std::stack<.+>(( )?&)?$",
+ stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
+ "std::priority_queue summary provider",
+ "^std::priority_queue<.+>(( )?&)?$", stl_summary_flags, true);
}
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/TestDataFormatterStdQueue.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/TestDataFormatterStdQueue.py
index d5ae06bd057c4..166ed83220d2b 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/TestDataFormatterStdQueue.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/TestDataFormatterStdQueue.py
@@ -15,28 +15,54 @@ def setUp(self):
TestBase.setUp(self)
self.namespace = "std"
- def check_variable(self, name):
+ def check_sequence(self, name, type_name):
var = self.frame().FindVariable(name)
- self.assertTrue(var.IsValid())
-
- queue = self.namespace + "::queue"
- self.assertIn(queue, var.GetDisplayTypeName())
- self.assertEqual(var.GetNumChildren(), 5)
+ self.assertTrue(var.IsValid(), name)
+ self.assertIn(self.namespace + "::" + type_name, var.GetDisplayTypeName())
+ self.assertEqual(var.GetNumChildren(), 5, name)
for i in range(5):
ch = var.GetChildAtIndex(i)
- self.assertTrue(ch.IsValid())
- self.assertEqual(ch.GetValueAsSigned(), i + 1)
+ self.assertTrue(ch.IsValid(), f"{name}[{i}]")
+ self.assertEqual(ch.GetValueAsSigned(), i + 1, f"{name}[{i}]")
+
+ def check_priority_queue(self, name):
+ var = self.frame().FindVariable(name)
+ self.assertTrue(var.IsValid(), name)
+ self.assertIn(self.namespace + "::priority_queue", var.GetDisplayTypeName())
+ self.assertEqual(var.GetNumChildren(), 5, name)
+ values = sorted(var.GetChildAtIndex(i).GetValueAsSigned() for i in range(5))
+ self.assertEqual(values, [1, 2, 3, 4, 5])
+
+ def do_test_queues(self):
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp", False)
+ )
+ self.check_sequence("q1", "queue")
+ self.check_sequence("q2", "queue")
+
+ def do_test_adaptors(self):
+ self.do_test_queues()
+ self.check_sequence("s1", "stack")
+ self.check_sequence("s2", "stack")
+ self.check_priority_queue("pq")
+
+ @expectedFailureAll(
+ bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android"
+ )
+ @add_test_categories(["libstdcxx"])
+ def test_libstdcxx(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_adaptors()
@expectedFailureAll(
bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android"
)
@add_test_categories(["libc++"])
def test_libcxx(self):
- """Test that std::queue is displayed correctly"""
self.build(dictionary={"USE_LIBCPP": 1})
- lldbutil.run_to_source_breakpoint(
- self, "// break here", lldb.SBFileSpec("main.cpp", False)
- )
+ self.do_test_queues()
- self.check_variable("q1")
- self.check_variable("q2")
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ self.build()
+ self.do_test_adaptors()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/main.cpp
index 406b437914932..a85c5f8ce39d2 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/queue/main.cpp
@@ -1,9 +1,15 @@
#include <queue>
+#include <stack>
#include <vector>
int main() {
std::queue<int> q1{{1, 2, 3, 4, 5}};
std::queue<int, std::vector<int>> q2{{1, 2, 3, 4, 5}};
- int ret = q1.size() + q2.size(); // break here
- return ret;
+ std::stack<int> s1{{1, 2, 3, 4, 5}};
+ std::stack<int, std::vector<int>> s2{{1, 2, 3, 4, 5}};
+ std::priority_queue<int> pq;
+ for (int v : {1, 2, 3, 4, 5})
+ pq.push(v);
+ int ret = q1.size() + q2.size() + s1.size() + s2.size() + pq.size();
+ return ret; // break here
}
>From 255b09e5785d95790d2da6d21a33a906f884ce5a Mon Sep 17 00:00:00 2001
From: Bjorn Schobben <bjorn.schobben at aimsport.com>
Date: Wed, 19 Aug 2026 13:29:36 +0200
Subject: [PATCH 2/4] [lldb] Rename queue frontend to
GenericContainerAdaptorFrontEndCreator
The protected member `c` is required by the standard, so the same
frontend covers libc++, libstdc++, and MSVC STL.
Part of #24834
---
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 12 ++++++------
.../Plugins/Language/CPlusPlus/LibCxx.h | 7 +++++--
.../Language/CPlusPlus/LibCxxQueue.cpp | 19 +++++++++----------
3 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index c28e75745dfca..b1fc657069de9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -908,7 +908,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::unordered containers synthetic children",
"^std::__[[:alnum:]]+::unordered_(multi)?(map|set)<.+> >$",
stl_synth_flags, true);
- AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ AddCXXSynthetic(cpp_category_sp, GenericContainerAdaptorFrontEndCreator,
"libc++ std::queue synthetic children",
"^std::__[[:alnum:]]+::queue<.+>$", stl_synth_flags, true);
AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,
@@ -1948,15 +1948,15 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::strong_ordering",
eTypeOptionHideChildren | eTypeOptionHideValue, false);
- // Container adaptors store the underlying container in a member named `c`
- // in both MSVC STL and libstdc++.
- AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ // Container adaptors expose the underlying container as the standard
+ // protected member `c` ([queue.defn], [stack.defn], [priqueue.overview]).
+ AddCXXSynthetic(cpp_category_sp, GenericContainerAdaptorFrontEndCreator,
"std::queue synthetic children", "^std::queue<.+>(( )?&)?$",
stl_synth_flags, true);
- AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ AddCXXSynthetic(cpp_category_sp, GenericContainerAdaptorFrontEndCreator,
"std::stack synthetic children", "^std::stack<.+>(( )?&)?$",
stl_synth_flags, true);
- AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
+ AddCXXSynthetic(cpp_category_sp, GenericContainerAdaptorFrontEndCreator,
"std::priority_queue synthetic children",
"^std::priority_queue<.+>(( )?&)?$", stl_synth_flags, true);
AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index b2cbff8890861..c593428cb081f 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -209,8 +209,11 @@ SyntheticChildrenFrontEnd *
LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
-SyntheticChildrenFrontEnd *LibcxxQueueFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP);
+// std::queue / std::stack / std::priority_queue. The underlying container
+// is the standard protected member `c`.
+SyntheticChildrenFrontEnd *
+GenericContainerAdaptorFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP);
SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp
index 9d9ae354f3c09..7e0abce5ece40 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp
@@ -15,9 +15,10 @@ using namespace lldb_private;
namespace {
-class QueueFrontEnd : public SyntheticChildrenFrontEnd {
+class ContainerAdaptorFrontEnd : public SyntheticChildrenFrontEnd {
public:
- QueueFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
+ ContainerAdaptorFrontEnd(ValueObject &valobj)
+ : SyntheticChildrenFrontEnd(valobj) {
Update();
}
@@ -34,8 +35,7 @@ class QueueFrontEnd : public SyntheticChildrenFrontEnd {
}
ValueObjectSP GetChildAtIndex(uint32_t idx) override {
- return m_container_sp ? m_container_sp->GetChildAtIndex(idx)
- : nullptr;
+ return m_container_sp ? m_container_sp->GetChildAtIndex(idx) : nullptr;
}
private:
@@ -44,11 +44,11 @@ class QueueFrontEnd : public SyntheticChildrenFrontEnd {
// objects are only destroyed when every shared pointer to any of them
// is destroyed, so we must not store a shared pointer to any ValueObject
// derived from our backend ValueObject (since we're in the same cluster).
- ValueObject* m_container_sp = nullptr;
+ ValueObject *m_container_sp = nullptr;
};
} // namespace
-lldb::ChildCacheState QueueFrontEnd::Update() {
+lldb::ChildCacheState ContainerAdaptorFrontEnd::Update() {
m_container_sp = nullptr;
ValueObjectSP c_sp = m_backend.GetChildMemberWithName("c");
if (!c_sp)
@@ -57,10 +57,9 @@ lldb::ChildCacheState QueueFrontEnd::Update() {
return lldb::ChildCacheState::eRefetch;
}
-SyntheticChildrenFrontEnd *
-formatters::LibcxxQueueFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP valobj_sp) {
+SyntheticChildrenFrontEnd *formatters::GenericContainerAdaptorFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
if (valobj_sp)
- return new QueueFrontEnd(*valobj_sp);
+ return new ContainerAdaptorFrontEnd(*valobj_sp);
return nullptr;
}
>From 9df48c1863693d73fecd17e35b50f2bd83770070 Mon Sep 17 00:00:00 2001
From: Bjorn Schobben <bjorn.schobben at aimsport.com>
Date: Wed, 19 Aug 2026 18:11:31 +0200
Subject: [PATCH 3/4] [lldb] Move container adaptor frontend to
GenericQueue.cpp
The frontend is shared by libc++, libstdc++, and MSVC STL. Put the
declaration in Generic.h and drop the LibCxxQueue.cpp name.
---
lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt | 2 +-
lldb/source/Plugins/Language/CPlusPlus/Generic.h | 6 ++++++
.../CPlusPlus/{LibCxxQueue.cpp => GenericQueue.cpp} | 5 +++--
lldb/source/Plugins/Language/CPlusPlus/LibCxx.h | 6 ------
.../lldb/source/Plugins/Language/CPlusPlus/BUILD.gn | 2 +-
5 files changed, 11 insertions(+), 10 deletions(-)
rename lldb/source/Plugins/Language/CPlusPlus/{LibCxxQueue.cpp => GenericQueue.cpp} (94%)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 68093f3c96017..b0f5b38d642c1 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -21,10 +21,10 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
GenericInitializerList.cpp
GenericList.cpp
GenericOptional.cpp
+ GenericQueue.cpp
LibCxx.cpp
LibCxxAtomic.cpp
LibCxxMap.cpp
- LibCxxQueue.cpp
LibCxxRangesRefView.cpp
LibCxxSliceArray.cpp
LibCxxProxyArray.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/Generic.h b/lldb/source/Plugins/Language/CPlusPlus/Generic.h
index 539eddd3d3e78..1f86b95c521f3 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/Generic.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/Generic.h
@@ -27,6 +27,12 @@ lldb::ValueObjectSP GetDesugaredSmartPointerValue(ValueObject &ptr,
SyntheticChildrenFrontEnd *
GenericInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);
+
+// std::queue / std::stack / std::priority_queue. The underlying container
+// is the standard protected member `c`.
+SyntheticChildrenFrontEnd *
+GenericContainerAdaptorFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
} // namespace formatters
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
similarity index 94%
rename from lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp
rename to lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
index 7e0abce5ece40..4939ec6d7a3b9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
@@ -1,4 +1,4 @@
-//===-- LibCxxQueue.cpp ---------------------------------------------------===//
+//===-- GenericQueue.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "LibCxx.h"
+#include "Generic.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
#include "llvm/Support/ErrorExtras.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index c593428cb081f..b2057c2f30b63 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -209,12 +209,6 @@ SyntheticChildrenFrontEnd *
LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
-// std::queue / std::stack / std::priority_queue. The underlying container
-// is the standard protected member `c`.
-SyntheticChildrenFrontEnd *
-GenericContainerAdaptorFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP);
-
SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
diff --git a/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn
index d7732a059ef29..dda2d6985fe50 100644
--- a/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn
@@ -43,11 +43,11 @@ static_library("CPlusPlus") {
"GenericInitializerList.cpp",
"GenericList.cpp",
"GenericOptional.cpp",
+ "GenericQueue.cpp",
"LibCxx.cpp",
"LibCxxAtomic.cpp",
"LibCxxMap.cpp",
"LibCxxProxyArray.cpp",
- "LibCxxQueue.cpp",
"LibCxxRangesRefView.cpp",
"LibCxxSliceArray.cpp",
"LibCxxSpan.cpp",
>From 3cce01c3876fe622a2b99e6d548e2cad867b54a4 Mon Sep 17 00:00:00 2001
From: Daedie-git <HC_Daedalus at hotmail.com>
Date: Thu, 20 Aug 2026 12:40:53 +0200
Subject: [PATCH 4/4] Update
lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
Co-authored-by: Nerixyz <nero.9 at hotmail.de>
---
lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
index 4939ec6d7a3b9..3c20c1afe2e9c 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/GenericQueue.cpp
@@ -1,4 +1,4 @@
-//===-- GenericQueue.cpp --------------------------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
More information about the llvm-commits
mailing list