[Lldb-commits] [lldb] [lldb] Add MSVC STL/libstdc++ formatters for error_code and error_condition (PR #217245)

via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 19 02:18:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Daedie-git

<details>
<summary>Changes</summary>

Summarize `std::error_code` and `std::error_condition` as `value=N`. MSVC stores the integer in `_Myval`; libstdc++ uses `_M_value`. Children stay visible so the category pointer (`_Mycat` / `_M_cat`) remains inspectable.

Tests: layout simulator plus a generic libstdc++/MSVC STL test.

Split out of #<!-- -->217177 at @<!-- -->Nerixyz's request. Leaving bitset (#<!-- -->175570), initializer_list (#<!-- -->178712), coroutine_handle (#<!-- -->194941), and chrono (#<!-- -->195125) to those PRs.

Part of #<!-- -->24834

CC @<!-- -->Nerixyz @<!-- -->DavidSpickett @<!-- -->Michael137

I've read the LLVM Developer Policy, Code-Review Policy, and [AI Tool Use Policy](https://llvm.org/docs/AIToolPolicy.html).

AI tool usage: Grok 4.6 was used to help write this change. I reviewed the result and can answer questions about the patch during review.

---
Full diff: https://github.com/llvm/llvm-project/pull/217245.diff


9 Files Affected:

- (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+17) 
- (modified) lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp (+23) 
- (modified) lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h (+5) 
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/Makefile (+2) 
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/TestDataFormatterStdErrorCode.py (+39) 
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/main.cpp (+9) 
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/Makefile (+2) 
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/TestDataFormatterMsvcStlErrorCodeSimulator.py (+25) 
- (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/main.cpp (+19) 


``````````diff
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 8225c2141a84a..2d47f6793712f 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1947,6 +1947,23 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
                 "MSVC STL/libstdc++ std::strong_ordering summary provider",
                 "std::strong_ordering",
                 eTypeOptionHideChildren | eTypeOptionHideValue, false);
+
+  // Keep children visible: the summary only prints the integer value, so
+  // the category pointer (_Mycat / _M_cat) must still be inspectable.
+  TypeSummaryImpl::Flags error_code_flags;
+  error_code_flags.SetCascades(true)
+      .SetSkipPointers(false)
+      .SetSkipReferences(false)
+      .SetDontShowChildren(false)
+      .SetDontShowValue(false)
+      .SetShowMembersOneLiner(false)
+      .SetHideItemNames(false);
+  AddCXXSummary(cpp_category_sp, MsvcStlErrorCodeSummaryProvider,
+                "MSVC STL/libstdc++ std::error_code summary provider",
+                "std::error_code", error_code_flags);
+  AddCXXSummary(cpp_category_sp, MsvcStlErrorCodeSummaryProvider,
+                "MSVC STL/libstdc++ std::error_condition summary provider",
+                "std::error_condition", error_code_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..2f69312f19ab9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
@@ -305,3 +305,26 @@ bool lldb_private::formatters::MsvcStlStrongOrderingSummaryProvider(
   }
   return true;
 }
+
+bool lldb_private::formatters::IsMsvcStlErrorCode(ValueObject &valobj) {
+  if (auto valobj_sp = valobj.GetNonSyntheticValue())
+    return valobj_sp->GetChildMemberWithName("_Myval") != nullptr &&
+           valobj_sp->GetChildMemberWithName("_Mycat") != nullptr;
+  return false;
+}
+
+bool lldb_private::formatters::MsvcStlErrorCodeSummaryProvider(
+    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
+  ValueObjectSP value_sp = valobj.GetChildMemberWithName("_Myval");
+  if (!value_sp)
+    value_sp = valobj.GetChildMemberWithName("_M_value");
+  if (!value_sp)
+    return false;
+
+  const char *value = value_sp->GetValueAsCString();
+  if (!value)
+    return false;
+
+  stream.Printf("value=%s", value);
+  return true;
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
index 0bdd548dd99e3..8f00abc2ed625 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::error_code / std::error_condition
+bool IsMsvcStlErrorCode(ValueObject &valobj);
+bool MsvcStlErrorCodeSummaryProvider(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/error_code/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/Makefile
new file mode 100644
index 0000000000000..3d0b98f13f3d7
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/Makefile
@@ -0,0 +1,2 @@
+CXX_SOURCES := main.cpp
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/TestDataFormatterStdErrorCode.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/TestDataFormatterStdErrorCode.py
new file mode 100644
index 0000000000000..1d847ee56b31d
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/TestDataFormatterStdErrorCode.py
@@ -0,0 +1,39 @@
+"""Test std::error_code / std::error_condition summaries."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class StdErrorCodeTestCase(TestBase):
+    SHARED_BUILD_TESTCASE = False
+    TEST_WITH_PDB_DEBUG_INFO = True
+
+    def do_test(self):
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.cpp")
+        )
+
+        ec = self.frame().FindVariable("ec")
+        self.assertTrue(ec.GetError().Success())
+        self.assertRegex(ec.summary, r"value=\d+")
+        self.assertGreaterEqual(ec.GetNumChildren(), 1)
+
+        econd = self.frame().FindVariable("econd")
+        self.assertTrue(econd.GetError().Success())
+        self.assertRegex(econd.summary, r"value=\d+")
+
+        default_ec = self.frame().FindVariable("default_ec")
+        self.assertTrue(default_ec.GetError().Success())
+        self.assertEqual(default_ec.summary, "value=0")
+
+    @add_test_categories(["libstdcxx"])
+    def test_libstdcxx(self):
+        self.build(dictionary={"USE_LIBSTDCPP": 1})
+        self.do_test()
+
+    @add_test_categories(["msvcstl"])
+    def test_msvcstl(self):
+        self.build()
+        self.do_test()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/main.cpp
new file mode 100644
index 0000000000000..d6dca8b6290ca
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/main.cpp
@@ -0,0 +1,9 @@
+#include <system_error>
+
+int main() {
+  std::error_code ec =
+      std::make_error_code(std::errc::no_such_file_or_directory);
+  std::error_condition econd = std::errc::no_such_file_or_directory;
+  std::error_code default_ec;
+  return 0; // break here
+}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/Makefile
new file mode 100644
index 0000000000000..3d0b98f13f3d7
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/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/error_code/TestDataFormatterMsvcStlErrorCodeSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/TestDataFormatterMsvcStlErrorCodeSimulator.py
new file mode 100644
index 0000000000000..d7915e60574b9
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/TestDataFormatterMsvcStlErrorCodeSimulator.py
@@ -0,0 +1,25 @@
+"""Simulate MSVC STL std::error_code and check the formatter."""
+
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class MsvcStlErrorCodeSimulatorTestCase(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "break here", lldb.SBFileSpec("main.cpp")
+        )
+
+        ec = self.frame().FindVariable("ec")
+        self.assertTrue(ec.IsValid())
+        self.assertGreaterEqual(ec.GetNumChildren(), 1)
+        self.assertIsNotNone(ec.GetChildMemberWithName("_Mycat"))
+        self.expect("frame variable ec", substrs=["value=2"])
+
+        econd = self.frame().FindVariable("econd")
+        self.assertTrue(econd.IsValid())
+        self.assertGreaterEqual(econd.GetNumChildren(), 1)
+        self.expect("frame variable econd", substrs=["value=7"])
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/main.cpp
new file mode 100644
index 0000000000000..b72103175ba7f
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvc-simulators/error_code/main.cpp
@@ -0,0 +1,19 @@
+// Layout approximation of MSVC STL std::error_code / error_condition.
+
+namespace std {
+struct error_code {
+  int _Myval;
+  const void *_Mycat;
+};
+
+struct error_condition {
+  int _Myval;
+  const void *_Mycat;
+};
+} // namespace std
+
+int main() {
+  std::error_code ec{2, nullptr};
+  std::error_condition econd{7, nullptr};
+  return 0; // break here
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/217245


More information about the lldb-commits mailing list