-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[LLDB] Add formatters for MSVC STL std::vector #147538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-lldb Author: nerix (Nerixyz) ChangesThis adds synthetic child providers for The structure of a Towards #24834. Patch is 20.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/147538.diff 7 Files Affected:
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index bbfc31a722f27..6869e4b56ebee 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -33,6 +33,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibStdcppTuple.cpp
LibStdcppUniquePointer.cpp
MsvcStl.cpp
+ MsvcStlVector.cpp
MSVCUndecoratedNameParser.cpp
LINK_COMPONENTS
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 17963c0273ba8..5a9fcba05ddbc 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1404,7 +1404,7 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
stl_deref_flags.SetFrontEndWantsDereference();
cpp_category_sp->AddTypeSynthetic(
- "^std::(__debug::)?vector<.+>(( )?&)?$", eFormatterMatchRegex,
+ "^std::__debug::vector<.+>(( )?&)?$", eFormatterMatchRegex,
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_synth_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
@@ -1465,10 +1465,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libstdc++ std::bitset summary provider",
"^std::(__debug::)?bitset<.+>(( )?&)?$", stl_summary_flags, true);
- AddCXXSummary(
- cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
- "libstdc++ std::vector summary provider",
- "^std::(__debug::)?vector<.+>(( )?&)?$", stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::ContainerSizeSummaryProvider,
+ "libstdc++ std::__debug::vector summary provider",
+ "^std::__debug::vector<.+>(( )?&)?$", stl_summary_flags, true);
AddCXXSummary(
cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
@@ -1611,6 +1611,10 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
.SetDontShowValue(false)
.SetShowMembersOneLiner(false)
.SetHideItemNames(false);
+ SyntheticChildren::Flags stl_synth_flags;
+ stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
+ false);
+
using StringElementType = StringPrinter::StringElementType;
RegisterStdStringSummaryProvider(
@@ -1636,6 +1640,28 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
return LibStdcppStringSummaryProvider(valobj, stream, options);
},
"MSVC STL/libstdc++ std::wstring summary provider"));
+
+ stl_summary_flags.SetDontShowChildren(false);
+ stl_summary_flags.SetSkipPointers(false);
+
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::ContainerSizeSummaryProvider,
+ "MSVC/libstdc++ std::vector summary provider",
+ "^std::vector<.+>(( )?&)?$", stl_summary_flags, true);
+ AddCXXSynthetic(
+ cpp_category_sp,
+ [](CXXSyntheticChildren *,
+ ValueObjectSP valobj_sp) -> SyntheticChildrenFrontEnd * {
+ if (!valobj_sp)
+ return nullptr;
+ if (auto *msvc = MsvcStlVectorSyntheticFrontEndCreator(valobj_sp))
+ return msvc;
+ return new ScriptedSyntheticChildren::FrontEnd(
+ "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider",
+ *valobj_sp);
+ },
+ "MSVC/libstdc++ std::vector synthetic provider",
+ "^std::vector<.+>(( )?&)?$", stl_synth_flags, true);
}
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
index e4ed923033aa7..78b9e56d65e28 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
@@ -29,6 +29,9 @@ bool MsvcStlWStringSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // VC 2015+ std::wstring
+lldb_private::SyntheticChildrenFrontEnd *
+MsvcStlVectorSyntheticFrontEndCreator(lldb::ValueObjectSP valobj_sp);
+
} // namespace formatters
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVector.cpp
new file mode 100644
index 0000000000000..f845aa30ebe1a
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVector.cpp
@@ -0,0 +1,295 @@
+//===-- MsvcStlVector.cpp -------------------------------------------------===//
+//
+// 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 "MsvcStl.h"
+
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+using namespace lldb;
+
+namespace lldb_private {
+namespace formatters {
+
+class MsvcStlVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ MsvcStlVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+ lldb::ChildCacheState Update() override;
+
+ llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
+
+private:
+ ValueObject *m_start = nullptr;
+ ValueObject *m_finish = nullptr;
+ CompilerType m_element_type;
+ uint32_t m_element_size = 0;
+};
+
+class MsvcStlVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ MsvcStlVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+ lldb::ChildCacheState Update() override;
+
+ llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
+
+private:
+ CompilerType m_bool_type;
+ ExecutionContextRef m_exe_ctx_ref;
+ uint64_t m_count = 0;
+ uint64_t m_element_bit_size = 0;
+ lldb::addr_t m_base_data_address = 0;
+ std::map<size_t, lldb::ValueObjectSP> m_children;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::MsvcStlVectorSyntheticFrontEnd::
+ MsvcStlVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
+ if (valobj_sp)
+ Update();
+}
+
+llvm::Expected<uint32_t> lldb_private::formatters::
+ MsvcStlVectorSyntheticFrontEnd::CalculateNumChildren() {
+ if (!m_start || !m_finish)
+ return llvm::createStringError(
+ "Failed to determine start/end of vector data.");
+
+ uint64_t start_val = m_start->GetValueAsUnsigned(0);
+ uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
+
+ // A default-initialized empty vector.
+ if (start_val == 0 && finish_val == 0)
+ return 0;
+
+ if (start_val == 0)
+ return llvm::createStringError("Invalid value for start of vector.");
+
+ if (finish_val == 0)
+ return llvm::createStringError("Invalid value for end of vector.");
+
+ if (start_val > finish_val)
+ return llvm::createStringError(
+ "Start of vector data begins after end pointer.");
+
+ size_t num_children = (finish_val - start_val);
+ if (num_children % m_element_size)
+ return llvm::createStringError("Size not multiple of element size.");
+
+ return num_children / m_element_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::MsvcStlVectorSyntheticFrontEnd::GetChildAtIndex(
+ uint32_t idx) {
+ if (!m_start || !m_finish)
+ return lldb::ValueObjectSP();
+
+ uint64_t offset = idx * m_element_size;
+ offset = offset + m_start->GetValueAsUnsigned(0);
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return CreateValueObjectFromAddress(name.GetString(), offset,
+ m_backend.GetExecutionContextRef(),
+ m_element_type);
+}
+
+lldb::ChildCacheState
+lldb_private::formatters::MsvcStlVectorSyntheticFrontEnd::Update() {
+ m_start = m_finish = nullptr;
+ ValueObjectSP data_sp(m_backend.GetChildAtNamePath({"_Mypair", "_Myval2"}));
+
+ if (!data_sp)
+ return lldb::ChildCacheState::eRefetch;
+
+ m_start = data_sp->GetChildMemberWithName("_Myfirst").get();
+ m_finish = data_sp->GetChildMemberWithName("_Mylast").get();
+ if (!m_start || !m_finish)
+ return lldb::ChildCacheState::eRefetch;
+
+ m_element_type = m_start->GetCompilerType().GetPointeeType();
+ llvm::Expected<uint64_t> size_or_err = m_element_type.GetByteSize(nullptr);
+ if (size_or_err)
+ m_element_size = *size_or_err;
+ else
+ LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), size_or_err.takeError(),
+ "{0}");
+
+ return lldb::ChildCacheState::eRefetch;
+}
+
+llvm::Expected<size_t> lldb_private::formatters::
+ MsvcStlVectorSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
+ if (!m_start || !m_finish)
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ auto optional_idx = ExtractIndexFromString(name.GetCString());
+ if (!optional_idx) {
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ }
+ return *optional_idx;
+}
+
+lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::
+ MsvcStlVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_bool_type(), m_exe_ctx_ref(),
+ m_children() {
+ if (valobj_sp) {
+ Update();
+ m_bool_type =
+ valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
+ }
+}
+
+llvm::Expected<uint32_t> lldb_private::formatters::
+ MsvcStlVectorBoolSyntheticFrontEnd::CalculateNumChildren() {
+ return m_count;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::GetChildAtIndex(
+ uint32_t idx) {
+ auto iter = m_children.find(idx), end = m_children.end();
+ if (iter != end)
+ return iter->second;
+ if (idx >= m_count)
+ return {};
+ if (m_base_data_address == 0 || m_count == 0)
+ return {};
+ if (!m_bool_type)
+ return {};
+
+ // The vector<bool> is represented as a sequence of `int`s.
+ // The size of an `int` is in `m_element_bit_size` (most often 32b).
+ // To access the element at index `i`:
+ // (bool)((data_address[i / bit_size] >> (i % bit_size)) & 1)
+
+ // int *byte_location = &data_address[i / bit_size]
+ size_t byte_idx = (idx / m_element_bit_size) * (m_element_bit_size / 8);
+ lldb::addr_t byte_location = m_base_data_address + byte_idx;
+
+ ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
+ if (!process_sp)
+ return {};
+ Status err;
+ Scalar scalar;
+ size_t bytes_read = process_sp->ReadScalarIntegerFromMemory(
+ byte_location, m_element_bit_size / 8, false, scalar, err);
+ if (err.Fail() || bytes_read == 0 || !scalar.IsValid())
+ return {};
+
+ size_t bit_index = idx % m_element_bit_size;
+ bool bit_set = scalar.GetAPSInt()[bit_index];
+ std::optional<uint64_t> size =
+ llvm::expectedToOptional(m_bool_type.GetByteSize(nullptr));
+ if (!size)
+ return {};
+ WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
+ if (bit_set && buffer_sp && buffer_sp->GetBytes()) {
+ // regardless of endianness, anything non-zero is true
+ *(buffer_sp->GetBytes()) = 1;
+ }
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ ValueObjectSP retval_sp(CreateValueObjectFromData(
+ name.GetString(),
+ DataExtractor(buffer_sp, process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize()),
+ m_exe_ctx_ref, m_bool_type));
+ if (retval_sp)
+ m_children[idx] = retval_sp;
+ return retval_sp;
+}
+
+lldb::ChildCacheState
+lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::Update() {
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return lldb::ChildCacheState::eRefetch;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+
+ ValueObjectSP size_sp = valobj_sp->GetChildMemberWithName("_Mysize");
+ if (!size_sp)
+ return lldb::ChildCacheState::eRefetch;
+ m_count = size_sp->GetValueAsUnsigned(0);
+ if (!m_count)
+ return lldb::ChildCacheState::eReuse;
+
+ ValueObjectSP begin_sp(valobj_sp->GetChildAtNamePath(
+ {"_Myvec", "_Mypair", "_Myval2", "_Myfirst"}));
+ if (!begin_sp) {
+ m_count = 0;
+ return lldb::ChildCacheState::eRefetch;
+ }
+
+ // FIXME: the STL exposes _EEN_VBITS as a constant - it should be used instead
+ CompilerType begin_ty = begin_sp->GetCompilerType().GetPointeeType();
+ if (!begin_ty.IsValid())
+ return lldb::ChildCacheState::eRefetch;
+ llvm::Expected<uint64_t> bit_size = begin_ty.GetBitSize(nullptr);
+ if (!bit_size)
+ return lldb::ChildCacheState::eRefetch;
+ m_element_bit_size = *bit_size;
+
+ m_base_data_address = begin_sp->GetValueAsUnsigned(0);
+ if (!m_base_data_address) {
+ m_count = 0;
+ return lldb::ChildCacheState::eRefetch;
+ }
+ return lldb::ChildCacheState::eRefetch;
+}
+
+llvm::Expected<size_t>
+lldb_private::formatters::MsvcStlVectorBoolSyntheticFrontEnd::
+ GetIndexOfChildWithName(ConstString name) {
+ if (!m_count || !m_base_data_address)
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ auto optional_idx = ExtractIndexFromString(name.AsCString());
+ if (!optional_idx) {
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ }
+ uint32_t idx = *optional_idx;
+ if (idx >= CalculateNumChildrenIgnoringErrors())
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ return idx;
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::MsvcStlVectorSyntheticFrontEndCreator(
+ lldb::ValueObjectSP valobj_sp) {
+ CompilerType type = valobj_sp->GetCompilerType();
+ if (!type.IsValid())
+ return nullptr;
+
+ std::vector<uint32_t> indexes;
+ // vector<T>
+ if (type.GetIndexOfChildMemberWithName("_Mypair", true, indexes) > 0)
+ return new MsvcStlVectorSyntheticFrontEnd(valobj_sp);
+ // vector<bool>
+ if (type.GetIndexOfChildMemberWithName("_Myvec", true, indexes) > 0)
+ return new MsvcStlVectorBoolSyntheticFrontEnd(valobj_sp);
+
+ return nullptr;
+}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py
index 56c86d1edde25..b4d6ce15b1af0 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py
@@ -47,7 +47,7 @@ def cleanup():
self.expect(
"frame variable -A vBool",
substrs=[
- "size=49",
+ "size=73",
"[0] = false",
"[1] = true",
"[18] = false",
@@ -55,13 +55,20 @@ def cleanup():
"[36] = false",
"[47] = true",
"[48] = true",
+ "[49] = true",
+ "[50] = false",
+ "[56] = false",
+ "[65] = true",
+ "[70] = false",
+ "[71] = true",
+ "[72] = true",
],
)
self.expect(
"expr -A -- vBool",
substrs=[
- "size=49",
+ "size=73",
"[0] = false",
"[1] = true",
"[18] = false",
@@ -69,6 +76,13 @@ def cleanup():
"[36] = false",
"[47] = true",
"[48] = true",
+ "[49] = true",
+ "[50] = false",
+ "[56] = false",
+ "[65] = true",
+ "[70] = false",
+ "[71] = true",
+ "[72] = true",
],
)
@@ -88,3 +102,9 @@ def test_libstdcxx_debug(self):
dictionary={"USE_LIBSTDCPP": 1, "CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
)
self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_libstdcxx(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build(dictionary={})
+ self.do_test()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/main.cpp
index 22fc6c89ca8a2..2c54166ace7cc 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/main.cpp
@@ -1,10 +1,10 @@
#include <cstdio>
-#include <string>
#include <vector>
int main() {
std::vector<bool> vBool;
+ // 0..=7
vBool.push_back(false);
vBool.push_back(true);
vBool.push_back(false);
@@ -14,6 +14,7 @@ int main() {
vBool.push_back(false);
vBool.push_back(true);
+ // 8..=15
vBool.push_back(false);
vBool.push_back(true);
vBool.push_back(false);
@@ -23,6 +24,7 @@ int main() {
vBool.push_back(false);
vBool.push_back(true);
+ // 16..=23
vBool.push_back(false);
vBool.push_back(true);
vBool.push_back(false);
@@ -32,6 +34,7 @@ int main() {
vBool.push_back(false);
vBool.push_back(true);
+ // 24..=31
vBool.push_back(false);
vBool.push_back(true);
vBool.push_back(false);
@@ -41,6 +44,7 @@ int main() {
vBool.push_back(false);
vBool.push_back(true);
+ // 32..=39
vBool.push_back(false);
vBool.push_back(true);
vBool.push_back(false);
@@ -50,6 +54,7 @@ int main() {
vBool.push_back(false);
vBool.push_back(true);
+ // 40..=47
vBool.push_back(false);
vBool.push_back(true);
vBool.push_back(false);
@@ -58,6 +63,38 @@ int main() {
vBool.push_back(true);
vBool.push_back(false);
vBool.push_back(true);
+
+ // 48..=55
+ vBool.push_back(true);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+
+ // 56..=63
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+
+ // 64..=71
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+ vBool.push_back(true);
+ vBool.push_back(true);
+ vBool.push_back(false);
+ vBool.push_back(true);
+
+ // 72
vBool.push_back(true);
std::puts("// Set break point at this line.");
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py
index ba8b10450f4fc..353f5fe4dcbad 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py
@@ -184,6 +184,12 @@ def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test()
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build(dictionary={})
+ self.do_test()
+
def do_test_ref_and_ptr(self):
"""Test that that file and class static variables display correctly."""
(self.target, process, threa...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally seems reasonable. Just left some preliminary questions
Will revisit later
vBool.push_back(true); | ||
vBool.push_back(true); | ||
vBool.push_back(false); | ||
vBool.push_back(true); | ||
vBool.push_back(false); | ||
vBool.push_back(true); | ||
vBool.push_back(false); | ||
vBool.push_back(true); | ||
|
||
// 56..=63 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason these new test-cases were added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should've mentioned this. While I was testing, I made the mistake of calculating the byte index as (idx / m_element_bit_size) * 8
. For reasons unknown to me, this made the tests pass (but it is wrong). I added the other elements to make sure that at least three elements of the underlying vector need to be accessed (to ensure that the calculation is actually correct).
@add_test_categories(["msvcstl"]) | ||
def test_libstdcxx(self): | ||
# No flags, because the "msvcstl" category checks that the MSVC STL is used by default. | ||
self.build(dictionary={}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.build(dictionary={}) | |
self.build() |
if (type.GetIndexOfChildMemberWithName("_Mypair", true, indexes) > 0) | ||
return new MsvcStlVectorSyntheticFrontEnd(valobj_sp); | ||
// vector<bool> | ||
if (type.GetIndexOfChildMemberWithName("_Myvec", true, indexes) > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we check the template argument type to distinguish bool vs. non-bool vector? Is it because PDB strips template info?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it because PDB strips template info?
This. I don't know how this is done in DWARF exactly, but my thought was that PDB could use the demangling to add template parameters(?).
This adds synthetic child providers for
std::vector<T>
andstd::vector<bool>
for MSVC's STL.The structure of a
std::vector<T>
is relatively similar to libc++'s implementation that uses__begin
and__end
.std::vector<bool>
is different. It's astd::vector<unsigned int>
wrapper instead ofstd::vector<uint8_t>
. This makes the calculation slightly less simple. I put a comment in theGetChildAtIndex
to make this clear.std::vector<T>
std::vector<bool>
Towards #24834.