Skip to content

[lldb] Upgrade GetIndexOfChildWithName to use llvm::Expected #136693

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

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions lldb/include/lldb/DataFormatters/TypeSynthetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class SyntheticChildrenFrontEnd {

virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;

virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
virtual llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) = 0;

/// This function is assumed to always succeed and if it fails, the front-end
/// should know to deal with it in the correct way (most probably, by refusing
Expand Down Expand Up @@ -117,8 +117,11 @@ class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {

lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }

size_t GetIndexOfChildWithName(ConstString name) override {
return UINT32_MAX;
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
return llvm::createStringError(
"'SyntheticChildrenFrontEnd::SyntheticValueProviderFrontEnd' cannot "
"find index of child '%s'",
name.AsCString());
}

lldb::ChildCacheState Update() override {
Expand Down Expand Up @@ -343,7 +346,7 @@ class TypeFilterImpl : public SyntheticChildren {

bool MightHaveChildren() override { return filter->GetCount() > 0; }

size_t GetIndexOfChildWithName(ConstString name) override;
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;

typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;

Expand Down Expand Up @@ -442,7 +445,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren {

bool MightHaveChildren() override;

size_t GetIndexOfChildWithName(ConstString name) override;
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;

lldb::ValueObjectSP GetSyntheticValue() override;

Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/DataFormatters/VectorIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

lldb::ChildCacheState Update() override;

size_t GetIndexOfChildWithName(ConstString name) override;
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;

private:
ExecutionContextRef m_exe_ctx_ref;
Expand Down
6 changes: 4 additions & 2 deletions lldb/include/lldb/Interpreter/ScriptInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,12 @@ class ScriptInterpreter : public PluginInterface {
return lldb::ValueObjectSP();
}

virtual int
virtual llvm::Expected<int>
GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
const char *child_name) {
return UINT32_MAX;
return llvm::createStringError(
"'PluginInterface::ScriptInterpreter' cannot find index of child '%s'",
child_name);
}

virtual bool
Expand Down
5 changes: 3 additions & 2 deletions lldb/include/lldb/Symbol/CompilerType.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,9 @@ class CompilerType {

/// Lookup a child given a name. This function will match base class names and
/// member member names in "clang_type" only, not descendants.
uint32_t GetIndexOfChildWithName(llvm::StringRef name,
bool omit_empty_base_classes) const;
llvm::Expected<uint32_t>
GetIndexOfChildWithName(llvm::StringRef name,
bool omit_empty_base_classes) const;

/// Lookup a child member given a name. This function will match member names
/// only and will descend into "clang_type" children in search for the first
Expand Down
9 changes: 6 additions & 3 deletions lldb/include/lldb/Symbol/TypeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,12 @@ class TypeSystem : public PluginInterface,
bool &child_is_base_class, bool &child_is_deref_of_parent,
ValueObject *valobj, uint64_t &language_flags) = 0;

virtual uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
llvm::StringRef name,
bool omit_empty_base_classes) = 0;
// Lookup a child given a name. This function will match base class names and
// member member names in "clang_type" only, not descendants.
virtual llvm::Expected<uint32_t>
GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
llvm::StringRef name,
bool omit_empty_base_classes) = 0;

virtual size_t GetIndexOfChildMemberWithName(
lldb::opaque_compiler_type_t type, llvm::StringRef name,
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/ValueObject/ValueObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ class ValueObject {
virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
bool can_create = true);

virtual size_t GetIndexOfChildWithName(llvm::StringRef name);
virtual llvm::Expected<size_t> GetIndexOfChildWithName(llvm::StringRef name);

llvm::Expected<uint32_t> GetNumChildren(uint32_t max = UINT32_MAX);
/// Like \c GetNumChildren but returns 0 on error. You probably
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/ValueObject/ValueObjectRegister.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ValueObjectRegisterSet : public ValueObject {
lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
bool can_create = true) override;

size_t GetIndexOfChildWithName(llvm::StringRef name) override;
llvm::Expected<size_t> GetIndexOfChildWithName(llvm::StringRef name) override;

protected:
bool UpdateValue() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class ValueObjectSynthetic : public ValueObject {
lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
bool can_create = true) override;

size_t GetIndexOfChildWithName(llvm::StringRef name) override;
llvm::Expected<size_t> GetIndexOfChildWithName(llvm::StringRef name) override;

lldb::ValueObjectSP
GetDynamicValue(lldb::DynamicValueType valueType) override;
Expand Down
8 changes: 5 additions & 3 deletions lldb/source/API/SBValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,13 +704,15 @@ SBValue SBValue::GetChildAtIndex(uint32_t idx,
uint32_t SBValue::GetIndexOfChildWithName(const char *name) {
LLDB_INSTRUMENT_VA(this, name);

uint32_t idx = UINT32_MAX;
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp) {
idx = value_sp->GetIndexOfChildWithName(name);
if (auto idx_or_err = value_sp->GetIndexOfChildWithName(name))
return *idx_or_err;
else
llvm::consumeError(idx_or_err.takeError());
}
return idx;
return UINT32_MAX;
}

SBValue SBValue::GetChildMemberWithName(const char *name) {
Expand Down
6 changes: 5 additions & 1 deletion lldb/source/DataFormatters/FormatterBytecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "FormatterBytecode.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Format.h"
Expand Down Expand Up @@ -489,7 +490,10 @@ llvm::Error Interpret(std::vector<ControlStackElement> &control,
TYPE_CHECK(Object, String);
auto name = data.Pop<std::string>();
POP_VALOBJ(valobj);
data.Push((uint64_t)valobj->GetIndexOfChildWithName(name));
if (auto index_or_err = valobj->GetIndexOfChildWithName(name))
data.Push((uint64_t)*index_or_err);
else
return index_or_err.takeError();
break;
}
case sel_get_type: {
Expand Down
14 changes: 9 additions & 5 deletions lldb/source/DataFormatters/TypeSynthetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ bool TypeFilterImpl::SetExpressionPathAtIndex(size_t i,
return true;
}

size_t
llvm::Expected<size_t>
TypeFilterImpl::FrontEnd::GetIndexOfChildWithName(ConstString name) {
const char *name_cstr = name.GetCString();
if (name_cstr) {
Expand All @@ -67,7 +67,9 @@ TypeFilterImpl::FrontEnd::GetIndexOfChildWithName(ConstString name) {
}
}
}
return UINT32_MAX;
return llvm::createStringError(
"'SyntheticChildrenFrontEnd::FrontEnd' cannot find index of child '%s'",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"'SyntheticChildrenFrontEnd::FrontEnd' cannot find index of child '%s'",
"'TypeFilterImpl::FrontEnd' cannot find index of child '%s'",

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest leaving out the function name entirely.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially suggested it because that'd make it easier to identify where this was coming from if we ever decide to log it (or see it in user reports)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Michael137 My thinking is that these error messages are meant to be read by LLDB users, and the function name is a tool to aid in debugging LLDB itself. Users won't understand the meaning of the function name here, so we shouldn't have it in the user-facing error message. If this is useful information needed to debug LLDB, then we should log it instead.
Let me know if you think that's not a good idea!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm fair question. Adding logging to all these places feels a bit noisy. In my opinion its helpful to be as specific as possible, and if we wanted to present something more generic to the user eventually then we can change the error message at the point where we are about to present it. I'm not sure where these error messages will currently show up actually

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding logging to all these places feels a bit noisy.

Currently the error is dropped silently. You wouldn't replace that with adding logging everywhere. My suggestion would be to:

  • return errors that are understandable to users
  • where necessary add logging in the error case with additional information

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where these error messages will currently show up actually

The error messages in the Expected return results of CompilerType are surfaced when formatting ValueObjects, for example.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm my main concern is that we end up getting user reports with a very generic error and then have no way to really tell where we went wrong. Then adding logging after-the-fact is a pretty slow turnaround. I guess usually these types of issues require a reproducer to debug anyway, so maybe this isn't a valid concern? Wdyt? I don't have a strong opinion on this. But it would be easier/more convenient to go from non-generic error back to generic error than the other way around if we really need to

name.AsCString());
}

std::string TypeFilterImpl::GetDescription() {
Expand Down Expand Up @@ -218,10 +220,12 @@ bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() {
return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp);
}

size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(
ConstString name) {
llvm::Expected<size_t>
ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(ConstString name) {
if (!m_wrapper_sp || m_interpreter == nullptr)
return UINT32_MAX;
return llvm::createStringError(
"'ScriptedSyntheticChildren::FrontEnd' cannot find index of child '%s'",
name.AsCString());
return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp,
name.GetCString());
}
Expand Down
10 changes: 7 additions & 3 deletions lldb/source/DataFormatters/VectorType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,15 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
return lldb::ChildCacheState::eRefetch;
}

size_t GetIndexOfChildWithName(ConstString name) override {
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
const char *item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
return UINT32_MAX;
if (idx == UINT32_MAX ||
(idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()))
return llvm::createStringError(
"'SyntheticChildrenFrontEnd::VectorTypeSyntheticFrontEnd' cannot "
"find index of child '%s'",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also print the idx that we found in the error message? (same applies to other places that do the idx >= CalculateNumChildrenIgnoringErrors comparison)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type has no child named '%s'

name.AsCString());
return idx;
}

Expand Down
19 changes: 15 additions & 4 deletions lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,12 @@ class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
return lldb::ChildCacheState::eRefetch;
}

size_t GetIndexOfChildWithName(ConstString name) override {
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
if (!m_block_struct_type.IsValid())
return UINT32_MAX;
return llvm::createStringError(
"'SyntheticChildrenFrontend::BlockPointerSyntheticFrontEnd' cannot "
"find index of child '%s'",
name.AsCString());

const bool omit_empty_base_classes = false;
return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
Expand All @@ -172,8 +175,16 @@ bool lldb_private::formatters::BlockPointerSummaryProvider(

static const ConstString s_FuncPtr_name("__FuncPtr");

lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
auto index_or_err =
synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name);

if (!index_or_err) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Types), index_or_err.takeError(), "{0}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LLDB_LOG_ERROR(GetLog(LLDBLog::Types), index_or_err.takeError(), "{0}");
LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), index_or_err.takeError(), "{0}");

return false;
}

lldb::ValueObjectSP child_sp =
synthetic_children->GetChildAtIndex(*index_or_err);

if (!child_sp) {
return false;
Expand Down
14 changes: 11 additions & 3 deletions lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,15 @@ lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::Update() {
return lldb::ChildCacheState::eRefetch;
}

size_t StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName(
llvm::Expected<size_t>
StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName(
ConstString name) {
if (!m_resume_ptr_sp || !m_destroy_ptr_sp)
return UINT32_MAX;
return llvm::createStringError(
"'SyntheticChildrenFrontend::StdlibCoroutineHandleSyntheticFrontEnd' "
"cannot find index of child '%s'. (m_resume_ptr_sp='%p', "
"m_destroy_ptr_sp='%p')",
name.AsCString(), m_resume_ptr_sp.get(), m_destroy_ptr_sp.get());

if (name == ConstString("resume"))
return 0;
Expand All @@ -211,7 +216,10 @@ size_t StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName(
if (name == ConstString("promise_ptr") && m_promise_ptr_sp)
return 2;

return UINT32_MAX;
return llvm::createStringError(
"'SyntheticChildrenFrontend::StdlibCoroutineHandleSyntheticFrontEnd' "
"cannot find index of child '%s'",
name.AsCString());
}

SyntheticChildrenFrontEnd *
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Language/CPlusPlus/Coroutines.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class StdlibCoroutineHandleSyntheticFrontEnd

lldb::ChildCacheState Update() override;

size_t GetIndexOfChildWithName(ConstString name) override;
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;

private:
lldb::ValueObjectSP m_resume_ptr_sp;
Expand Down
11 changes: 9 additions & 2 deletions lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ class GenericBitsetFrontEnd : public SyntheticChildrenFrontEnd {

GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib);

size_t GetIndexOfChildWithName(ConstString name) override {
return formatters::ExtractIndexFromString(name.GetCString());
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
size_t idx = formatters::ExtractIndexFromString(name.GetCString());
if (idx == UINT32_MAX) {
return llvm::createStringError(
"'SyntheticChildrenFrontend::GenericBitsetFrontEnd' cannot find "
"index of child '%s'",
name.AsCString());
}
return idx;
}

lldb::ChildCacheState Update() override;
Expand Down
11 changes: 9 additions & 2 deletions lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,17 @@ class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {

GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib);

size_t GetIndexOfChildWithName(ConstString name) override {
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
if (name == "$$dereference$$")
return 0;
return formatters::ExtractIndexFromString(name.GetCString());
size_t idx = formatters::ExtractIndexFromString(name.GetCString());
if (idx == UINT32_MAX) {
return llvm::createStringError(
"'SyntheticChildrenFrontend::GenericOptionalFrontend' cannot find "
"index of child '%s'",
name.AsCString());
}
return idx;
}

llvm::Expected<uint32_t> CalculateNumChildren() override {
Expand Down
28 changes: 21 additions & 7 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,17 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
return lldb::ChildCacheState::eRefetch;
}

size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
llvm::Expected<size_t>
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name) {
if (name == "__ptr_")
return 0;
if (name == "$$dereference$$")
return 1;
return UINT32_MAX;
return llvm::createStringError(
"'SyntheticChildrenFrontend::LibcxxSharedPtrSyntheticFrontEnd' cannot "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"'SyntheticChildrenFrontend::LibcxxSharedPtrSyntheticFrontEnd' cannot "
"'LibcxxSharedPtrSyntheticFrontEnd' cannot "

"find index of child '%s'",
name.AsCString());
}

lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
Expand Down Expand Up @@ -407,15 +411,19 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
return lldb::ChildCacheState::eRefetch;
}

size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
llvm::Expected<size_t>
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name) {
if (name == "pointer")
return 0;
if (name == "deleter")
return 1;
if (name == "$$dereference$$")
return 2;
return UINT32_MAX;
return llvm::createStringError(
"'ScriptedSyntheticChildren::LibcxxUniquePtrSyntheticFrontEnd' cannot "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"'ScriptedSyntheticChildren::LibcxxUniquePtrSyntheticFrontEnd' cannot "
"'LibcxxUniquePtrSyntheticFrontEnd' cannot "

"find index of child '%s'",
name.AsCString());
}

bool lldb_private::formatters::LibcxxContainerSummaryProvider(
Expand Down Expand Up @@ -456,9 +464,15 @@ ExtractLibcxxStringInfo(ValueObject &valobj) {
if (!l)
return {};

StringLayout layout = l->GetIndexOfChildWithName("__data_") == 0
? StringLayout::DSC
: StringLayout::CSD;
auto index_or_err = l->GetIndexOfChildWithName("__data_");
if (!index_or_err) {
LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), index_or_err.takeError(),
"{0}");
return {};
}

StringLayout layout =
*index_or_err == 0 ? StringLayout::DSC : StringLayout::CSD;

bool short_mode = false; // this means the string is in short-mode and the
// data is stored inline
Expand Down
Loading
Loading