mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 20:46:05 +00:00
Revert "[lldb] Improve maintainability and readability for ValueObject methods (#75865)"
This reverts commit d657519838e4b2310e13ec5ff52599e041860825 as it breaks two dozen tests. The breakages are related to variable path expression parsing and summary string parsing (possibly the same code).
This commit is contained in:
parent
7a6c2628e9
commit
78b00c116b
@ -1582,64 +1582,62 @@ bool ValueObject::IsUninitializedReference() {
|
||||
|
||||
ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
|
||||
bool can_create) {
|
||||
if (!IsPointerType() && !IsArrayType())
|
||||
return ValueObjectSP();
|
||||
ValueObjectSP synthetic_child_sp;
|
||||
if (IsPointerType() || IsArrayType()) {
|
||||
std::string index_str = llvm::formatv("[{0}]", index);
|
||||
ConstString index_const_str(index_str);
|
||||
// Check if we have already created a synthetic array member in this valid
|
||||
// object. If we have we will re-use it.
|
||||
synthetic_child_sp = GetSyntheticChild(index_const_str);
|
||||
if (!synthetic_child_sp) {
|
||||
ValueObject *synthetic_child;
|
||||
// We haven't made a synthetic array member for INDEX yet, so lets make
|
||||
// one and cache it for any future reference.
|
||||
synthetic_child = CreateChildAtIndex(0, true, index);
|
||||
|
||||
std::string index_str = llvm::formatv("[{0}]", index);
|
||||
ConstString index_const_str(index_str);
|
||||
// Check if we have already created a synthetic array member in this valid
|
||||
// object. If we have we will re-use it.
|
||||
if (auto existing_synthetic_child = GetSyntheticChild(index_const_str))
|
||||
return existing_synthetic_child;
|
||||
|
||||
// We haven't made a synthetic array member for INDEX yet, so lets make
|
||||
// one and cache it for any future reference.
|
||||
ValueObject *synthetic_child = CreateChildAtIndex(0, true, index);
|
||||
|
||||
if (!synthetic_child)
|
||||
return ValueObjectSP();
|
||||
|
||||
// Cache the synthetic child's value because it's valid.
|
||||
AddSyntheticChild(index_const_str, synthetic_child);
|
||||
auto synthetic_child_sp = synthetic_child->GetSP();
|
||||
synthetic_child_sp->SetName(ConstString(index_str));
|
||||
synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
|
||||
// Cache the value if we got one back...
|
||||
if (synthetic_child) {
|
||||
AddSyntheticChild(index_const_str, synthetic_child);
|
||||
synthetic_child_sp = synthetic_child->GetSP();
|
||||
synthetic_child_sp->SetName(ConstString(index_str));
|
||||
synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return synthetic_child_sp;
|
||||
}
|
||||
|
||||
ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
|
||||
bool can_create) {
|
||||
if (!IsScalarType())
|
||||
return ValueObjectSP();
|
||||
ValueObjectSP synthetic_child_sp;
|
||||
if (IsScalarType()) {
|
||||
std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
|
||||
ConstString index_const_str(index_str);
|
||||
// Check if we have already created a synthetic array member in this valid
|
||||
// object. If we have we will re-use it.
|
||||
synthetic_child_sp = GetSyntheticChild(index_const_str);
|
||||
if (!synthetic_child_sp) {
|
||||
uint32_t bit_field_size = to - from + 1;
|
||||
uint32_t bit_field_offset = from;
|
||||
if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
|
||||
bit_field_offset =
|
||||
GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
|
||||
// We haven't made a synthetic array member for INDEX yet, so lets make
|
||||
// one and cache it for any future reference.
|
||||
ValueObjectChild *synthetic_child = new ValueObjectChild(
|
||||
*this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),
|
||||
0, bit_field_size, bit_field_offset, false, false,
|
||||
eAddressTypeInvalid, 0);
|
||||
|
||||
std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
|
||||
ConstString index_const_str(index_str);
|
||||
|
||||
// Check if we have already created a synthetic array member in this valid
|
||||
// object. If we have we will re-use it.
|
||||
if (auto existing_synthetic_child = GetSyntheticChild(index_const_str))
|
||||
return existing_synthetic_child;
|
||||
|
||||
uint32_t bit_field_size = to - from + 1;
|
||||
uint32_t bit_field_offset = from;
|
||||
if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
|
||||
bit_field_offset =
|
||||
GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
|
||||
|
||||
// We haven't made a synthetic array member for INDEX yet, so lets make
|
||||
// one and cache it for any future reference.
|
||||
ValueObjectChild *synthetic_child = new ValueObjectChild(
|
||||
*this, GetCompilerType(), index_const_str, GetByteSize().value_or(0), 0,
|
||||
bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid, 0);
|
||||
|
||||
if (!synthetic_child)
|
||||
return ValueObjectSP();
|
||||
|
||||
// Cache the synthetic child's value because it's valid.
|
||||
AddSyntheticChild(index_const_str, synthetic_child);
|
||||
auto synthetic_child_sp = synthetic_child->GetSP();
|
||||
synthetic_child_sp->SetName(ConstString(index_str));
|
||||
synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
|
||||
// Cache the value if we got one back...
|
||||
if (synthetic_child) {
|
||||
AddSyntheticChild(index_const_str, synthetic_child);
|
||||
synthetic_child_sp = synthetic_child->GetSP();
|
||||
synthetic_child_sp->SetName(ConstString(index_str));
|
||||
synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return synthetic_child_sp;
|
||||
}
|
||||
|
||||
@ -1649,8 +1647,9 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
|
||||
|
||||
ValueObjectSP synthetic_child_sp;
|
||||
|
||||
if (name_const_str.IsEmpty())
|
||||
if (name_const_str.IsEmpty()) {
|
||||
name_const_str.SetString("@" + std::to_string(offset));
|
||||
}
|
||||
|
||||
// Check if we have already created a synthetic array member in this valid
|
||||
// object. If we have we will re-use it.
|
||||
@ -1660,13 +1659,13 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
|
||||
return synthetic_child_sp;
|
||||
|
||||
if (!can_create)
|
||||
return ValueObjectSP();
|
||||
return {};
|
||||
|
||||
ExecutionContext exe_ctx(GetExecutionContextRef());
|
||||
std::optional<uint64_t> size =
|
||||
type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
|
||||
if (!size)
|
||||
return ValueObjectSP();
|
||||
return {};
|
||||
ValueObjectChild *synthetic_child =
|
||||
new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
|
||||
false, false, eAddressTypeInvalid, 0);
|
||||
@ -1700,7 +1699,7 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
|
||||
return synthetic_child_sp;
|
||||
|
||||
if (!can_create)
|
||||
return ValueObjectSP();
|
||||
return {};
|
||||
|
||||
const bool is_base_class = true;
|
||||
|
||||
@ -1708,7 +1707,7 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
|
||||
std::optional<uint64_t> size =
|
||||
type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
|
||||
if (!size)
|
||||
return ValueObjectSP();
|
||||
return {};
|
||||
ValueObjectChild *synthetic_child =
|
||||
new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
|
||||
is_base_class, false, eAddressTypeInvalid, 0);
|
||||
@ -1737,30 +1736,30 @@ static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
|
||||
ValueObjectSP
|
||||
ValueObject::GetSyntheticExpressionPathChild(const char *expression,
|
||||
bool can_create) {
|
||||
ValueObjectSP synthetic_child_sp;
|
||||
ConstString name_const_string(expression);
|
||||
// Check if we have already created a synthetic array member in this valid
|
||||
// object. If we have we will re-use it.
|
||||
if (auto existing_synthetic_child = GetSyntheticChild(name_const_string))
|
||||
return existing_synthetic_child;
|
||||
synthetic_child_sp = GetSyntheticChild(name_const_string);
|
||||
if (!synthetic_child_sp) {
|
||||
// We haven't made a synthetic array member for expression yet, so lets
|
||||
// make one and cache it for any future reference.
|
||||
synthetic_child_sp = GetValueForExpressionPath(
|
||||
expression, nullptr, nullptr,
|
||||
GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
|
||||
GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
|
||||
None));
|
||||
|
||||
// We haven't made a synthetic array member for expression yet, so lets
|
||||
// make one and cache it for any future reference.
|
||||
auto path_options = GetValueForExpressionPathOptions();
|
||||
path_options.SetSyntheticChildrenTraversal(
|
||||
GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None);
|
||||
auto synthetic_child =
|
||||
GetValueForExpressionPath(expression, nullptr, nullptr, path_options);
|
||||
|
||||
if (!synthetic_child)
|
||||
return ValueObjectSP();
|
||||
|
||||
// Cache the synthetic child's value because it's valid.
|
||||
// FIXME: this causes a "real" child to end up with its name changed to
|
||||
// the contents of expression
|
||||
AddSyntheticChild(name_const_string, synthetic_child.get());
|
||||
synthetic_child->SetName(
|
||||
ConstString(SkipLeadingExpressionPathSeparators(expression)));
|
||||
return synthetic_child;
|
||||
// Cache the value if we got one back...
|
||||
if (synthetic_child_sp.get()) {
|
||||
// FIXME: this causes a "real" child to end up with its name changed to
|
||||
// the contents of expression
|
||||
AddSyntheticChild(name_const_string, synthetic_child_sp.get());
|
||||
synthetic_child_sp->SetName(
|
||||
ConstString(SkipLeadingExpressionPathSeparators(expression)));
|
||||
}
|
||||
}
|
||||
return synthetic_child_sp;
|
||||
}
|
||||
|
||||
void ValueObject::CalculateSyntheticValue() {
|
||||
@ -1957,55 +1956,66 @@ ValueObjectSP ValueObject::GetValueForExpressionPath(
|
||||
const GetValueForExpressionPathOptions &options,
|
||||
ExpressionPathAftermath *final_task_on_target) {
|
||||
|
||||
auto dummy_stop_reason = eExpressionPathScanEndReasonUnknown;
|
||||
auto dummy_value_type = eExpressionPathEndResultTypeInvalid;
|
||||
auto dummy_final_task = eExpressionPathAftermathNothing;
|
||||
ExpressionPathScanEndReason dummy_reason_to_stop =
|
||||
ValueObject::eExpressionPathScanEndReasonUnknown;
|
||||
ExpressionPathEndResultType dummy_final_value_type =
|
||||
ValueObject::eExpressionPathEndResultTypeInvalid;
|
||||
ExpressionPathAftermath dummy_final_task_on_target =
|
||||
ValueObject::eExpressionPathAftermathNothing;
|
||||
|
||||
auto proxy_stop_reason = reason_to_stop ? reason_to_stop : &dummy_stop_reason;
|
||||
auto proxy_value_type =
|
||||
final_value_type ? final_value_type : &dummy_value_type;
|
||||
auto proxy_final_task =
|
||||
final_task_on_target ? final_task_on_target : &dummy_final_task;
|
||||
ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
|
||||
expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
|
||||
final_value_type ? final_value_type : &dummy_final_value_type, options,
|
||||
final_task_on_target ? final_task_on_target
|
||||
: &dummy_final_task_on_target);
|
||||
|
||||
auto ret_value = GetValueForExpressionPath_Impl(expression, proxy_stop_reason,
|
||||
proxy_value_type, options,
|
||||
proxy_final_task);
|
||||
if (!final_task_on_target ||
|
||||
*final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
|
||||
return ret_val;
|
||||
|
||||
// The caller knows nothing happened if `final_task_on_target` doesn't change.
|
||||
if (!ret_value || (*proxy_value_type) != eExpressionPathEndResultTypePlain ||
|
||||
!final_task_on_target)
|
||||
return ValueObjectSP();
|
||||
|
||||
ExpressionPathAftermath &final_task_on_target_ref = (*final_task_on_target);
|
||||
ExpressionPathScanEndReason stop_reason_for_error;
|
||||
Status error;
|
||||
// The method can only dereference and take the address of plain objects.
|
||||
switch (final_task_on_target_ref) {
|
||||
case eExpressionPathAftermathNothing:
|
||||
return ret_value;
|
||||
|
||||
case eExpressionPathAftermathDereference:
|
||||
ret_value = ret_value->Dereference(error);
|
||||
stop_reason_for_error = eExpressionPathScanEndReasonDereferencingFailed;
|
||||
break;
|
||||
|
||||
case eExpressionPathAftermathTakeAddress:
|
||||
ret_value = ret_value->AddressOf(error);
|
||||
stop_reason_for_error = eExpressionPathScanEndReasonTakingAddressFailed;
|
||||
break;
|
||||
if (ret_val.get() &&
|
||||
((final_value_type ? *final_value_type : dummy_final_value_type) ==
|
||||
eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
|
||||
// of plain objects
|
||||
{
|
||||
if ((final_task_on_target ? *final_task_on_target
|
||||
: dummy_final_task_on_target) ==
|
||||
ValueObject::eExpressionPathAftermathDereference) {
|
||||
Status error;
|
||||
ValueObjectSP final_value = ret_val->Dereference(error);
|
||||
if (error.Fail() || !final_value.get()) {
|
||||
if (reason_to_stop)
|
||||
*reason_to_stop =
|
||||
ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
|
||||
if (final_value_type)
|
||||
*final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
|
||||
return ValueObjectSP();
|
||||
} else {
|
||||
if (final_task_on_target)
|
||||
*final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
|
||||
return final_value;
|
||||
}
|
||||
}
|
||||
if (*final_task_on_target ==
|
||||
ValueObject::eExpressionPathAftermathTakeAddress) {
|
||||
Status error;
|
||||
ValueObjectSP final_value = ret_val->AddressOf(error);
|
||||
if (error.Fail() || !final_value.get()) {
|
||||
if (reason_to_stop)
|
||||
*reason_to_stop =
|
||||
ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
|
||||
if (final_value_type)
|
||||
*final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
|
||||
return ValueObjectSP();
|
||||
} else {
|
||||
if (final_task_on_target)
|
||||
*final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
|
||||
return final_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret_value && error.Success()) {
|
||||
final_task_on_target_ref = eExpressionPathAftermathNothing;
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
if (reason_to_stop)
|
||||
*reason_to_stop = stop_reason_for_error;
|
||||
|
||||
if (final_value_type)
|
||||
*final_value_type = eExpressionPathEndResultTypeInvalid;
|
||||
return ValueObjectSP();
|
||||
return ret_val; // final_task_on_target will still have its original value, so
|
||||
// you know I did not do it
|
||||
}
|
||||
|
||||
ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
|
||||
@ -2676,47 +2686,39 @@ ValueObjectSP ValueObject::AddressOf(Status &error) {
|
||||
const bool scalar_is_load_address = false;
|
||||
addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
|
||||
error.Clear();
|
||||
if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
|
||||
switch (address_type) {
|
||||
case eAddressTypeInvalid: {
|
||||
StreamString expr_path_strm;
|
||||
GetExpressionPath(expr_path_strm);
|
||||
error.SetErrorStringWithFormat("'%s' is not in memory",
|
||||
expr_path_strm.GetData());
|
||||
} break;
|
||||
|
||||
StreamString expr_path_strm;
|
||||
GetExpressionPath(expr_path_strm);
|
||||
const char *expr_path_str = expr_path_strm.GetData();
|
||||
|
||||
ExecutionContext exe_ctx(GetExecutionContextRef());
|
||||
auto scope = exe_ctx.GetBestExecutionContextScope();
|
||||
|
||||
if (addr == LLDB_INVALID_ADDRESS) {
|
||||
error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
|
||||
expr_path_str);
|
||||
return ValueObjectSP();
|
||||
}
|
||||
|
||||
switch (address_type) {
|
||||
case eAddressTypeInvalid:
|
||||
error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_str);
|
||||
return ValueObjectSP();
|
||||
|
||||
case eAddressTypeHost:
|
||||
error.SetErrorStringWithFormat("'%s' is in host process (LLDB) memory",
|
||||
expr_path_str);
|
||||
return ValueObjectSP();
|
||||
|
||||
case eAddressTypeFile:
|
||||
case eAddressTypeLoad: {
|
||||
CompilerType compiler_type = GetCompilerType();
|
||||
if (!compiler_type) {
|
||||
error.SetErrorStringWithFormat("'%s' doesn't have a compiler type",
|
||||
expr_path_str);
|
||||
return ValueObjectSP();
|
||||
case eAddressTypeFile:
|
||||
case eAddressTypeLoad: {
|
||||
CompilerType compiler_type = GetCompilerType();
|
||||
if (compiler_type) {
|
||||
std::string name(1, '&');
|
||||
name.append(m_name.AsCString(""));
|
||||
ExecutionContext exe_ctx(GetExecutionContextRef());
|
||||
m_addr_of_valobj_sp = ValueObjectConstResult::Create(
|
||||
exe_ctx.GetBestExecutionContextScope(),
|
||||
compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
|
||||
eAddressTypeInvalid, m_data.GetAddressByteSize());
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
StreamString expr_path_strm;
|
||||
GetExpressionPath(expr_path_strm);
|
||||
error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
|
||||
expr_path_strm.GetData());
|
||||
}
|
||||
|
||||
std::string name(1, '&');
|
||||
name.append(m_name.AsCString(""));
|
||||
m_addr_of_valobj_sp = ValueObjectConstResult::Create(
|
||||
scope, compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
|
||||
eAddressTypeInvalid, m_data.GetAddressByteSize());
|
||||
return m_addr_of_valobj_sp;
|
||||
}
|
||||
}
|
||||
return m_addr_of_valobj_sp;
|
||||
}
|
||||
|
||||
ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user