forked from OSchip/llvm-project
Unify libstdcpp and libcxx formatters for `std::optional`
Reviewed By: wallace Differential Revision: https://reviews.llvm.org/D115178
This commit is contained in:
parent
afdec434d4
commit
cfb0750891
|
@ -4,12 +4,12 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
|
|||
CPlusPlusNameParser.cpp
|
||||
CxxStringTypes.cpp
|
||||
GenericBitset.cpp
|
||||
GenericOptional.cpp
|
||||
LibCxx.cpp
|
||||
LibCxxAtomic.cpp
|
||||
LibCxxInitializerList.cpp
|
||||
LibCxxList.cpp
|
||||
LibCxxMap.cpp
|
||||
LibCxxOptional.cpp
|
||||
LibCxxQueue.cpp
|
||||
LibCxxTuple.cpp
|
||||
LibCxxUnorderedMap.cpp
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "BlockPointer.h"
|
||||
#include "CPlusPlusNameParser.h"
|
||||
#include "CxxStringTypes.h"
|
||||
#include "Generic.h"
|
||||
#include "LibCxx.h"
|
||||
#include "LibCxxAtomic.h"
|
||||
#include "LibCxxVariant.h"
|
||||
|
@ -655,7 +656,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"libc++ std::tuple synthetic children",
|
||||
ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
|
||||
stl_synth_flags, true);
|
||||
AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
|
||||
AddCXXSynthetic(cpp_category_sp, LibcxxOptionalSyntheticFrontEndCreator,
|
||||
"libc++ std::optional synthetic children",
|
||||
ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
|
||||
stl_synth_flags, true);
|
||||
|
@ -772,7 +773,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
ConstString("^std::__[[:alnum:]]+::atomic<.+>$"),
|
||||
stl_summary_flags, true);
|
||||
AddCXXSummary(cpp_category_sp,
|
||||
lldb_private::formatters::LibcxxOptionalSummaryProvider,
|
||||
lldb_private::formatters::GenericOptionalSummaryProvider,
|
||||
"libc++ std::optional summary provider",
|
||||
ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
|
||||
stl_summary_flags, true);
|
||||
|
@ -918,11 +919,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
||||
stl_deref_flags,
|
||||
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
|
||||
cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
|
||||
RegularExpression("^std::optional<.+>(( )?&)?$"),
|
||||
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
||||
stl_synth_flags,
|
||||
"lldb.formatters.cpp.gnu_libstdcpp.StdOptionalSynthProvider")));
|
||||
cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
|
||||
RegularExpression("^std::multiset<.+> >(( )?&)?$"),
|
||||
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
||||
|
@ -946,11 +942,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
|
||||
stl_summary_flags.SetDontShowChildren(false);
|
||||
stl_summary_flags.SetSkipPointers(false);
|
||||
cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
|
||||
RegularExpression("^std::optional<.+>(( )?&)?$"),
|
||||
TypeSummaryImplSP(new ScriptSummaryFormat(
|
||||
stl_summary_flags,
|
||||
"lldb.formatters.cpp.gnu_libstdcpp.StdOptionalSummaryProvider")));
|
||||
cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
|
||||
RegularExpression("^std::bitset<.+>(( )?&)?$"),
|
||||
TypeSummaryImplSP(
|
||||
|
@ -1031,6 +1022,12 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"std::bitset synthetic child", ConstString("^std::bitset<.+>(( )?&)?$"),
|
||||
stl_deref_flags, true);
|
||||
|
||||
AddCXXSynthetic(
|
||||
cpp_category_sp,
|
||||
lldb_private::formatters::LibStdcppOptionalSyntheticFrontEndCreator,
|
||||
"std::optional synthetic child",
|
||||
ConstString("^std::optional<.+>(( )?&)?$"), stl_deref_flags, true);
|
||||
|
||||
AddCXXSummary(cpp_category_sp,
|
||||
lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
|
||||
"libstdc++ std::unique_ptr summary provider",
|
||||
|
@ -1046,6 +1043,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"libstdc++ std::weak_ptr summary provider",
|
||||
ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
|
||||
true);
|
||||
AddCXXSummary(
|
||||
cpp_category_sp, lldb_private::formatters::GenericOptionalSummaryProvider,
|
||||
"libstd++ std::optional summary provider",
|
||||
ConstString("^std::optional<.+>(( )?&)?$"), stl_summary_flags, true);
|
||||
}
|
||||
|
||||
static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
//===-- LibCxx.h -----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_GENERIC_H
|
||||
#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_GENERIC_H
|
||||
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/DataFormatters/TypeSummary.h"
|
||||
#include "lldb/Utility/Stream.h"
|
||||
|
||||
namespace lldb_private {
|
||||
namespace formatters {
|
||||
|
||||
bool GenericOptionalSummaryProvider(ValueObject &valobj, Stream &stream,
|
||||
const TypeSummaryOptions &options);
|
||||
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_GENERIC_H
|
|
@ -0,0 +1,139 @@
|
|||
//===-- GenericOptional.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 "Generic.h"
|
||||
#include "LibCxx.h"
|
||||
#include "LibStdcpp.h"
|
||||
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
|
||||
#include "lldb/DataFormatters/FormattersHelpers.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
bool lldb_private::formatters::GenericOptionalSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
||||
stream.Printf(" Has Value=%s ",
|
||||
valobj.GetNumChildren() == 0 ? "false" : "true");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Synthetic Children Provider
|
||||
namespace {
|
||||
|
||||
class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
enum class StdLib {
|
||||
LibCxx,
|
||||
LibStdcpp,
|
||||
};
|
||||
|
||||
GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib);
|
||||
|
||||
size_t GetIndexOfChildWithName(ConstString name) override {
|
||||
return formatters::ExtractIndexFromString(name.GetCString());
|
||||
}
|
||||
|
||||
bool MightHaveChildren() override { return true; }
|
||||
size_t CalculateNumChildren() override { return m_has_value ? 1U : 0U; }
|
||||
|
||||
ValueObjectSP GetChildAtIndex(size_t idx) override;
|
||||
bool Update() override;
|
||||
|
||||
private:
|
||||
bool m_has_value = false;
|
||||
StdLib m_stdlib;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj,
|
||||
StdLib stdlib)
|
||||
: SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {
|
||||
if (auto target_sp = m_backend.GetTargetSP()) {
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
bool GenericOptionalFrontend::Update() {
|
||||
ValueObjectSP engaged_sp;
|
||||
|
||||
if (m_stdlib == StdLib::LibCxx)
|
||||
engaged_sp =
|
||||
m_backend.GetChildMemberWithName(ConstString("__engaged_"), true);
|
||||
else if (m_stdlib == StdLib::LibStdcpp)
|
||||
engaged_sp =
|
||||
m_backend.GetChildMemberWithName(ConstString("_M_payload"), true)
|
||||
->GetChildMemberWithName(ConstString("_M_engaged"), true);
|
||||
|
||||
if (!engaged_sp)
|
||||
return false;
|
||||
|
||||
// _M_engaged/__engaged is a bool flag and is true if the optional contains a
|
||||
// value. Converting it to unsigned gives us a size of 1 if it contains a
|
||||
// value and 0 if not.
|
||||
m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(size_t _idx) {
|
||||
if (!m_has_value)
|
||||
return ValueObjectSP();
|
||||
|
||||
ValueObjectSP val_sp;
|
||||
|
||||
if (m_stdlib == StdLib::LibCxx)
|
||||
// __val_ contains the underlying value of an optional if it has one.
|
||||
// Currently because it is part of an anonymous union
|
||||
// GetChildMemberWithName() does not peer through and find it unless we are
|
||||
// at the parent itself. We can obtain the parent through __engaged_.
|
||||
val_sp = m_backend.GetChildMemberWithName(ConstString("__engaged_"), true)
|
||||
->GetParent()
|
||||
->GetChildAtIndex(0, true)
|
||||
->GetChildMemberWithName(ConstString("__val_"), true);
|
||||
else if (m_stdlib == StdLib::LibStdcpp) {
|
||||
val_sp = m_backend.GetChildMemberWithName(ConstString("_M_payload"), true)
|
||||
->GetChildMemberWithName(ConstString("_M_payload"), true);
|
||||
|
||||
// In some implementations, _M_value contains the underlying value of an
|
||||
// optional, and in other versions, it's in the payload member.
|
||||
ValueObjectSP candidate =
|
||||
val_sp->GetChildMemberWithName(ConstString("_M_value"), true);
|
||||
if (candidate)
|
||||
val_sp = candidate;
|
||||
}
|
||||
|
||||
if (!val_sp)
|
||||
return ValueObjectSP();
|
||||
|
||||
CompilerType holder_type = val_sp->GetCompilerType();
|
||||
|
||||
if (!holder_type)
|
||||
return ValueObjectSP();
|
||||
|
||||
return val_sp->Clone(ConstString("Value"));
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
formatters::LibStdcppOptionalSyntheticFrontEndCreator(
|
||||
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
||||
if (valobj_sp)
|
||||
return new GenericOptionalFrontend(
|
||||
*valobj_sp, GenericOptionalFrontend::StdLib::LibStdcpp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator(
|
||||
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
||||
if (valobj_sp)
|
||||
return new GenericOptionalFrontend(*valobj_sp,
|
||||
GenericOptionalFrontend::StdLib::LibCxx);
|
||||
return nullptr;
|
||||
}
|
|
@ -170,8 +170,8 @@ SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,
|
|||
lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP valobj_sp);
|
||||
LibcxxOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
//===-- LibCxxOptional.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 "LibCxx.h"
|
||||
#include "lldb/DataFormatters/FormattersHelpers.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
namespace {
|
||||
|
||||
class OptionalFrontEnd : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
OptionalFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
|
||||
Update();
|
||||
}
|
||||
|
||||
size_t GetIndexOfChildWithName(ConstString name) override {
|
||||
return formatters::ExtractIndexFromString(name.GetCString());
|
||||
}
|
||||
|
||||
bool MightHaveChildren() override { return true; }
|
||||
bool Update() override;
|
||||
size_t CalculateNumChildren() override { return m_has_value ? 1U : 0U; }
|
||||
ValueObjectSP GetChildAtIndex(size_t idx) override;
|
||||
|
||||
private:
|
||||
/// True iff the option contains a value.
|
||||
bool m_has_value = false;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
bool OptionalFrontEnd::Update() {
|
||||
ValueObjectSP engaged_sp(
|
||||
m_backend.GetChildMemberWithName(ConstString("__engaged_"), true));
|
||||
|
||||
if (!engaged_sp)
|
||||
return false;
|
||||
|
||||
// __engaged_ is a bool flag and is true if the optional contains a value.
|
||||
// Converting it to unsigned gives us a size of 1 if it contains a value
|
||||
// and 0 if not.
|
||||
m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueObjectSP OptionalFrontEnd::GetChildAtIndex(size_t idx) {
|
||||
if (!m_has_value)
|
||||
return ValueObjectSP();
|
||||
|
||||
// __val_ contains the underlying value of an optional if it has one.
|
||||
// Currently because it is part of an anonymous union GetChildMemberWithName()
|
||||
// does not peer through and find it unless we are at the parent itself.
|
||||
// We can obtain the parent through __engaged_.
|
||||
ValueObjectSP val_sp(
|
||||
m_backend.GetChildMemberWithName(ConstString("__engaged_"), true)
|
||||
->GetParent()
|
||||
->GetChildAtIndex(0, true)
|
||||
->GetChildMemberWithName(ConstString("__val_"), true));
|
||||
|
||||
if (!val_sp)
|
||||
return ValueObjectSP();
|
||||
|
||||
CompilerType holder_type = val_sp->GetCompilerType();
|
||||
|
||||
if (!holder_type)
|
||||
return ValueObjectSP();
|
||||
|
||||
return val_sp->Clone(ConstString("Value"));
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
formatters::LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP valobj_sp) {
|
||||
if (valobj_sp)
|
||||
return new OptionalFrontEnd(*valobj_sp);
|
||||
return nullptr;
|
||||
}
|
|
@ -45,6 +45,10 @@ SyntheticChildrenFrontEnd *
|
|||
LibStdcppBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibStdcppOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
|
Loading…
Reference in New Issue