-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[LLDB] Add formatters for MSVC STL std::optional #149545
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
Conversation
@llvm/pr-subscribers-lldb Author: nerix (Nerixyz) ChangesAdds synthetic children for Towards #24834. Full diff: https://github.com/llvm/llvm-project/pull/149545.diff 4 Files Affected:
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()
|
✅ With the latest revision this PR passed the Python code formatter. |
9cb391e
to
927e9c7
Compare
@@ -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; |
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.
Lets move this down where we actually use it
Adds synthetic children for
std::optional
from MSVC's STL. Most of the machinery forstd::optional
is already there.Towards #24834.