- Now using ${var} as the summary for an aggregate type will produce "name-of-type @ object-location" instead of giving an error
  e.g. you may get "foo_class @ 0x123456" when typing "type summary add -f ${var} foo_class"
- Added a new special formatting token %T for summaries. This shows the type of the object.
  Using it, the new "type @ location" summary could be manually generated by writing ${var%T} @ ${var%L}
- Bits and pieces required to support "frame variable array[n-m]"
  The feature is not enabled yet because some additional design and support code is required, but the basics
  are getting there
- Fixed a potential issue where a ValueObjectSyntheticFilter was not holding on to its SyntheticChildrenSP
  Because of the way VOSF are being built now, this has never been an actual issue, but it is still sensible for
  a VOSF to hold on to the SyntheticChildrenSP as well as to its FrontEnd


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@138080 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index fead729..07cbe7b 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -744,6 +744,8 @@
                 *val_obj_display = ValueObject::eDisplaySummary;
             else if (*format_name == '#')
                 *val_obj_display = ValueObject::eDisplayChildrenCount;
+            else if (*format_name == 'T')
+                *val_obj_display = ValueObject::eDisplayType;
             else if (log)
                 log->Printf("%s is an error, leaving the previous value alone", format_name);
         }
@@ -1165,25 +1167,52 @@
                                     StreamString str_temp;
                                     if (log)
                                         log->Printf("I am into array || pointer && !range");
-                                    // try to use the special cases
-                                    var_success = target->DumpPrintableRepresentation(str_temp,
-                                                                                      val_obj_display,
-                                                                                      custom_format);
-                                    if (log)
-                                        log->Printf("special cases did%s match", var_success ? "" : "n't");
-                                    if (!var_success)
+                                    
+                                    if (target->HasSpecialCasesForPrintableRepresentation(val_obj_display,
+                                                                                          custom_format))
                                     {
-                                        s << "<invalid usage of pointer value as object>";
+                                        // try to use the special cases
+                                        var_success = target->DumpPrintableRepresentation(str_temp,
+                                                                                          val_obj_display,
+                                                                                          custom_format);
+                                        if (log)
+                                            log->Printf("special cases did%s match", var_success ? "" : "n't");
+                                        
+                                        // should not happen
+                                        if (!var_success)
+                                            s << "<invalid usage of pointer value as object>";
+                                        else
+                                            s << str_temp.GetData();
                                         var_success = true;
+                                        break;
                                     }
                                     else
-                                        s << str_temp.GetData();
+                                    {
+                                        // if ${var}
+                                        if (was_plain_var)
+                                        {
+                                            s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
+                                        }
+                                        else
+                                        {
+                                            s << "<invalid usage of pointer value as object>";
+                                        }
+                                        var_success = true;
+                                        break;
+                                    }
+                                }
+                                
+                                // if directly trying to print ${var}, and this is an aggregate, display a nice
+                                // type @ location message
+                                if (is_aggregate && was_plain_var)
+                                {
+                                    s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
+                                    var_success = true;
                                     break;
                                 }
                                 
-                                // if directly trying to print ${var} using its value, and this is an aggregate, display a nice
-                                // error message about it (and avoid recursion in DumpPrintableRepresentation)
-                                if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eDisplayValue) || was_plain_var))
+                                // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
+                                if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eDisplayValue)))
                                 {
                                     s << "<invalid use of aggregate type>";
                                     var_success = true;
diff --git a/source/Core/FormatClasses.cpp b/source/Core/FormatClasses.cpp
index 9a7b32c..ff46986 100644
--- a/source/Core/FormatClasses.cpp
+++ b/source/Core/FormatClasses.cpp
@@ -181,6 +181,31 @@
     return sstr.GetString();
 }
 
+std::string
+SyntheticArrayView::GetDescription()
+{
+    StreamString sstr;
+    sstr.Printf("%s%s%s {\n",
+                m_cascades ? "" : " (not cascading)",
+                m_skip_pointers ? " (skip pointers)" : "",
+                m_skip_references ? " (skip references)" : "");
+    SyntheticArrayRange* ptr = &m_head;
+    while (ptr && ptr != m_tail)
+    {
+        if (ptr->GetLow() == ptr->GetHigh())
+            sstr.Printf("    [%d]\n",
+                        ptr->GetLow());
+        else
+            sstr.Printf("    [%d-%d]\n",
+                        ptr->GetLow(),
+                        ptr->GetHigh());
+        ptr = ptr->GetNext();
+    }
+    
+    sstr.Printf("}");
+    return sstr.GetString();
+}
+
 SyntheticScriptProvider::FrontEnd::FrontEnd(std::string pclass,
                                             lldb::ValueObjectSP be) :
 SyntheticChildrenFrontEnd(be),
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index aabfd71..a9e2236 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -989,6 +989,9 @@
             snprintf((char*)return_value, 512, "%d", count);
             break;
         }
+        case eDisplayType:
+            return_value = GetTypeName().AsCString();
+            break;
         default:
             break;
     }
@@ -1007,7 +1010,11 @@
                 // this thing has no value, and it seems to have no summary
                 // some combination of unitialized data and other factors can also
                 // raise this condition, so let's print a nice generic error message
-                return_value = "<no available summary>";
+                {
+                    alloc_mem.resize(684);
+                    return_value = &alloc_mem[0];
+                    snprintf((char*)return_value, 684, "%s @ %s", GetTypeName().AsCString(), GetLocationAsCString());
+                }
             }
             else
                 return_value = GetValueAsCString();
@@ -1026,6 +1033,50 @@
     
 }
 
+// if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep
+// this call up to date by returning true for your new special cases. We will eventually move
+// to checking this call result before trying to display special cases
+bool
+ValueObject::HasSpecialCasesForPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,
+                                                       lldb::Format custom_format)
+{
+    clang_type_t elem_or_pointee_type;
+    Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type));
+    
+    if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer)
+        && val_obj_display == ValueObject::eDisplayValue)
+    {        
+        if (IsCStringContainer(true) && 
+            (custom_format == lldb::eFormatCString ||
+             custom_format == lldb::eFormatCharArray ||
+             custom_format == lldb::eFormatChar ||
+             custom_format == lldb::eFormatVectorOfChar))
+            return true;
+
+        if (flags.Test(ClangASTContext::eTypeIsArray))
+        {
+            if ((custom_format == lldb::eFormatBytes) ||
+                (custom_format == lldb::eFormatBytesWithASCII))
+                return true;
+            
+            if ((custom_format == lldb::eFormatVectorOfChar) ||
+                (custom_format == lldb::eFormatVectorOfFloat32) ||
+                (custom_format == lldb::eFormatVectorOfFloat64) ||
+                (custom_format == lldb::eFormatVectorOfSInt16) ||
+                (custom_format == lldb::eFormatVectorOfSInt32) ||
+                (custom_format == lldb::eFormatVectorOfSInt64) ||
+                (custom_format == lldb::eFormatVectorOfSInt8) ||
+                (custom_format == lldb::eFormatVectorOfUInt128) ||
+                (custom_format == lldb::eFormatVectorOfUInt16) ||
+                (custom_format == lldb::eFormatVectorOfUInt32) ||
+                (custom_format == lldb::eFormatVectorOfUInt64) ||
+                (custom_format == lldb::eFormatVectorOfUInt8))
+                return true;
+        }
+    }
+    return false;
+}
+
 bool
 ValueObject::DumpPrintableRepresentation(Stream& s,
                                          ValueObjectRepresentationStyle val_obj_display,
@@ -1380,6 +1431,19 @@
     return ClangASTContext::IsPossibleDynamicType (GetClangAST (), GetClangType());
 }
 
+lldb::ValueObjectSP
+ValueObject::GetSyntheticArrayMember (int32_t index, bool can_create)
+{
+    if (IsArrayType())
+        return GetSyntheticArrayMemberFromArray(index, can_create);
+
+    if (IsPointerType())
+        return GetSyntheticArrayMemberFromPointer(index, can_create);
+    
+    return ValueObjectSP();
+    
+}
+
 ValueObjectSP
 ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create)
 {
@@ -1497,6 +1561,42 @@
 }
 
 lldb::ValueObjectSP
+ValueObject::GetSyntheticArrayRangeChild (uint32_t from, uint32_t to, bool can_create)
+{
+    ValueObjectSP synthetic_child_sp;
+    if (IsArrayType () || IsPointerType ())
+    {
+        char index_str[64];
+        snprintf(index_str, sizeof(index_str), "[%i-%i]", 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)
+        {
+            ValueObjectSynthetic *synthetic_child;
+            
+            // We haven't made a synthetic array member for INDEX yet, so
+            // lets make one and cache it for any future reference.
+            SyntheticArrayView *view = new SyntheticArrayView();
+            view->AddRange(from,to);
+            SyntheticChildrenSP view_sp(view);
+            synthetic_child = new ValueObjectSynthetic(*this, view_sp);
+            
+            // 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_is_bitfield_for_scalar = true;
+            }
+        }
+    }
+    return synthetic_child_sp;
+}
+
+lldb::ValueObjectSP
 ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create)
 {
     
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index f48597e..31d3fa1 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -40,6 +40,7 @@
     m_address (),
     m_type_sp(),
     m_use_synthetic (lldb::eUseSyntheticFilter),
+    m_synth_sp(filter),
     m_synth_filter(filter->GetFrontEnd(parent.GetSP())),
     m_children_byindex(),
     m_name_toindex()
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 299fdd1..35df2d2 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -526,6 +526,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;
+        const bool no_synth_array = (options & eExpressionPathOptionsNoSyntheticArrayRange) != 0;
         error.Clear();
         bool deref = false;
         bool address_of = false;
@@ -861,6 +862,7 @@
                                 // this is most probably a BitField, let's take a look
                                 char *real_end = NULL;
                                 long final_index = ::strtol (end+1, &real_end, 0);
+                                bool expand_bitfield = true;
                                 if (real_end && *real_end == ']')
                                 {
                                     // if the format given is [high-low], swap range
@@ -908,15 +910,31 @@
                                         valobj_sp = temp;
                                         deref = false;
                                     }
-
-                                    child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
-                                    if (!child_valobj_sp)
+                                    /*else if (valobj_sp->IsArrayType() || valobj_sp->IsPointerType())
                                     {
-                                        valobj_sp->GetExpressionPath (var_expr_path_strm, false);
-                                        error.SetErrorStringWithFormat ("bitfield range %i-%i is not valid for \"(%s) %s\"", 
-                                                                        child_index, final_index, 
-                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
-                                                                        var_expr_path_strm.GetString().c_str());
+                                        child_valobj_sp = valobj_sp->GetSyntheticArrayRangeChild(child_index, final_index, true);
+                                        expand_bitfield = false;
+                                        if (!child_valobj_sp)
+                                        {
+                                            valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                            error.SetErrorStringWithFormat ("array range %i-%i is not valid for \"(%s) %s\"", 
+                                                                            child_index, final_index, 
+                                                                            valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                            var_expr_path_strm.GetString().c_str());
+                                        }
+                                    }*/
+
+                                    if (expand_bitfield)
+                                    {
+                                        child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
+                                        if (!child_valobj_sp)
+                                        {
+                                            valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                            error.SetErrorStringWithFormat ("bitfield range %i-%i is not valid for \"(%s) %s\"", 
+                                                                            child_index, final_index, 
+                                                                            valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                            var_expr_path_strm.GetString().c_str());
+                                        }
                                     }
                                 }