[Lldb-commits] [lldb] 566bfbb - [formatters] Add a libstdcpp formatter for bitset and unify tests across stdlibs
Walter Erquinigo via lldb-commits
lldb-commits at lists.llvm.org
Tue Oct 26 14:49:57 PDT 2021
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)
More information about the lldb-commits
mailing list