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,