Author: Daedie-git Date: 2026-08-20T18:47:36+02:00 New Revision: c548c6ad4e3965bba68097a588edc8d667328c4f
URL: https://github.com/llvm/llvm-project/commit/c548c6ad4e3965bba68097a588edc8d667328c4f DIFF: https://github.com/llvm/llvm-project/commit/c548c6ad4e3965bba68097a588edc8d667328c4f.diff LOG: [lldb] Add MSVC STL/libstdc++ formatters for error_code and error_condition (#217245) Summarize `std::error_code` and `std::error_condition` as `value=N`. MSVC stores the integer in `_Myval`; libstdc++ uses `_M_value`. The category is shown in the synthetic children provider. Part of #24834 Assisted-by: Grok 4.6 Assisted-by: codex-5.6-high --------- Co-authored-by: Bjorn Schobben <[email protected]> Added: lldb/source/Plugins/Language/CPlusPlus/GenericErrorCode.cpp lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/Makefile lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/TestDataFormatterStdErrorCode.py lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/main.cpp Modified: lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp lldb/source/Plugins/Language/CPlusPlus/Generic.h Removed: ################################################################################ diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 6f2010acd234e..c34f63637dbb4 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -18,6 +18,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN CxxStringTypes.cpp Generic.cpp GenericBitset.cpp + GenericErrorCode.cpp GenericFilesystem.cpp GenericInitializerList.cpp GenericList.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 32e8154ee2d7a..30050e0878e6e 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1972,6 +1972,17 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider, "std::priority_queue summary provider", "^std::priority_queue<.+>(( )?&)?$", stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, GenericErrorCodeSummaryProvider, + "MSVC STL/libstdc++ std::error_code summary provider", + "std::error_code", stl_summary_flags); + AddCXXSummary(cpp_category_sp, GenericErrorCodeSummaryProvider, + "MSVC STL/libstdc++ std::error_condition summary provider", + "std::error_condition", stl_summary_flags); + AddCXXSynthetic(cpp_category_sp, GenericErrorCodeSyntheticFrontEndCreator, + "MSVC STL/libstdc++ std::error_code/error_condition " + "synthetic children", + "^std::error_(code|condition)$", stl_synth_flags, true); } static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/Generic.h b/lldb/source/Plugins/Language/CPlusPlus/Generic.h index 92355ad3e536e..c0c578ac34fe8 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/Generic.h +++ b/lldb/source/Plugins/Language/CPlusPlus/Generic.h @@ -19,6 +19,12 @@ namespace formatters { bool GenericOptionalSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); +bool GenericErrorCodeSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); +SyntheticChildrenFrontEnd * +GenericErrorCodeSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp); + bool GenericFilesystemPathSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericErrorCode.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericErrorCode.cpp new file mode 100644 index 0000000000000..b50567f5a2c18 --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericErrorCode.cpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// 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 "Generic.h" + +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "llvm/Support/ErrorExtras.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +ValueObjectSP GetValue(ValueObject &valobj) { + ValueObjectSP value_sp = valobj.GetChildMemberWithName("_Myval"); // MSVC STL. + if (!value_sp) + value_sp = valobj.GetChildMemberWithName("_M_value"); // libstdc++. + return value_sp; +} + +ValueObjectSP GetCategory(ValueObject &valobj) { + ValueObjectSP category_sp = + valobj.GetChildMemberWithName("_Mycat"); // MSVC STL. + if (!category_sp) + category_sp = valobj.GetChildMemberWithName("_M_cat"); // libstdc++. + return category_sp; +} + +class GenericErrorCodeFrontend : public SyntheticChildrenFrontEnd { +public: + explicit GenericErrorCodeFrontend(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override { + if (name == "Category" && m_category) + return 0; + return llvm::createStringErrorV("type has no child named '{0}'", name); + } + + llvm::Expected<uint32_t> CalculateNumChildren() override { + return m_category ? 1U : 0U; + } + + ValueObjectSP GetChildAtIndex(uint32_t idx) override { + if (idx != 0 || !m_category) + return {}; + return m_category->Clone(ConstString("Category")); + } + + lldb::ChildCacheState Update() override { + m_category = GetCategory(m_backend).get(); + return lldb::ChildCacheState::eRefetch; + } + +private: + // Children derived from the backend share its ClusterManager. Keeping a + // shared pointer here would create an ownership cycle. + ValueObject *m_category = nullptr; +}; + +} // namespace + +bool lldb_private::formatters::GenericErrorCodeSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + ValueObjectSP valobj_sp = valobj.GetNonSyntheticValue(); + if (!valobj_sp) + return false; + + ValueObjectSP value_sp = GetValue(*valobj_sp); + if (!value_sp) + return false; + + const char *value = value_sp->GetValueAsCString(); + if (!value) + return false; + + stream.Printf("value=%s", value); + return true; +} + +SyntheticChildrenFrontEnd * +lldb_private::formatters::GenericErrorCodeSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (!valobj_sp) + return nullptr; + return new GenericErrorCodeFrontend(*valobj_sp); +} 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..841084bf45637 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/error_code/TestDataFormatterStdErrorCode.py @@ -0,0 +1,45 @@ +"""Test std::error_code / std::error_condition summaries.""" + +import re + +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 check_value(self, name, summary): + self.expect_var_path( + name, + summary=summary, + children=[ + ValueCheck( + name="Category", + value=re.compile(r"0x(?!0+$)[0-9a-fA-F]+$"), + ) + ], + ) + + def do_test(self): + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.cpp") + ) + + self.check_value("ec", "value=2") + self.check_value("econd", "value=7") + self.check_value("negative", "value=-1") + self.check_value("default_ec", "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..a15a9cb473a3d --- /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(2, std::generic_category()); + std::error_condition econd(7, std::generic_category()); + std::error_code negative(-1, std::generic_category()); + std::error_code default_ec; + return 0; // break here +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
