[Lldb-commits] [lldb] r138080 - in /lldb/trunk: include/lldb/Core/ include/lldb/Target/ source/Core/ source/Target/ test/functionalities/data-formatter/data-formatter-cpp/ test/functionalities/data-formatter/rdar-9973865/ test/functionalities/data-formatter/rdar-9973992/

Enrico Granata granata.enrico at gmail.com
Fri Aug 19 14:13:46 PDT 2011


Author: enrico
Date: Fri Aug 19 16:13:46 2011
New Revision: 138080

URL: http://llvm.org/viewvc/llvm-project?rev=138080&view=rev
Log:
- 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

Added:
    lldb/trunk/test/functionalities/data-formatter/rdar-9973992/
    lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Makefile
    lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Test-rdar-9973992.py
    lldb/trunk/test/functionalities/data-formatter/rdar-9973992/main.cpp
Modified:
    lldb/trunk/include/lldb/Core/FormatClasses.h
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h
    lldb/trunk/include/lldb/Target/StackFrame.h
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Core/FormatClasses.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
    lldb/trunk/test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py

Modified: lldb/trunk/include/lldb/Core/FormatClasses.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatClasses.h?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatClasses.h (original)
+++ lldb/trunk/include/lldb/Core/FormatClasses.h Fri Aug 19 16:13:46 2011
@@ -384,6 +384,241 @@
     
 };
 
+struct SyntheticArrayRange
+{
+private:
+    int m_low;
+    int m_high;
+    SyntheticArrayRange* m_next;
+    
+public:
+    
+    SyntheticArrayRange () : 
+        m_low(-1),
+        m_high(-2),
+        m_next(NULL)
+    {}
+
+    SyntheticArrayRange (int L) : 
+        m_low(L),
+        m_high(L),
+        m_next(NULL)
+    {}
+    
+    SyntheticArrayRange (int L, int H) : 
+        m_low(L),
+        m_high(H),
+        m_next(NULL)
+    {}
+    
+    SyntheticArrayRange (int L, int H, SyntheticArrayRange* N) : 
+        m_low(L),
+        m_high(H),
+        m_next(N)
+    {}
+    
+    inline int
+    GetLow ()
+    {
+        return m_low;
+    }
+    
+    inline int
+    GetHigh ()
+    {
+        return m_high;
+    }
+    
+    inline void
+    SetLow (int L)
+    {
+        m_low = L;
+    }
+    
+    inline void
+    SetHigh (int H)
+    {
+        m_high = H;
+    }
+    
+    inline  int
+    GetSelfCount()
+    {
+        return GetHigh() - GetLow() + 1;
+    }
+    
+    int
+    GetCount()
+    {
+        int count = GetSelfCount();
+        if (m_next)
+            count += m_next->GetCount();
+        return count;
+    }
+    
+    inline SyntheticArrayRange*
+    GetNext()
+    {
+        return m_next;
+    }
+    
+    void
+    SetNext(SyntheticArrayRange* N)
+    {
+        if (m_next)
+            delete m_next;
+        m_next = N;
+    }
+    
+    void
+    SetNext(int L, int H)
+    {
+        if (m_next)
+            delete m_next;
+        m_next = new SyntheticArrayRange(L, H);
+    }
+    
+    void
+    SetNext(int L)
+    {
+        if (m_next)
+            delete m_next;
+        m_next = new SyntheticArrayRange(L);
+    }
+    
+    ~SyntheticArrayRange()
+    {
+        delete m_next;
+        m_next = NULL;
+    }
+    
+};
+    
+class SyntheticArrayView : public SyntheticChildren
+{
+    SyntheticArrayRange m_head;
+    SyntheticArrayRange *m_tail;
+public:
+    SyntheticArrayView(bool casc = false,
+                       bool skipptr = false,
+                       bool skipref = false) :
+    SyntheticChildren(casc, skipptr, skipref),
+    m_head(),
+    m_tail(&m_head)
+    {
+    }
+    
+    void
+    AddRange(int L, int H)
+    {
+        m_tail->SetLow(L);
+        m_tail->SetHigh(H);
+        m_tail->SetNext(new SyntheticArrayRange());
+        m_tail = m_tail->GetNext();
+    }
+    
+    int
+    GetCount()
+    {
+        return m_head.GetCount();
+    }
+    
+    const int
+    GetRealIndexForIndex(int i)
+    {
+        if (i >= GetCount())
+            return -1;
+        
+        SyntheticArrayRange* ptr = &m_head;
+        
+        int residual = i;
+        
+        while(ptr && ptr != m_tail)
+        {
+            if (residual >= ptr->GetSelfCount())
+            {
+                residual -= ptr->GetSelfCount();
+                ptr = ptr->GetNext();
+            }
+            
+            return ptr->GetLow() + residual;
+        }
+        
+        return -1;
+        
+    }
+    
+    bool
+    IsScripted()
+    {
+        return false;
+    }
+    
+    std::string
+    GetDescription();
+    
+    class FrontEnd : public SyntheticChildrenFrontEnd
+    {
+    private:
+        SyntheticArrayView* filter;
+    public:
+        
+        FrontEnd(SyntheticArrayView* flt,
+                 lldb::ValueObjectSP be) :
+        SyntheticChildrenFrontEnd(be),
+        filter(flt)
+        {}
+        
+        virtual
+        ~FrontEnd()
+        {
+        }
+        
+        virtual uint32_t
+        CalculateNumChildren()
+        {
+            return filter->GetCount();
+        }
+        
+        virtual lldb::ValueObjectSP
+        GetChildAtIndex (uint32_t idx, bool can_create)
+        {
+            if (idx >= filter->GetCount())
+                return lldb::ValueObjectSP();
+            return m_backend->GetSyntheticArrayMember(filter->GetRealIndexForIndex(idx), can_create);
+        }
+        
+        virtual void
+        Update() {}
+        
+        virtual uint32_t
+        GetIndexOfChildWithName (const ConstString &name_cs)
+        {
+            const char* name_cstr = name_cs.GetCString();
+            if (*name_cstr != '[')
+                return UINT32_MAX;
+            std::string name(name_cstr+1);
+            if (name[name.size()-1] != ']')
+                return UINT32_MAX;
+            name = name.erase(name.size()-1,1);
+            int index = Args::StringToSInt32 (name.c_str(), -1);
+            if (index < 0)
+                return UINT32_MAX;
+            return index;
+        }
+        
+        typedef lldb::SharedPtr<SyntheticChildrenFrontEnd>::Type SharedPointer;
+        
+    };
+    
+    virtual SyntheticChildrenFrontEnd::SharedPointer
+    GetFrontEnd(lldb::ValueObjectSP backend)
+    {
+        return SyntheticChildrenFrontEnd::SharedPointer(new FrontEnd(this, backend));
+    }
+    
+};
+
 
 struct SummaryFormat
 {

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Fri Aug 19 16:13:46 2011
@@ -79,7 +79,8 @@
         eDisplaySummary,
         eDisplayLanguageSpecific,
         eDisplayLocation,
-        eDisplayChildrenCount
+        eDisplayChildrenCount,
+        eDisplayType
     };
     
     enum ExpressionPathScanEndReason
@@ -658,6 +659,10 @@
                                lldb::Format custom_format = lldb::eFormatInvalid);
 
     bool
+    HasSpecialCasesForPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,
+                                              lldb::Format custom_format);
+    
+    bool
     DumpPrintableRepresentation(Stream& s,
                                 ValueObjectRepresentationStyle val_obj_display = eDisplaySummary,
                                 lldb::Format custom_format = lldb::eFormatInvalid,
@@ -693,6 +698,9 @@
 public:
     lldb::ValueObjectSP
     GetSyntheticChild (const ConstString &key) const;
+    
+    lldb::ValueObjectSP
+    GetSyntheticArrayMember (int32_t index, bool can_create);
 
     lldb::ValueObjectSP
     GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create);
@@ -704,6 +712,9 @@
     GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create);
     
     lldb::ValueObjectSP
+    GetSyntheticArrayRangeChild (uint32_t from, uint32_t to, bool can_create);
+    
+    lldb::ValueObjectSP
     GetSyntheticExpressionPathChild(const char* expression, bool can_create);
     
     virtual lldb::ValueObjectSP

Modified: lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h Fri Aug 19 16:13:46 2011
@@ -24,9 +24,9 @@
 //----------------------------------------------------------------------
 // A ValueObject that obtains its children from some source other than
 // real information
-// This is currently used to implement children filtering, where only
-// a subset of the real children are shown, but it can be used for any
-// source of made-up children information
+// This is currently used to implement Python-based children and filters
+// but you can bind it to any source of synthetic information and have
+// it behave accordingly
 //----------------------------------------------------------------------
 class ValueObjectSynthetic : public ValueObject
 {
@@ -121,6 +121,7 @@
     lldb::TypeSP m_type_sp;
     lldb::ValueObjectSP m_owning_valobj_sp;
     lldb::SyntheticValueType m_use_synthetic;
+    lldb::SyntheticChildrenSP m_synth_sp;   // hold on to your synthetic children provider
     lldb::SyntheticChildrenFrontEndSP m_synth_filter;
     
     typedef std::map<uint32_t, lldb::ValueObjectSP> ByIndexMap;

Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Fri Aug 19 16:13:46 2011
@@ -32,9 +32,10 @@
 public:
     enum ExpressionPathOption
     {
-        eExpressionPathOptionCheckPtrVsMember     = (1u << 0),
-        eExpressionPathOptionsNoFragileObjcIvar   = (1u << 1),
-        eExpressionPathOptionsNoSyntheticChildren = (1u << 2)
+        eExpressionPathOptionCheckPtrVsMember       = (1u << 0),
+        eExpressionPathOptionsNoFragileObjcIvar     = (1u << 1),
+        eExpressionPathOptionsNoSyntheticChildren   = (1u << 2),
+        eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
     };
     //------------------------------------------------------------------
     // Constructors and Destructors

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Fri Aug 19 16:13:46 2011
@@ -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;

Modified: lldb/trunk/source/Core/FormatClasses.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatClasses.cpp?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatClasses.cpp (original)
+++ lldb/trunk/source/Core/FormatClasses.cpp Fri Aug 19 16:13:46 2011
@@ -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),

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Fri Aug 19 16:13:46 2011
@@ -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)
 {
     

Modified: lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp Fri Aug 19 16:13:46 2011
@@ -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()

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Fri Aug 19 16:13:46 2011
@@ -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;
                                     }
+                                    /*else if (valobj_sp->IsArrayType() || valobj_sp->IsPointerType())
+                                    {
+                                        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());
+                                        }
+                                    }*/
 
-                                    child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
-                                    if (!child_valobj_sp)
+                                    if (expand_bitfield)
                                     {
-                                        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->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());
+                                        }
                                     }
                                 }
                                 

Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Fri Aug 19 16:13:46 2011
@@ -195,7 +195,34 @@
                        '[2] = cool object @ 0x',
                        '[3] = cool object @ 0x',
                        '[4] = cool object @ 0x'])
+                            
+        # test getting similar output by exploiting ${var} = 'type @ location' for aggregates
+        self.runCmd("type summary add -f \"${var}\" i_am_cool")
+        
+        # this test might fail if the compiler tries to store
+        # these values into registers.. hopefully this is not
+        # going to be the case
+        self.expect("frame variable cool_array",
+                    substrs = ['[0] = i_am_cool @ 0x',
+                               '[1] = i_am_cool @ 0x',
+                               '[2] = i_am_cool @ 0x',
+                               '[3] = i_am_cool @ 0x',
+                               '[4] = i_am_cool @ 0x'])
+
             
+        # test getting same output by exploiting %T and %L together for aggregates
+        self.runCmd("type summary add -f \"${var%T} @ ${var%L}\" i_am_cool")
+        
+        # this test might fail if the compiler tries to store
+        # these values into registers.. hopefully this is not
+        # going to be the case
+        self.expect("frame variable cool_array",
+                    substrs = ['[0] = i_am_cool @ 0x',
+                               '[1] = i_am_cool @ 0x',
+                               '[2] = i_am_cool @ 0x',
+                               '[3] = i_am_cool @ 0x',
+                               '[4] = i_am_cool @ 0x'])
+                            
         self.runCmd("type summary add -f \"goofy\" i_am_cool")
         self.runCmd("type summary add -f \"${var.second_cool%S}\" i_am_cooler")
 

Modified: lldb/trunk/test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py?rev=138080&r1=138079&r2=138080&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py Fri Aug 19 16:13:46 2011
@@ -56,10 +56,10 @@
         self.runCmd("type summary add -f \"SUMMARY SUCCESS ${var}\" Summarize")
         
         self.expect('frame variable mine_ptr',
-                substrs = ['SUMMARY SUCCESS <invalid usage of pointer value as object>'])
+                substrs = ['SUMMARY SUCCESS summarize_ptr_t @ '])
 
         self.expect('frame variable *mine_ptr',
-                substrs = ['SUMMARY SUCCESS <invalid use of aggregate type>'])
+                substrs = ['SUMMARY SUCCESS summarize_t @'])
 
         self.runCmd("type summary add -f \"SUMMARY SUCCESS ${var.first}\" Summarize")
 

Added: lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Makefile?rev=138080&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Makefile Fri Aug 19 16:13:46 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Test-rdar-9973992.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Test-rdar-9973992.py?rev=138080&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Test-rdar-9973992.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/rdar-9973992/Test-rdar-9973992.py Fri Aug 19 16:13:46 2011
@@ -0,0 +1,90 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class DataFormatterTestCase(TestBase):
+
+    # test for rdar://problem/9973992 (What should we do for "${var}" in summaries of aggregate types?)
+    mydir = os.path.join("functionalities", "data-formatter", "rdar-9973992")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    def test_with_dsym_and_run_command(self):
+        """Test data formatter commands."""
+        self.buildDsym()
+        self.data_formatter_commands()
+
+    def test_with_dwarf_and_run_command(self):
+        """Test data formatter commands."""
+        self.buildDwarf()
+        self.data_formatter_commands()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number to break at.
+        self.line = line_number('main.cpp', '// Set break point at this line.')
+
+    def data_formatter_commands(self):
+        """Test that that file and class static variables display correctly."""
+        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+        self.expect("breakpoint set -f main.cpp -l %d" % self.line,
+                    BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" %
+                        self.line)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # This is the function to remove the custom formats in order to have a
+        # clean slate for the next test case.
+        def cleanup():
+            self.runCmd('type summary clear', check=False)
+
+        # Execute the cleanup function during test case tear down.
+        self.addTearDownHook(cleanup)
+
+        self.runCmd("type summary add -f \"SUMMARY SUCCESS ${var}\" Summarize")
+        
+        self.expect('frame variable mine_ptr',
+                substrs = ['SUMMARY SUCCESS summarize_ptr_t @ '])
+
+        self.expect('frame variable *mine_ptr',
+                substrs = ['SUMMARY SUCCESS summarize_t @'])
+
+        self.runCmd("type summary add -f \"SUMMARY SUCCESS ${var.first}\" Summarize")
+
+        self.expect('frame variable mine_ptr',
+                    substrs = ['SUMMARY SUCCESS 10'])
+
+        self.expect('frame variable *mine_ptr',
+                    substrs = ['SUMMARY SUCCESS 10'])
+            
+        self.runCmd("type summary add -f \"${var}\" Summarize")
+        self.runCmd("type summary add -f \"${var}\" -e TwoSummarizes")
+            
+        self.expect('frame variable',
+            substrs = ['(TwoSummarizes) twos = TwoSummarizes @ ',
+                       'first = summarize_t @ ',
+                       'second = summarize_t @ '])
+                    
+        self.runCmd("type summary add -f \"SUMMARY SUCCESS ${var.first}\" Summarize")
+        self.expect('frame variable',
+                    substrs = ['(TwoSummarizes) twos = TwoSummarizes @ ',
+                               'first = SUMMARY SUCCESS 1',
+                               'second = SUMMARY SUCCESS 3'])
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/data-formatter/rdar-9973992/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/rdar-9973992/main.cpp?rev=138080&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/rdar-9973992/main.cpp (added)
+++ lldb/trunk/test/functionalities/data-formatter/rdar-9973992/main.cpp Fri Aug 19 16:13:46 2011
@@ -0,0 +1,41 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+struct Summarize
+{
+    int first;
+    int second;
+};
+
+typedef struct Summarize summarize_t;
+typedef summarize_t *summarize_ptr_t;
+
+summarize_t global_mine = {30, 40};
+
+struct TwoSummarizes
+{
+    summarize_t first;
+    summarize_t second;
+};
+
+int
+main()
+{
+    summarize_t mine = {10, 20};
+    summarize_ptr_t mine_ptr = &mine;
+    
+    TwoSummarizes twos = { {1,2}, {3,4} };
+    
+    printf ("Summarize: first: %d second: %d and address: 0x%p\n", mine.first, mine.second, mine_ptr); // Set break point at this line.
+    printf ("Global summarize: first: %d second: %d.\n", global_mine.first, global_mine.second);
+    return 0;
+}
+
+





More information about the lldb-commits mailing list