Basic support for reading synthetic children by index:
if your datatype provides synthetic children, "frame variable object[index]" should now do the right thing
in cases where the above syntax would have been rejected before, i.e.
object is not a pointer nor an array (frame variable ignores potential overload of [])
object is a pointer to an Objective-C class (which cannot be dereferenced)
expression will still run operator[] if available and complain if it cannot do so
synthetic children by name do not work yet
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@137097 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index ba030c4..e88bcb9 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -1668,6 +1668,22 @@
}
bool
+ValueObject::HasSyntheticValue()
+{
+ UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
+
+ if (m_last_synthetic_filter.get() == NULL)
+ return false;
+
+ CalculateSyntheticValue(lldb::eUseSyntheticFilter);
+
+ if (m_synthetic_value)
+ return true;
+ else
+ return false;
+}
+
+bool
ValueObject::GetBaseClassPath (Stream &s)
{
if (IsBaseClass())
@@ -2042,12 +2058,15 @@
{
if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T*
{
- if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong!
+ if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar...
{
- *first_unparsed = expression_cstr;
- *reason_to_stop = ValueObject::eRangeOperatorInvalid;
- *final_result = ValueObject::eInvalid;
- return ValueObjectSP();
+ if (options.m_no_synthetic_children) // ...only chance left is synthetic
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eRangeOperatorInvalid;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
}
else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
{
@@ -2117,6 +2136,9 @@
ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
if (!child_valobj_sp)
child_valobj_sp = root->GetSyntheticArrayMemberFromArray(index, true);
+ if (!child_valobj_sp)
+ if (root->HasSyntheticValue() && root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetNumChildren() > index)
+ child_valobj_sp = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
if (child_valobj_sp)
{
root = child_valobj_sp;
@@ -2154,7 +2176,19 @@
}
else
{
- root = root->GetSyntheticArrayMemberFromPointer(index, true);
+ if (ClangASTType::GetMinimumLanguage(root->GetClangAST(),
+ root->GetClangType()) == lldb::eLanguageTypeObjC
+ &&
+ ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false
+ &&
+ root->HasSyntheticValue()
+ &&
+ options.m_no_synthetic_children == false)
+ {
+ root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
+ }
+ else
+ root = root->GetSyntheticArrayMemberFromPointer(index, true);
if (!root.get())
{
*first_unparsed = expression_cstr;
@@ -2170,7 +2204,7 @@
}
}
}
- else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
+ else if (ClangASTContext::IsScalarType(root_clang_type))
{
root = root->GetSyntheticBitFieldChild(index, index, true);
if (!root.get())
@@ -2188,6 +2222,24 @@
return root;
}
}
+ else if (root->HasSyntheticValue() && options.m_no_synthetic_children)
+ {
+ root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
}
else // we have a low and a high index
{
diff --git a/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp
index 1672694..ac1462d 100644
--- a/source/Symbol/ClangASTType.cpp
+++ b/source/Symbol/ClangASTType.cpp
@@ -115,6 +115,8 @@
ConstString
ClangASTType::GetConstTypeName ()
{
+ if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type))
+ return ConstString("<invalid>");
return GetConstTypeName (m_type);
}
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 803e49b..9ce7590 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -525,6 +525,7 @@
{
const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+ const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
error.Clear();
bool deref = false;
bool address_of = false;
@@ -718,14 +719,55 @@
if (valobj_sp->IsPointerType ())
{
- child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
- if (!child_valobj_sp)
+ if (no_synth_child == false
+ &&
+ ClangASTType::GetMinimumLanguage(valobj_sp->GetClangAST(),
+ valobj_sp->GetClangType()) == lldb::eLanguageTypeObjC /* is ObjC pointer */
+ &&
+ ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(valobj_sp->GetClangType())) == false /* is not double-ptr */)
{
- valobj_sp->GetExpressionPath (var_expr_path_strm, false);
- error.SetErrorStringWithFormat ("failed to use pointer as array for index %i for \"(%s) %s\"",
- child_index,
- valobj_sp->GetTypeName().AsCString("<invalid type>"),
- var_expr_path_strm.GetString().c_str());
+ // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children
+ lldb::ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter);
+ if (synthetic.get() == NULL /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the original object */
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else
+ {
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ }
+ else
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("failed to use pointer as array for index %i for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
}
}
else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
@@ -757,10 +799,36 @@
}
else
{
- valobj_sp->GetExpressionPath (var_expr_path_strm, false);
- error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
- valobj_sp->GetTypeName().AsCString("<invalid type>"),
- var_expr_path_strm.GetString().c_str());
+ lldb::ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter);
+ if (no_synth_child /* synthetic is forbidden */ ||
+ synthetic.get() == NULL /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the original object */
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else
+ {
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
}
if (!child_valobj_sp)
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index f1b126d..a5103b4 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -1035,7 +1035,8 @@
frame->CalculateExecutionContext(exe_ctx);
Error error;
const uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar;
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren;
lldb::VariableSP var_sp;
result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr,
use_dynamic,