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/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)