[Lldb-commits] [lldb] [lldb] Add MSVC STL formatter for std::source_location (PR #217244)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Aug 20 11:27:53 PDT 2026
https://github.com/Daedie-git updated https://github.com/llvm/llvm-project/pull/217244
>From 4d69ded0939eeac32d6c1d717280743a67d1dffa Mon Sep 17 00:00:00 2001
From: Bjorn Schobben <bjorn.schobben at aimsport.com>
Date: Wed, 19 Aug 2026 11:03:18 +0200
Subject: [PATCH 1/3] [lldb] Add MSVC STL formatter for std::source_location
Dispatch on the MSVC layout (_File/_Line) so the shared std:: name
does not steal libstdc++'s existing formatter. Leave a default-
constructed location without a summary.
Part of #24834
---
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 12 ++++++
.../Plugins/Language/CPlusPlus/MsvcStl.cpp | 41 +++++++++++++++++++
.../Plugins/Language/CPlusPlus/MsvcStl.h | 5 +++
.../TestDataFormatterStdSourceLocation.py | 20 +++++++++
.../msvc-simulators/source_location/Makefile | 2 +
...FormatterMsvcStlSourceLocationSimulator.py | 22 ++++++++++
.../msvc-simulators/source_location/main.cpp | 18 ++++++++
7 files changed, 120 insertions(+)
create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile
create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py
create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 30050e0878e6e..423fbd9a91e98 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1725,6 +1725,14 @@ GenericStrongOrderingSummaryProvider(ValueObject &valobj, Stream &stream,
return LibStdcppStrongOrderingSummaryProvider(valobj, stream, options);
}
+static bool
+GenericSourceLocationSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ if (IsMsvcStlSourceLocation(valobj))
+ return MsvcStlSourceLocationSummaryProvider(valobj, stream, options);
+ return LibStdcppSourceLocationSummaryProvider(valobj, stream, options);
+}
+
/// Load formatters that are formatting types from more than one STL
static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
@@ -1983,6 +1991,10 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"MSVC STL/libstdc++ std::error_code/error_condition "
"synthetic children",
"^std::error_(code|condition)$", stl_synth_flags, true);
+
+ AddCXXSummary(cpp_category_sp, GenericSourceLocationSummaryProvider,
+ "MSVC STL/libstdc++ std::source_location summary provider",
+ "std::source_location", stl_summary_flags);
}
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
index 93a01acdc0f0a..f32d2be4c149e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
@@ -16,6 +16,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/ValueObject/ValueObject.h"
+#include "llvm/ADT/StringRef.h"
#include "Plugins/Language/CPlusPlus/CxxStringTypes.h"
@@ -305,3 +306,43 @@ bool lldb_private::formatters::MsvcStlStrongOrderingSummaryProvider(
}
return true;
}
+
+bool lldb_private::formatters::IsMsvcStlSourceLocation(ValueObject &valobj) {
+ if (auto valobj_sp = valobj.GetNonSyntheticValue())
+ return valobj_sp->GetChildMemberWithName("_File") != nullptr &&
+ valobj_sp->GetChildMemberWithName("_Line") != nullptr;
+ return false;
+}
+
+bool lldb_private::formatters::MsvcStlSourceLocationSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
+ ValueObjectSP file_sp = valobj.GetChildMemberWithName("_File");
+ ValueObjectSP function_sp = valobj.GetChildMemberWithName("_Function");
+ ValueObjectSP line_sp = valobj.GetChildMemberWithName("_Line");
+ ValueObjectSP column_sp = valobj.GetChildMemberWithName("_Column");
+
+ if (!file_sp || !function_sp || !line_sp || !column_sp)
+ return false;
+
+ bool success = false;
+ uint64_t line = line_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ return false;
+
+ uint64_t column = column_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ return false;
+
+ const char *file = file_sp->GetSummaryAsCString();
+ // Default-constructed source_location is empty; don't invent a summary.
+ if (line == 0 && column == 0 &&
+ (!file || file[0] == '\0' || llvm::StringRef(file) == "\"\""))
+ return false;
+
+ stream.Format("{0}:{1}:{2}", file ? file : "<unknown>", line, column);
+
+ if (const char *function = function_sp->GetSummaryAsCString())
+ stream.Printf(" (%s)", function);
+
+ return true;
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
index 0bdd548dd99e3..1000a229118f2 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
@@ -142,6 +142,11 @@ SyntheticChildrenFrontEnd *
MsvcStlSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);
+// MSVC STL std::source_location
+bool IsMsvcStlSourceLocation(ValueObject &valobj);
+bool MsvcStlSourceLocationSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
} // namespace formatters
} // namespace lldb_private
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
index 4dd28c816a10c..5ffa9a62cc8e8 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
@@ -51,3 +51,23 @@ def test_libcxx(self):
def test_libstdcxx(self):
self.build(dictionary={"USE_LIBSTDCPP": 1})
self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+
+ frame = self.frame()
+ loc_main = frame.FindVariable("loc_main")
+ self.assertTrue(loc_main.GetError().Success())
+ self.assertRegex(loc_main.summary, r"main\.cpp\":6:\d+.*main")
+
+ loc_foo = frame.FindVariable("loc_foo")
+ self.assertTrue(loc_foo.GetError().Success())
+ self.assertRegex(loc_foo.summary, r"main\.cpp\":3:\d+.*foo")
+
+ loc_empty = frame.FindVariable("loc_empty")
+ self.assertTrue(loc_empty.GetError().Success())
+ self.assertTrue(not loc_empty.summary)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile
new file mode 100644
index 0000000000000..3d0b98f13f3d7
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile
@@ -0,0 +1,2 @@
+CXX_SOURCES := main.cpp
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py
new file mode 100644
index 0000000000000..5211f58279c7d
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py
@@ -0,0 +1,22 @@
+"""Simulate MSVC STL std::source_location and check the formatter."""
+
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class MsvcStlSourceLocationSimulatorTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "break here", lldb.SBFileSpec("main.cpp")
+ )
+
+ self.expect(
+ "frame variable loc",
+ substrs=['"main.cpp":6:1', "__cdecl", "main"],
+ )
+ loc_empty = self.frame().FindVariable("loc_empty")
+ self.assertTrue(loc_empty.GetError().Success())
+ self.assertTrue(not loc_empty.summary)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp
new file mode 100644
index 0000000000000..da13cfcf1949d
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp
@@ -0,0 +1,18 @@
+// Layout approximation of MSVC STL std::source_location.
+
+#include <stdint.h>
+
+namespace std {
+struct source_location {
+ const char *_File;
+ const char *_Function;
+ uint32_t _Line;
+ uint32_t _Column;
+};
+} // namespace std
+
+int main() {
+ std::source_location loc{"main.cpp", "int __cdecl main(void)", 6, 1};
+ std::source_location loc_empty{"", "", 0, 0};
+ return 0; // break here
+}
>From 6c4d067eb2d8b53ed4ac6523a91ee238890bc88f Mon Sep 17 00:00:00 2001
From: Bjorn Schobben <bjorn.schobben at aimsport.com>
Date: Thu, 20 Aug 2026 19:23:07 +0200
Subject: [PATCH 2/3] [lldb] Refine MSVC source_location formatter coverage
---
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 8 +++---
.../TestDataFormatterStdSourceLocation.py | 25 ++++++++++---------
.../msvc-simulators/source_location/Makefile | 2 --
...FormatterMsvcStlSourceLocationSimulator.py | 22 ----------------
.../msvc-simulators/source_location/main.cpp | 18 -------------
5 files changed, 17 insertions(+), 58 deletions(-)
delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile
delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py
delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 423fbd9a91e98..f1ca9f1acd4a4 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1852,6 +1852,10 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"MSVC STL/libstdc++ std::filesystem::path summary provider",
"^std::filesystem::(__cxx11::)?path$", stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, GenericSourceLocationSummaryProvider,
+ "MSVC STL/libstdc++ std::source_location summary provider",
+ "std::source_location", stl_summary_flags);
+
stl_summary_flags.SetDontShowChildren(false);
stl_summary_flags.SetSkipPointers(false);
@@ -1991,10 +1995,6 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"MSVC STL/libstdc++ std::error_code/error_condition "
"synthetic children",
"^std::error_(code|condition)$", stl_synth_flags, true);
-
- AddCXXSummary(cpp_category_sp, GenericSourceLocationSummaryProvider,
- "MSVC STL/libstdc++ std::source_location summary provider",
- "std::source_location", stl_summary_flags);
}
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
index 5ffa9a62cc8e8..5e1cf90ae644a 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
@@ -3,6 +3,7 @@
"""
import lldb
+import re
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
@@ -59,15 +60,15 @@ def test_msvcstl(self):
self, "// break here", lldb.SBFileSpec("main.cpp")
)
- frame = self.frame()
- loc_main = frame.FindVariable("loc_main")
- self.assertTrue(loc_main.GetError().Success())
- self.assertRegex(loc_main.summary, r"main\.cpp\":6:\d+.*main")
-
- loc_foo = frame.FindVariable("loc_foo")
- self.assertTrue(loc_foo.GetError().Success())
- self.assertRegex(loc_foo.summary, r"main\.cpp\":3:\d+.*foo")
-
- loc_empty = frame.FindVariable("loc_empty")
- self.assertTrue(loc_empty.GetError().Success())
- self.assertTrue(not loc_empty.summary)
+ self.expect_var_path(
+ "loc_main",
+ summary=re.compile(r'main\.cpp":6:\d+.*main'),
+ children=[],
+ )
+ self.expect_var_path(
+ "loc_foo",
+ summary=re.compile(r'main\.cpp":3:\d+.*foo'),
+ children=[],
+ )
+ loc_empty = self.expect_var_path("loc_empty", children=[])
+ self.assertIsNone(loc_empty.summary)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile
deleted file mode 100644
index 3d0b98f13f3d7..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-CXX_SOURCES := main.cpp
-include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py
deleted file mode 100644
index 5211f58279c7d..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/TestDataFormatterMsvcStlSourceLocationSimulator.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""Simulate MSVC STL std::source_location and check the formatter."""
-
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class MsvcStlSourceLocationSimulatorTestCase(TestBase):
- NO_DEBUG_INFO_TESTCASE = True
-
- def test(self):
- self.build()
- lldbutil.run_to_source_breakpoint(
- self, "break here", lldb.SBFileSpec("main.cpp")
- )
-
- self.expect(
- "frame variable loc",
- substrs=['"main.cpp":6:1', "__cdecl", "main"],
- )
- loc_empty = self.frame().FindVariable("loc_empty")
- self.assertTrue(loc_empty.GetError().Success())
- self.assertTrue(not loc_empty.summary)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp
deleted file mode 100644
index da13cfcf1949d..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/source_location/main.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Layout approximation of MSVC STL std::source_location.
-
-#include <stdint.h>
-
-namespace std {
-struct source_location {
- const char *_File;
- const char *_Function;
- uint32_t _Line;
- uint32_t _Column;
-};
-} // namespace std
-
-int main() {
- std::source_location loc{"main.cpp", "int __cdecl main(void)", 6, 1};
- std::source_location loc_empty{"", "", 0, 0};
- return 0; // break here
-}
>From f4ed95f3a6d4eff86d46ecc16b7507210be7b842 Mon Sep 17 00:00:00 2001
From: Bjorn Schobben <bjorn.schobben at aimsport.com>
Date: Thu, 20 Aug 2026 20:27:27 +0200
Subject: [PATCH 3/3] [lldb] Test source_location child hiding through CLI
output
---
.../TestDataFormatterStdSourceLocation.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
index 5e1cf90ae644a..48943aa626c63 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/source_location/TestDataFormatterStdSourceLocation.py
@@ -63,12 +63,17 @@ def test_msvcstl(self):
self.expect_var_path(
"loc_main",
summary=re.compile(r'main\.cpp":6:\d+.*main'),
- children=[],
)
self.expect_var_path(
"loc_foo",
summary=re.compile(r'main\.cpp":3:\d+.*foo'),
- children=[],
)
- loc_empty = self.expect_var_path("loc_empty", children=[])
+ loc_empty = self.expect_var_path("loc_empty")
self.assertIsNone(loc_empty.summary)
+
+ for member in ("_File =", "_Function =", "_Line =", "_Column ="):
+ self.expect(
+ "frame variable loc_main loc_foo",
+ matching=False,
+ substrs=[member],
+ )
More information about the lldb-commits
mailing list