140 lines
4.4 KiB
C++
140 lines
4.4 KiB
C++
//===-- 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;
|
|
}
|