blob: e122fadb1ec769af09a8ac764caba6f8c65e475a [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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 "llvm/Support/ErrorExtras.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
namespace {
class MsvcStlExpectedFrontend : public SyntheticChildrenFrontEnd {
public:
MsvcStlExpectedFrontend(ValueObject &valobj)
: SyntheticChildrenFrontEnd(valobj) {
if (valobj.GetTargetSP())
Update();
}
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
if (!m_active)
return llvm::createStringErrorV("type has no child named '{0}'", name);
if (m_has_value) {
if (name == "Value" || name == "$$dereference$$")
return 0;
} else if (name == "Unexpected") {
return 0;
}
return llvm::createStringErrorV("type has no child named '{0}'", name);
}
llvm::Expected<uint32_t> CalculateNumChildren() override {
return m_active ? 1U : 0U;
}
ValueObjectSP GetChildAtIndex(uint32_t idx) override {
if (!m_active || idx != 0)
return {};
return m_active->Clone(m_has_value ? "Value" : "Unexpected");
}
lldb::ChildCacheState Update() override {
m_active = nullptr;
m_has_value = false;
ValueObjectSP ns = m_backend.GetNonSyntheticValue();
if (!ns)
return lldb::ChildCacheState::eRefetch;
ValueObjectSP has_sp = ns->GetChildMemberWithName("_Has_value");
if (!has_sp)
return lldb::ChildCacheState::eRefetch;
m_has_value = has_sp->GetValueAsUnsigned(0) != 0;
// expected<void, E> has no value child when engaged.
m_active =
ns->GetChildMemberWithName(m_has_value ? "_Value" : "_Unexpected")
.get();
return lldb::ChildCacheState::eRefetch;
}
private:
ValueObject *m_active = nullptr;
bool m_has_value = false;
};
} // namespace
bool formatters::IsMsvcStlExpected(ValueObject &valobj) {
if (auto valobj_sp = valobj.GetNonSyntheticValue())
return valobj_sp->GetChildMemberWithName("_Has_value") != nullptr;
return false;
}
bool formatters::MsvcStlExpectedSummaryProvider(ValueObject &valobj,
Stream &stream,
const TypeSummaryOptions &) {
ValueObjectSP ns = valobj.GetNonSyntheticValue();
if (!ns)
return false;
ValueObjectSP has_sp = ns->GetChildMemberWithName("_Has_value");
if (!has_sp)
return false;
// Keep the summary consistent with std::optional.
stream.Printf(" Has Value=%s ",
has_sp->GetValueAsUnsigned(0) ? "true" : "false");
return true;
}
SyntheticChildrenFrontEnd *formatters::MsvcStlExpectedSyntheticFrontEndCreator(
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
if (valobj_sp)
return new MsvcStlExpectedFrontend(*valobj_sp);
return nullptr;
}