llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: nerix (Nerixyz) <details> <summary>Changes</summary> Adds synthetic children for `std::optional` from MSVC's STL. Most of the machinery for `std::optional` is already there. Towards #<!-- -->24834. --- Full diff: https://github.com/llvm/llvm-project/pull/149545.diff 4 Files Affected: - (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+19-10) - (modified) lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp (+24-2) - (modified) lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h (+6) - (modified) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py (+12-7) ``````````diff diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index a8ebde0b55815..a49990e11f86d 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1545,20 +1545,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::bitset synthetic child", "^std::(__debug::)?bitset<.+>(( )?&)?$", stl_deref_flags, true); - AddCXXSynthetic( - cpp_category_sp, - lldb_private::formatters::LibStdcppOptionalSyntheticFrontEndCreator, - "std::optional synthetic child", "^std::optional<.+>(( )?&)?$", - stl_deref_flags, true); - AddCXXSummary(cpp_category_sp, lldb_private::formatters::StdlibCoroutineHandleSummaryProvider, "libstdc++ std::coroutine_handle summary provider", libstdcpp_std_coroutine_handle_regex, stl_summary_flags, true); - AddCXXSummary(cpp_category_sp, - lldb_private::formatters::GenericOptionalSummaryProvider, - "libstd++ std::optional summary provider", - "^std::optional<.+>(( )?&)?$", stl_summary_flags, true); } static lldb_private::SyntheticChildrenFrontEnd * @@ -1648,6 +1638,17 @@ GenericForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *children, *valobj_sp); } +static SyntheticChildrenFrontEnd * +GenericOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *children, + lldb::ValueObjectSP valobj_sp) { + if (!valobj_sp) + return nullptr; + + if (IsMsvcStlOptional(*valobj_sp)) + return MsvcStlOptionalSyntheticFrontEndCreator(children, valobj_sp); + return LibStdcppOptionalSyntheticFrontEndCreator(children, valobj_sp); +} + /// Load formatters that are formatting types from more than one STL static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { if (!cpp_category_sp) @@ -1664,6 +1665,8 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( false); + SyntheticChildren::Flags stl_deref_flags = stl_synth_flags; + stl_deref_flags.SetFrontEndWantsDereference(); using StringElementType = StringPrinter::StringElementType; @@ -1712,6 +1715,9 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSynthetic(cpp_category_sp, GenericForwardListSyntheticFrontEndCreator, "std::forward_list synthetic children", "^std::forward_list<.+>(( )?&)?$", stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, GenericOptionalSyntheticFrontEndCreator, + "std::optional synthetic children", + "^std::optional<.+>(( )?&)?$", stl_deref_flags, true); AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider, "MSVC STL/libstdc++ std::shared_ptr summary provider", @@ -1739,6 +1745,9 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { TypeSummaryImplSP(new ScriptSummaryFormat( stl_summary_flags, "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); + AddCXXSummary(cpp_category_sp, GenericOptionalSummaryProvider, + "MSVC STL/libstd++ std::optional summary provider", + "^std::optional<.+>(( )?&)?$", stl_summary_flags, true); } static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp index c041f39022d10..7fc6eb55d4e3e 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp @@ -9,6 +9,7 @@ #include "Generic.h" #include "LibCxx.h" #include "LibStdcpp.h" +#include "MsvcStl.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Target/Target.h" @@ -32,6 +33,7 @@ class GenericOptionalFrontend : public SyntheticChildrenFrontEnd { enum class StdLib { LibCxx, LibStdcpp, + MsvcStl, }; GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib); @@ -77,7 +79,8 @@ lldb::ChildCacheState GenericOptionalFrontend::Update() { else if (m_stdlib == StdLib::LibStdcpp) { if (ValueObjectSP payload = m_backend.GetChildMemberWithName("_M_payload")) engaged_sp = payload->GetChildMemberWithName("_M_engaged"); - } + } else if (m_stdlib == StdLib::MsvcStl) + engaged_sp = m_backend.GetChildMemberWithName("_Has_value"); if (!engaged_sp) return lldb::ChildCacheState::eRefetch; @@ -114,7 +117,12 @@ ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(uint32_t _idx) { ValueObjectSP candidate = val_sp->GetChildMemberWithName("_M_value"); if (candidate) val_sp = candidate; - } + } else if (m_stdlib == StdLib::MsvcStl) + // Same issue as with LibCxx + val_sp = m_backend.GetChildMemberWithName("_Has_value") + ->GetParent() + ->GetChildAtIndex(0) + ->GetChildMemberWithName("_Value"); if (!val_sp) return ValueObjectSP(); @@ -143,3 +151,17 @@ SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator( GenericOptionalFrontend::StdLib::LibCxx); return nullptr; } + +bool formatters::IsMsvcStlOptional(ValueObject &valobj) { + if (auto valobj_sp = valobj.GetNonSyntheticValue()) + return valobj_sp->GetChildMemberWithName("_Has_value") != nullptr; + return false; +} + +SyntheticChildrenFrontEnd *formatters::MsvcStlOptionalSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new GenericOptionalFrontend( + *valobj_sp, GenericOptionalFrontend::StdLib::MsvcStl); + return nullptr; +} diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h index 0f3db4b50eeaf..c08eecfdecee7 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h @@ -65,6 +65,12 @@ SyntheticChildrenFrontEnd * MsvcStlListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp); +// MSVC STL std::optional<> +bool IsMsvcStlOptional(ValueObject &valobj); +SyntheticChildrenFrontEnd * +MsvcStlOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp); + } // namespace formatters } // namespace lldb_private diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py index 99d79a9f125b1..dd800feb967a2 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py @@ -3,12 +3,10 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -USE_LIBSTDCPP = "USE_LIBSTDCPP" -USE_LIBCPP = "USE_LIBCPP" - class GenericOptionalDataFormatterTestCase(TestBase): - def do_test_with_run_command(self, stdlib_type): + + def do_test_with_run_command(self): """Test that that file and class static variables display correctly.""" # This is the function to remove the custom formats in order to have a @@ -21,7 +19,6 @@ def cleanup(): self.addTearDownHook(cleanup) - self.build(dictionary={stdlib_type: "1"}) self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) bkpt = self.target().FindBreakpointByID( @@ -100,7 +97,8 @@ def cleanup(): ## We are skipping gcc version less that 5.1 since this test requires -std=c++17 @skipIf(compiler="gcc", compiler_version=["<", "5.1"]) def test_with_run_command_libcpp(self): - self.do_test_with_run_command(USE_LIBCPP) + self.build(dictionary={"USE_LIBCPP": 1}) + self.do_test_with_run_command() @add_test_categories(["libstdcxx"]) ## Clang 7.0 is the oldest Clang that can reliably parse newer libc++ versions @@ -109,4 +107,11 @@ def test_with_run_command_libcpp(self): ## We are skipping gcc version less that 5.1 since this test requires -std=c++17 @skipIf(compiler="gcc", compiler_version=["<", "5.1"]) def test_with_run_command_libstdcpp(self): - self.do_test_with_run_command(USE_LIBSTDCPP) + self.build(dictionary={"USE_LIBSTDCPP": 1}) + self.do_test_with_run_command() + + @add_test_categories(["msvcstl"]) + def test_with_run_command_msvcstl(self): + # No flags, because the "msvcstl" category checks that the MSVC STL is used by default. + self.build() + self.do_test_with_run_command() `````````` </details> https://github.com/llvm/llvm-project/pull/149545 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits