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
|
CPlusPlusNameParser.cpp
|
||||||
CxxStringTypes.cpp
|
CxxStringTypes.cpp
|
||||||
GenericBitset.cpp
|
GenericBitset.cpp
|
||||||
|
GenericOptional.cpp
|
||||||
LibCxx.cpp
|
LibCxx.cpp
|
||||||
LibCxxAtomic.cpp
|
LibCxxAtomic.cpp
|
||||||
LibCxxInitializerList.cpp
|
LibCxxInitializerList.cpp
|
||||||
LibCxxList.cpp
|
LibCxxList.cpp
|
||||||
LibCxxMap.cpp
|
LibCxxMap.cpp
|
||||||
LibCxxOptional.cpp
|
|
||||||
LibCxxQueue.cpp
|
LibCxxQueue.cpp
|
||||||
LibCxxTuple.cpp
|
LibCxxTuple.cpp
|
||||||
LibCxxUnorderedMap.cpp
|
LibCxxUnorderedMap.cpp
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "BlockPointer.h"
|
#include "BlockPointer.h"
|
||||||
#include "CPlusPlusNameParser.h"
|
#include "CPlusPlusNameParser.h"
|
||||||
#include "CxxStringTypes.h"
|
#include "CxxStringTypes.h"
|
||||||
|
#include "Generic.h"
|
||||||
#include "LibCxx.h"
|
#include "LibCxx.h"
|
||||||
#include "LibCxxAtomic.h"
|
#include "LibCxxAtomic.h"
|
||||||
#include "LibCxxVariant.h"
|
#include "LibCxxVariant.h"
|
||||||
|
@ -655,7 +656,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
"libc++ std::tuple synthetic children",
|
"libc++ std::tuple synthetic children",
|
||||||
ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
|
ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
|
||||||
stl_synth_flags, true);
|
stl_synth_flags, true);
|
||||||
AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
|
AddCXXSynthetic(cpp_category_sp, LibcxxOptionalSyntheticFrontEndCreator,
|
||||||
"libc++ std::optional synthetic children",
|
"libc++ std::optional synthetic children",
|
||||||
ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
|
ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
|
||||||
stl_synth_flags, true);
|
stl_synth_flags, true);
|
||||||
|
@ -772,7 +773,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
ConstString("^std::__[[:alnum:]]+::atomic<.+>$"),
|
ConstString("^std::__[[:alnum:]]+::atomic<.+>$"),
|
||||||
stl_summary_flags, true);
|
stl_summary_flags, true);
|
||||||
AddCXXSummary(cpp_category_sp,
|
AddCXXSummary(cpp_category_sp,
|
||||||
lldb_private::formatters::LibcxxOptionalSummaryProvider,
|
lldb_private::formatters::GenericOptionalSummaryProvider,
|
||||||
"libc++ std::optional summary provider",
|
"libc++ std::optional summary provider",
|
||||||
ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
|
ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
|
||||||
stl_summary_flags, true);
|
stl_summary_flags, true);
|
||||||
|
@ -918,11 +919,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
||||||
stl_deref_flags,
|
stl_deref_flags,
|
||||||
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
|
"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(
|
cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
|
||||||
RegularExpression("^std::multiset<.+> >(( )?&)?$"),
|
RegularExpression("^std::multiset<.+> >(( )?&)?$"),
|
||||||
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
SyntheticChildrenSP(new ScriptedSyntheticChildren(
|
||||||
|
@ -946,11 +942,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
|
|
||||||
stl_summary_flags.SetDontShowChildren(false);
|
stl_summary_flags.SetDontShowChildren(false);
|
||||||
stl_summary_flags.SetSkipPointers(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(
|
cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
|
||||||
RegularExpression("^std::bitset<.+>(( )?&)?$"),
|
RegularExpression("^std::bitset<.+>(( )?&)?$"),
|
||||||
TypeSummaryImplSP(
|
TypeSummaryImplSP(
|
||||||
|
@ -1031,6 +1022,12 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
"std::bitset synthetic child", ConstString("^std::bitset<.+>(( )?&)?$"),
|
"std::bitset synthetic child", ConstString("^std::bitset<.+>(( )?&)?$"),
|
||||||
stl_deref_flags, true);
|
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,
|
AddCXXSummary(cpp_category_sp,
|
||||||
lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
|
lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
|
||||||
"libstdc++ std::unique_ptr summary provider",
|
"libstdc++ std::unique_ptr summary provider",
|
||||||
|
@ -1046,6 +1043,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
"libstdc++ std::weak_ptr summary provider",
|
"libstdc++ std::weak_ptr summary provider",
|
||||||
ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
|
ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
|
||||||
true);
|
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) {
|
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,7 +170,7 @@ SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,
|
||||||
lldb::ValueObjectSP);
|
lldb::ValueObjectSP);
|
||||||
|
|
||||||
SyntheticChildrenFrontEnd *
|
SyntheticChildrenFrontEnd *
|
||||||
LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
|
LibcxxOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||||
lldb::ValueObjectSP valobj_sp);
|
lldb::ValueObjectSP valobj_sp);
|
||||||
|
|
||||||
SyntheticChildrenFrontEnd *
|
SyntheticChildrenFrontEnd *
|
||||||
|
|
|
@ -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 *,
|
LibStdcppBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||||
lldb::ValueObjectSP);
|
lldb::ValueObjectSP);
|
||||||
|
|
||||||
|
SyntheticChildrenFrontEnd *
|
||||||
|
LibStdcppOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||||
|
lldb::ValueObjectSP);
|
||||||
|
|
||||||
SyntheticChildrenFrontEnd *
|
SyntheticChildrenFrontEnd *
|
||||||
LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||||
lldb::ValueObjectSP);
|
lldb::ValueObjectSP);
|
||||||
|
|
Loading…
Reference in New Issue