Revert "[lldb] Fix member access in GetExpressionPath"

This reverts commit 0205aa4a02 because it
breaks TestArray.py:

  a->c = <parent failed to evaluate: parent is NULL>

I decided to revert instead of disable the test because it looks like a
legitimate issue with the patch.
This commit is contained in:
Jonas Devlieghere
2022-10-20 15:20:50 -07:00
parent a6ac968360
commit 8c7a1f8761
6 changed files with 56 additions and 243 deletions

View File

@@ -273,6 +273,8 @@ CompilerType ValueObject::MaybeCalculateCompleteType() {
return compiler_type;
}
DataExtractor &ValueObject::GetDataExtractor() {
UpdateValueIfNeeded(false);
return m_data;
@@ -407,9 +409,8 @@ ValueObject::GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
return root;
}
lldb::ValueObjectSP
ValueObject::GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs,
size_t *index_of_error) {
lldb::ValueObjectSP ValueObject::GetChildAtIndexPath(
llvm::ArrayRef<std::pair<size_t, bool>> idxs, size_t *index_of_error) {
if (idxs.size() == 0)
return GetSP();
ValueObjectSP root(GetSP());
@@ -1184,10 +1185,9 @@ bool ValueObject::DumpPrintableRepresentation(
{
Status error;
lldb::WritableDataBufferSP buffer_sp;
std::pair<size_t, bool> read_string =
ReadPointedString(buffer_sp, error, 0,
(custom_format == eFormatVectorOfChar) ||
(custom_format == eFormatCharArray));
std::pair<size_t, bool> read_string = ReadPointedString(
buffer_sp, error, 0, (custom_format == eFormatVectorOfChar) ||
(custom_format == eFormatCharArray));
lldb_private::formatters::StringPrinter::
ReadBufferAndDumpToStreamOptions options(*this);
options.SetData(DataExtractor(
@@ -1552,7 +1552,8 @@ bool ValueObject::GetDeclaration(Declaration &decl) {
return false;
}
void ValueObject::AddSyntheticChild(ConstString key, ValueObject *valobj) {
void ValueObject::AddSyntheticChild(ConstString key,
ValueObject *valobj) {
m_synthetic_children[key] = valobj;
}
@@ -1923,96 +1924,64 @@ void ValueObject::GetExpressionPath(Stream &s,
return;
}
// Checks whether a value is dereference of a non-reference parent.
// This is used to determine whether to print a dereference operation (*).
auto is_deref_of_non_reference = [](ValueObject *value) {
if (value == nullptr)
return false;
ValueObject *value_parent = value->GetParent();
if (value_parent) {
CompilerType parent_compiler_type = value_parent->GetCompilerType();
if (parent_compiler_type) {
const uint32_t parent_type_info = parent_compiler_type.GetTypeInfo();
if (parent_type_info & eTypeIsReference)
return false;
}
}
return value->IsDereferenceOfParent();
};
const bool is_deref_of_parent = IsDereferenceOfParent();
ValueObject *parent = GetParent();
if (is_deref_of_non_reference(this) &&
if (is_deref_of_parent &&
epformat == eGetExpressionPathFormatDereferencePointers) {
// this is the original format of GetExpressionPath() producing code like
// *(a_ptr).memberName, which is entirely fine, until you put this into
// StackFrame::GetValueForVariableExpressionPath() which prefers to see
// a_ptr->memberName. The eHonorPointers mode is meant to produce strings
// in this latter format.
s.PutChar('*');
if (parent)
parent->GetExpressionPath(s, epformat);
return;
// a_ptr->memberName. the eHonorPointers mode is meant to produce strings
// in this latter format
s.PutCString("*(");
}
const bool is_deref_of_parent = IsDereferenceOfParent();
bool is_parent_deref_of_non_reference = false;
bool print_obj_access = false;
bool print_ptr_access = false;
ValueObject *parent = GetParent();
if (!IsBaseClass() && !is_deref_of_parent) {
ValueObject *non_base_class_parent = GetNonBaseClassParent();
if (non_base_class_parent && !non_base_class_parent->GetName().IsEmpty()) {
CompilerType non_base_class_parent_compiler_type =
non_base_class_parent->GetCompilerType();
if (non_base_class_parent_compiler_type) {
if (parent && parent->IsDereferenceOfParent() &&
epformat == eGetExpressionPathFormatHonorPointers) {
print_ptr_access = true;
} else {
const uint32_t non_base_class_parent_type_info =
non_base_class_parent_compiler_type.GetTypeInfo();
if (parent)
parent->GetExpressionPath(s, epformat);
if (non_base_class_parent_type_info & eTypeIsPointer) {
print_ptr_access = true;
} else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
!(non_base_class_parent_type_info & eTypeIsArray)) {
print_obj_access = true;
// if we are a deref_of_parent just because we are synthetic array members
// made up to allow ptr[%d] syntax to work in variable printing, then add our
// name ([%d]) to the expression path
if (m_flags.m_is_array_item_for_pointer &&
epformat == eGetExpressionPathFormatHonorPointers)
s.PutCString(m_name.GetStringRef());
if (!IsBaseClass()) {
if (!is_deref_of_parent) {
ValueObject *non_base_class_parent = GetNonBaseClassParent();
if (non_base_class_parent &&
!non_base_class_parent->GetName().IsEmpty()) {
CompilerType non_base_class_parent_compiler_type =
non_base_class_parent->GetCompilerType();
if (non_base_class_parent_compiler_type) {
if (parent && parent->IsDereferenceOfParent() &&
epformat == eGetExpressionPathFormatHonorPointers) {
s.PutCString("->");
} else {
const uint32_t non_base_class_parent_type_info =
non_base_class_parent_compiler_type.GetTypeInfo();
if (non_base_class_parent_type_info & eTypeIsPointer) {
s.PutCString("->");
} else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
!(non_base_class_parent_type_info & eTypeIsArray)) {
s.PutChar('.');
}
}
}
}
is_parent_deref_of_non_reference =
is_deref_of_non_reference(non_base_class_parent) &&
epformat == eGetExpressionPathFormatDereferencePointers;
const char *name = GetName().GetCString();
if (name)
s.PutCString(name);
}
}
if (parent) {
// The parent should be wrapped in parenthesis when doing a member access.
// This prevents forming incorrect expressions such as *(ptr).field,
// which dereferences the field instead of the ptr, and constructs the
// expression in the format (*(ptr)).field. To create expressions compatible
// with StackFrame::GetValueForVariableExpressionPath() and reduce amount of
// unnecessary parenthesis, this is done only when the parent has the
// dereference syntax *(parent).
const bool wrap_parent_in_parens = (print_obj_access || print_ptr_access) &&
is_parent_deref_of_non_reference;
if (wrap_parent_in_parens)
s.PutChar('(');
parent->GetExpressionPath(s, epformat);
if (wrap_parent_in_parens)
s.PutChar(')');
}
if (print_obj_access)
s.PutChar('.');
if (print_ptr_access)
s.PutCString("->");
if (!IsBaseClass() && !is_deref_of_parent) {
const char *name = GetName().GetCString();
if (name)
s.PutCString(name);
if (is_deref_of_parent &&
epformat == eGetExpressionPathFormatDereferencePointers) {
s.PutChar(')');
}
}
@@ -3139,6 +3108,8 @@ bool ValueObject::CanProvideValue() {
return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}
ValueObjectSP ValueObject::Persist() {
if (!UpdateValueIfNeeded())
return nullptr;