[Lldb-commits] [lldb] [LLDB] Fix MS STL `variant` with non-trivial types and PDB (PR #171489)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Dec 10 08:57:22 PST 2025
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/171489
>From 3860c0b95ce99e944d1598513428c5e81aeea395 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Thu, 6 Nov 2025 19:51:20 +0100
Subject: [PATCH 1/2] [LLDB] Fix MS STL `variant` with non-trivial types and
PDB
---
.../Language/CPlusPlus/MsvcStlVariant.cpp | 25 +++++++++++++------
.../variant/TestDataFormatterStdVariant.py | 23 +++++++++++++++++
.../generic/variant/main.cpp | 5 ++++
3 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp
index 52a3d98d2af4b..3391ca33a9277 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp
@@ -67,12 +67,18 @@ std::optional<int64_t> GetIndexValue(ValueObject &valobj) {
ValueObjectSP GetNthStorage(ValueObject &outer, int64_t index) {
// We need to find the std::_Variant_storage base class.
- // -> std::_SMF_control (typedef to std::_Variant_base)
- ValueObjectSP container_sp = outer.GetSP()->GetChildAtIndex(0);
- if (!container_sp)
+ // Navigate "down" to std::_Variant_base by finding the holder of "_Which".
+ // This might be down a few levels if a variant member isn't trivially
+ // destructible/copyable/etc.
+ ValueObjectSP which_sp = outer.GetChildMemberWithName("_Which");
+ if (!which_sp)
+ return nullptr;
+ ValueObject *parent = which_sp->GetParent();
+ if (!parent)
return nullptr;
- // -> std::_Variant_storage
- container_sp = container_sp->GetChildAtIndex(0);
+
+ // Now go to std::_Variant_storage
+ ValueObjectSP container_sp = parent->GetChildAtIndex(0);
if (!container_sp)
return nullptr;
@@ -119,8 +125,13 @@ bool formatters::MsvcStlVariantSummaryProvider(
storage_type = storage_type.GetTypedefedType();
CompilerType active_type = storage_type.GetTypeTemplateArgument(1, true);
- if (!active_type)
- return false;
+ if (!active_type) {
+ // PDB: get the type from the head as we don't have template arguments there
+ ValueObjectSP head = GetHead(*storage);
+ active_type = head->GetCompilerType();
+ if (!active_type)
+ return false;
+ }
stream << " Active Type = " << active_type.GetDisplayTypeName() << " ";
return true;
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py
index 9f32ad97c1f0a..d5c4f5c34cfe0 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py
@@ -9,6 +9,8 @@
class StdVariantDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def do_test(self):
"""Test that that file and class static variables display correctly."""
@@ -48,6 +50,14 @@ def cleanup():
],
)
+ self.expect_expr(
+ "v4",
+ result_summary=" Active Type = int ",
+ result_children=[
+ ValueCheck(name="Value", value="4"),
+ ],
+ )
+
lldbutil.continue_to_breakpoint(self.process, bkpt)
self.expect(
@@ -67,6 +77,19 @@ def cleanup():
substrs=["v3 = Active Type = char {", "Value = 'A'", "}"],
)
+ string_name = (
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char>>"
+ if self.getDebugInfo() == "pdb"
+ else "std::basic_string<char>"
+ )
+ self.expect_expr(
+ "v4",
+ result_summary=f" Active Type = {string_name} ",
+ result_children=[
+ ValueCheck(name="Value", summary='"a string"'),
+ ],
+ )
+
self.expect("frame variable v_valueless", substrs=["v_valueless = No Value"])
self.expect(
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/main.cpp
index 620b97b7306f9..9983104ca9628 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/main.cpp
@@ -49,6 +49,8 @@ int main() {
S>
v_300_types_valueless;
+ std::variant<int, bool, std::string> v4 = 4;
+
v_valueless = 5;
v_300_types_valueless.emplace<0>(10);
@@ -70,6 +72,9 @@ int main() {
// state when we change its value.
v1 = 2.0;
d = std::get<double>(v1);
+
+ v4 = "a string";
+
printf("%f\n", d); // break here
try {
>From ae5ecead822566dbe5317a1e6372428a36173540 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 10 Dec 2025 17:57:05 +0100
Subject: [PATCH 2/2] fix: comments
---
lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp
index 3391ca33a9277..96470eaf572e4 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp
@@ -77,7 +77,7 @@ ValueObjectSP GetNthStorage(ValueObject &outer, int64_t index) {
if (!parent)
return nullptr;
- // Now go to std::_Variant_storage
+ // Now go to std::_Variant_storage.
ValueObjectSP container_sp = parent->GetChildAtIndex(0);
if (!container_sp)
return nullptr;
@@ -126,7 +126,8 @@ bool formatters::MsvcStlVariantSummaryProvider(
CompilerType active_type = storage_type.GetTypeTemplateArgument(1, true);
if (!active_type) {
- // PDB: get the type from the head as we don't have template arguments there
+ // PDB: get the type from the head as we don't have template arguments
+ // there.
ValueObjectSP head = GetHead(*storage);
active_type = head->GetCompilerType();
if (!active_type)
More information about the lldb-commits
mailing list