Author: Danil Stefaniuc Date: 2021-10-26T14:49:50-07:00 New Revision: 566bfbb740bb0ffef827ce983d7aa899236fcb88
URL: https://github.com/llvm/llvm-project/commit/566bfbb740bb0ffef827ce983d7aa899236fcb88 DIFF: https://github.com/llvm/llvm-project/commit/566bfbb740bb0ffef827ce983d7aa899236fcb88.diff LOG: [formatters] Add a libstdcpp formatter for bitset and unify tests across stdlibs This diff adds a data formatter for libstdcpp's bitset. Besides, it unifies the tests for bitset for libcxx and libstdcpp for maintainability. Reviewed By: wallace Differential Revision: https://reviews.llvm.org/D112180 Added: lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/Makefile lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/TestDataFormatterGenericBitset.py lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/main.cpp Modified: lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h Removed: lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp ################################################################################ diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 2a541a9e528cd..eb53649ab0ff9 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -3,9 +3,9 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN CPlusPlusLanguage.cpp CPlusPlusNameParser.cpp CxxStringTypes.cpp + GenericBitset.cpp LibCxx.cpp LibCxxAtomic.cpp - LibCxxBitset.cpp LibCxxInitializerList.cpp LibCxxList.cpp LibCxxMap.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 4ef35eefaf32f..240bbecfc2c53 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -895,6 +895,8 @@ static void LoadLibStdcppFormatters(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(); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::vector<.+>(( )?&)?$"), @@ -913,6 +915,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(true); + cpp_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression("^std::bitset<.+>(( )?&)?$"), + TypeSummaryImplSP( + new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::vector<.+>(( )?&)?$"), TypeSummaryImplSP( @@ -959,6 +965,12 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic( + cpp_category_sp, + lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator, + "std::bitset synthetic child", ConstString("^std::bitset<.+>(( )?&)?$"), + stl_deref_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibStdcppUniquePointerSummaryProvider, "libstdc++ std::unique_ptr summary provider", diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp similarity index 71% rename from lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp rename to lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index e5b868fc0fce0..fc8255983436c 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -1,4 +1,4 @@ -//===-- LibCxxBitset.cpp --------------------------------------------------===// +//===-- GenericBitset.cpp //-----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "LibCxx.h" +#include "LibStdcpp.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Target/Target.h" @@ -16,9 +17,15 @@ using namespace lldb_private; namespace { -class BitsetFrontEnd : public SyntheticChildrenFrontEnd { +/// This class can be used for handling bitsets from both libcxx and libstdcpp. +class GenericBitsetFrontEnd : public SyntheticChildrenFrontEnd { public: - BitsetFrontEnd(ValueObject &valobj); + enum class StdLib { + LibCxx, + LibStdcpp, + }; + + GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib); size_t GetIndexOfChildWithName(ConstString name) override { return formatters::ExtractIndexFromString(name.GetCString()); @@ -30,6 +37,8 @@ class BitsetFrontEnd : public SyntheticChildrenFrontEnd { ValueObjectSP GetChildAtIndex(size_t idx) override; private: + ConstString GetDataContainerMemberName(); + // The lifetime of a ValueObject and all its derivative ValueObjects // (children, clones, etc.) is managed by a ClusterManager. These // objects are only destroyed when every shared pointer to any of them @@ -38,15 +47,16 @@ class BitsetFrontEnd : public SyntheticChildrenFrontEnd { // Value objects created from raw data (i.e. in a diff erent cluster) must // be referenced via shared pointer to keep them alive, however. std::vector<ValueObjectSP> m_elements; - ValueObject* m_first = nullptr; + ValueObject *m_first = nullptr; CompilerType m_bool_type; ByteOrder m_byte_order = eByteOrderInvalid; uint8_t m_byte_size = 0; + StdLib m_stdlib; }; } // namespace -BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) - : SyntheticChildrenFrontEnd(valobj) { +GenericBitsetFrontEnd::GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib) + : SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) { m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool); if (auto target_sp = m_backend.GetTargetSP()) { m_byte_order = target_sp->GetArchitecture().GetByteOrder(); @@ -55,7 +65,16 @@ BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) } } -bool BitsetFrontEnd::Update() { +ConstString GenericBitsetFrontEnd::GetDataContainerMemberName() { + switch (m_stdlib) { + case StdLib::LibCxx: + return ConstString("__first_"); + case StdLib::LibStdcpp: + return ConstString("_M_w"); + } +} + +bool GenericBitsetFrontEnd::Update() { m_elements.clear(); m_first = nullptr; @@ -65,16 +84,17 @@ bool BitsetFrontEnd::Update() { size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay(); size_t size = 0; + if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) size = arg->value.getLimitedValue(capping_size); m_elements.assign(size, ValueObjectSP()); - - m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true).get(); + m_first = m_backend.GetChildMemberWithName(GetDataContainerMemberName(), true) + .get(); return false; } -ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { +ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_elements.size() || !m_first) return ValueObjectSP(); @@ -112,9 +132,18 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { return m_elements[idx]; } +SyntheticChildrenFrontEnd *formatters::LibStdcppBitsetSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new GenericBitsetFrontEnd(*valobj_sp, + GenericBitsetFrontEnd::StdLib::LibStdcpp); + return nullptr; +} + SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { if (valobj_sp) - return new BitsetFrontEnd(*valobj_sp); + return new GenericBitsetFrontEnd(*valobj_sp, + GenericBitsetFrontEnd::StdLib::LibCxx); return nullptr; } diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h index 9e41aa0ffc011..b6f9c469fedda 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h @@ -41,6 +41,10 @@ SyntheticChildrenFrontEnd * LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +SyntheticChildrenFrontEnd * +LibStdcppBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + SyntheticChildrenFrontEnd * LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/Makefile similarity index 75% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/Makefile index 680e1abfbef58..99998b20bcb05 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/Makefile @@ -1,4 +1,3 @@ CXX_SOURCES := main.cpp -USE_LIBCPP := 1 include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/TestDataFormatterGenericBitset.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/TestDataFormatterGenericBitset.py new file mode 100644 index 0000000000000..7dac8ec06c0b8 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/TestDataFormatterGenericBitset.py @@ -0,0 +1,93 @@ +""" +Test lldb data formatter subsystem for bitset for libcxx and libstdcpp. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +USE_LIBSTDCPP = "USE_LIBSTDCPP" +USE_LIBCPP = "USE_LIBCPP" +VALUE = "VALUE" +REFERENCE = "REFERENCE" +POINTER = "POINTER" + +class GenericBitsetDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + primes = [1]*300 + primes[0] = primes[1] = 0 + for i in range(2, len(primes)): + for j in range(2*i, len(primes), i): + primes[j] = 0 + self.primes = primes + + def getBitsetVariant(self, size, variant): + if variant == VALUE: + return "std::bitset<" + str(size) + ">" + elif variant == REFERENCE: + return "std::bitset<" + str(size) + "> &" + elif variant == POINTER: + return "std::bitset<" + str(size) + "> *" + return "" + + def check(self, name, size, variant): + var = self.frame().FindVariable(name) + self.assertTrue(var.IsValid()) + self.assertEqual(var.GetNumChildren(), size) + children = [] + for i in range(size): + child = var.GetChildAtIndex(i) + children.append(ValueCheck(value=str(bool(child.GetValueAsUnsigned())).lower())) + self.assertEqual(child.GetValueAsUnsigned(), self.primes[i], + "variable: %s, index: %d"%(name, size)) + self.expect_var_path(name,type=self.getBitsetVariant(size,variant),children=children) + + def do_test_value(self, stdlib_type): + """Test that std::bitset is displayed correctly""" + self.build(dictionary={stdlib_type: "1"}) + + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.check("empty", 0, VALUE) + self.check("small", 13, VALUE) + self.check("large", 70, VALUE) + + @add_test_categories(["libstdcxx"]) + def test_value_libstdcpp(self): + self.do_test_value(USE_LIBSTDCPP) + + @add_test_categories(["libc++"]) + def test_value_libcpp(self): + self.do_test_value(USE_LIBCPP) + + def do_test_ptr_and_ref(self, stdlib_type): + """Test that ref and ptr to std::bitset is displayed correctly""" + self.build(dictionary={stdlib_type: "1"}) + + (_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Check ref and ptr', + lldb.SBFileSpec("main.cpp", False)) + + self.check("ref", 13, REFERENCE) + self.check("ptr", 13, POINTER) + + lldbutil.continue_to_breakpoint(process, bkpt) + + self.check("ref", 70, REFERENCE) + self.check("ptr", 70, POINTER) + + @add_test_categories(["libstdcxx"]) + def test_ptr_and_ref_libstdcpp(self): + self.do_test_ptr_and_ref(USE_LIBSTDCPP) + + @add_test_categories(["libc++"]) + def test_ptr_and_ref_libcpp(self): + self.do_test_ptr_and_ref(USE_LIBCPP) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/main.cpp similarity index 67% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/main.cpp index 2a1532adb4b29..c7be1c5c71337 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/bitset/main.cpp @@ -1,27 +1,26 @@ #include <bitset> #include <stdio.h> -template<std::size_t N> -void fill(std::bitset<N> &b) { +template <std::size_t N> void fill(std::bitset<N> &b) { b.set(); b[0] = b[1] = false; for (std::size_t i = 2; i < N; ++i) { - for (std::size_t j = 2*i; j < N; j+=i) + for (std::size_t j = 2 * i; j < N; j += i) b[j] = false; } } -template<std::size_t N> +template <std::size_t N> void by_ref_and_ptr(std::bitset<N> &ref, std::bitset<N> *ptr) { - // Check ref and ptr - return; + // Check ref and ptr + return; } int main() { std::bitset<0> empty; std::bitset<13> small; fill(small); - std::bitset<200> large; + std::bitset<70> large; fill(large); by_ref_and_ptr(small, &small); // break here by_ref_and_ptr(large, &large); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py deleted file mode 100644 index 26f1972257bdd..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Test lldb data formatter subsystem. -""" - - - -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestDataFormatterLibcxxBitset(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - TestBase.setUp(self) - - primes = [1]*300 - primes[0] = primes[1] = 0 - for i in range(2, len(primes)): - for j in range(2*i, len(primes), i): - primes[j] = 0 - self.primes = primes - - def check(self, name, size): - var = self.frame().FindVariable(name) - self.assertTrue(var.IsValid()) - self.assertEqual(var.GetNumChildren(), size) - for i in range(size): - child = var.GetChildAtIndex(i) - self.assertEqual(child.GetValueAsUnsigned(), self.primes[i], - "variable: %s, index: %d"%(name, size)) - - @add_test_categories(["libc++"]) - def test_value(self): - """Test that std::bitset is displayed correctly""" - self.build() - lldbutil.run_to_source_breakpoint(self, '// break here', - lldb.SBFileSpec("main.cpp", False)) - - self.check("empty", 0) - self.check("small", 13) - self.check("large", 200) - - @add_test_categories(["libc++"]) - def test_ptr_and_ref(self): - """Test that ref and ptr to std::bitset is displayed correctly""" - self.build() - (_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, - 'Check ref and ptr', - lldb.SBFileSpec("main.cpp", False)) - - self.check("ref", 13) - self.check("ptr", 13) - - lldbutil.continue_to_breakpoint(process, bkpt) - - self.check("ref", 200) - self.check("ptr", 200) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits