[Lldb-commits] [lldb] r135731 - in /lldb/trunk: include/lldb/ include/lldb/Core/ include/lldb/Interpreter/ lldb.xcodeproj/ source/API/ source/Commands/ source/Core/ source/Interpreter/ test/functionalities/data-formatter/data-formatter-categories/ test/functionalities/data-formatter/data-formatter-cpp/ test/functionalities/data-formatter/data-formatter-synth/ www/

Enrico Granata granata.enrico at gmail.com
Thu Jul 21 17:16:09 PDT 2011


Author: enrico
Date: Thu Jul 21 19:16:08 2011
New Revision: 135731

URL: http://llvm.org/viewvc/llvm-project?rev=135731&view=rev
Log:
when typing a summary string you can use the %S symbol to explicitly indicate that you want the summary to be used to print the target object
 (e.g. ${var%S}). this might already be the default if your variable is of an aggregate type
new feature: synthetic filters. you can restrict the number of children for your variables to only a meaningful subset
 - the restricted list of children obeys the typical rules (e.g. summaries prevail over children)
 - one-line summaries show only the filtered (synthetic) children, if you type an expanded summary string, or you use Python scripts, all the real children are accessible
 - to provide a synthetic children list use the "type synth add" command, as in:
   type synth add foo_type --child varA --child varB[0] --child varC->packet->flags[1-4]
   (you can use ., ->, single-item array operator [N] and bitfield operator [N-M]; array slice access is not supported, giving simplified names to expression paths is not supported)
 - a new -S option to frame variable and target variable lets you override synthetic children and instead show real ones

Added:
    lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h
    lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp
    lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/
    lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/Makefile
    lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/main.cpp
Modified:
    lldb/trunk/include/lldb/Core/Debugger.h
    lldb/trunk/include/lldb/Core/FormatClasses.h
    lldb/trunk/include/lldb/Core/FormatManager.h
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/include/lldb/lldb-forward-rtti.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBValue.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Commands/CommandObjectFrame.cpp
    lldb/trunk/source/Commands/CommandObjectMemory.cpp
    lldb/trunk/source/Commands/CommandObjectTarget.cpp
    lldb/trunk/source/Commands/CommandObjectType.cpp
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Core/FormatClasses.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp
    lldb/trunk/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp
    lldb/trunk/www/varformats.html

Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Thu Jul 21 19:16:08 2011
@@ -505,6 +505,9 @@
         static bool
         GetSummaryFormat(ValueObject& vobj,
                          lldb::SummaryFormatSP& entry);
+        static bool
+        GetSyntheticFilter(ValueObject& vobj,
+                           lldb::SyntheticFilterSP& entry);
         
         class NamedSummaryFormats
         {

Modified: lldb/trunk/include/lldb/Core/FormatClasses.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatClasses.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatClasses.h (original)
+++ lldb/trunk/include/lldb/Core/FormatClasses.h Thu Jul 21 19:16:08 2011
@@ -17,6 +17,7 @@
 
 // C++ Includes
 #include <string>
+#include <vector>
 
 // Other libraries and framework includes
 
@@ -55,23 +56,23 @@
     }
     
     bool
-    Cascades()
+    Cascades() const
     {
         return m_cascades;
     }
     bool
-    SkipsPointers()
+    SkipsPointers() const
     {
         return m_skip_pointers;
     }
     bool
-    SkipsReferences()
+    SkipsReferences() const
     {
         return m_skip_references;
     }
     
     lldb::Format
-    GetFormat()
+    GetFormat() const
     {
         return m_format;
     }
@@ -80,6 +81,57 @@
     FormatObject(lldb::ValueObjectSP object);
     
 };
+    
+struct SyntheticFilter
+{
+    bool m_cascades;
+    bool m_skip_pointers;
+    bool m_skip_references;
+    std::vector<std::string> m_expression_paths;
+    
+    SyntheticFilter(bool casc = false,
+                    bool skipptr = false,
+                    bool skipref = false) :
+    m_cascades(casc),
+    m_skip_pointers(skipptr),
+    m_skip_references(skipref),
+    m_expression_paths()
+    {
+    }
+    
+    void
+    AddExpressionPath(std::string path)
+    {
+        bool need_add_dot = true;
+        if (path[0] == '.' ||
+            (path[0] == '-' && path[1] == '>') ||
+            path[0] == '[')
+            need_add_dot = false;
+        // add a '.' symbol to help forgetful users
+        if(!need_add_dot)
+            m_expression_paths.push_back(path);
+        else
+            m_expression_paths.push_back(std::string(".") + path);
+    }
+        
+    int
+    GetCount() const
+    {
+        return m_expression_paths.size();
+    }
+    
+    const std::string&
+    GetExpressionPathAtIndex(int i) const
+    {
+        return m_expression_paths[i];
+    }
+    
+    std::string
+    GetDescription();
+    
+    typedef lldb::SharedPtr<SyntheticFilter>::Type SharedPointer;
+    typedef bool(*SyntheticFilterCallback)(void*, const char*, const SyntheticFilter::SharedPointer&);
+};
 
 struct SummaryFormat
 {
@@ -106,17 +158,17 @@
     }
     
     bool
-    Cascades()
+    Cascades() const
     {
         return m_cascades;
     }
     bool
-    SkipsPointers()
+    SkipsPointers() const
     {
         return m_skip_pointers;
     }
     bool
-    SkipsReferences()
+    SkipsReferences() const
     {
         return m_skip_references;
     }
@@ -174,7 +226,7 @@
     }
     
     std::string
-    GetFormat()
+    GetFormat() const
     {
         return m_format;
     }
@@ -213,13 +265,13 @@
     }
     
     std::string
-    GetFunctionName()
+    GetFunctionName() const
     {
         return m_function_name;
     }
     
     std::string
-    GetPythonScript()
+    GetPythonScript() const
     {
         return m_python_script;
     }

Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Thu Jul 21 19:16:08 2011
@@ -415,12 +415,15 @@
 private:
     typedef FormatNavigator<const char*, SummaryFormat> SummaryNavigator;
     typedef FormatNavigator<lldb::RegularExpressionSP, SummaryFormat> RegexSummaryNavigator;
+    typedef FormatNavigator<const char*, SyntheticFilter> FilterNavigator;
     
     typedef SummaryNavigator::MapType SummaryMap;
     typedef RegexSummaryNavigator::MapType RegexSummaryMap;
+    typedef FilterNavigator::MapType FilterMap;
         
     SummaryNavigator::SharedPointer m_summary_nav;
     RegexSummaryNavigator::SharedPointer m_regex_summary_nav;
+    FilterNavigator::SharedPointer m_filter_nav;
     
     bool m_enabled;
     
@@ -428,6 +431,8 @@
     
     Mutex m_mutex;
     
+    std::string m_name;
+    
     void
     Enable(bool value = true)
     {
@@ -449,13 +454,17 @@
     
     typedef SummaryNavigator::SharedPointer SummaryNavigatorSP;
     typedef RegexSummaryNavigator::SharedPointer RegexSummaryNavigatorSP;
+    typedef FilterNavigator::SharedPointer FilterNavigatorSP;
     
-    FormatCategory(IFormatChangeListener* clist) :
+    FormatCategory(IFormatChangeListener* clist,
+                   std::string name) :
     m_summary_nav(new SummaryNavigator(clist)),
     m_regex_summary_nav(new RegexSummaryNavigator(clist)),
+    m_filter_nav(new FilterNavigator(clist)),
     m_enabled(false),
     m_change_listener(clist),
-    m_mutex(Mutex::eMutexTypeRecursive)
+    m_mutex(Mutex::eMutexTypeRecursive),
+    m_name(name)
     {}
     
     SummaryNavigatorSP
@@ -470,6 +479,12 @@
         return RegexSummaryNavigatorSP(m_regex_summary_nav);
     }
     
+    FilterNavigatorSP
+    Filter()
+    {
+        return FilterNavigatorSP(m_filter_nav);
+    }
+    
     bool
     IsEnabled() const
     {
@@ -491,15 +506,27 @@
         return regex;
     }
     
+    bool
+    Get(ValueObject& vobj,
+        lldb::SyntheticFilterSP& entry,
+        uint32_t* reason = NULL)
+    {
+        if (!IsEnabled())
+            return false;
+        return (Filter()->Get(vobj, entry, reason));
+    }
+    
+    // just a shortcut for Summary()->Clear; RegexSummary()->Clear()
     void
-    Clear()
+    ClearSummaries()
     {
         m_summary_nav->Clear();
         m_regex_summary_nav->Clear();
     }
     
+    // just a shortcut for (Summary()->Delete(name) || RegexSummary()->Delete(name))
     bool
-    Delete(const char* name)
+    DeleteSummaries(const char* name)
     {
         bool del_sum = m_summary_nav->Delete(name);
         bool del_rex = m_regex_summary_nav->Delete(name);
@@ -513,6 +540,12 @@
         return Summary()->GetCount() + RegexSummary()->GetCount();
     }
     
+    std::string
+    GetName()
+    {
+        return m_name;
+    }
+    
     typedef lldb::SharedPtr<FormatCategory>::Type SharedPointer;
 };
 
@@ -648,23 +681,6 @@
         return true;
     }
     
-    class match_category_to_name
-    {
-    private:
-        FormatCategory* addr;
-    public:
-        
-        match_category_to_name(FormatCategory* ptr) : addr(ptr)
-        {}
-        
-        bool operator()(std::pair<const char*,FormatCategory::SharedPointer> map_entry)
-        {
-            if (addr == map_entry.second.get())
-                return true;
-            return false;
-        }
-    };
-    
     void
     LoopThrough(CallbackType callback, void* param)
     {
@@ -678,13 +694,7 @@
                 for (begin = m_active_categories.begin(); begin != end; begin++)
                 {
                     FormatCategory::SharedPointer category = *begin;
-                    const char* type;
-                    MapIterator type_position = 
-                    std::find_if(m_map.begin(),m_map.end(),match_category_to_name(category.get()));
-                    if (type_position != m_map.end())
-                        type = type_position->first;
-                    else
-                        continue;
+                    const char* type = category->GetName().c_str();
                     if (!callback(param, type, category))
                         break;
                 }
@@ -741,6 +751,38 @@
         }
         return !first;
     }
+    
+    bool
+    Get(ValueObject& vobj,
+        lldb::SyntheticFilterSP& entry)
+    {
+        Mutex::Locker(m_map_mutex);
+        
+        uint32_t reason_why;
+        bool first = true;
+        
+        ActiveCategoriesIterator begin, end = m_active_categories.end();
+        
+        for (begin = m_active_categories.begin(); begin != end; begin++)
+        {
+            FormatCategory::SharedPointer category = *begin;
+            lldb::SyntheticFilterSP current_format;
+            if (!category->Get(vobj, current_format, &reason_why))
+                continue;
+            if (reason_why == lldb::eFormatterDirectChoice)
+            {
+                entry = current_format;
+                return true;
+            }
+            else if (first)
+            {
+                entry = current_format;
+                first = false;
+            }
+        }
+        return !first;
+    }
+
 };
 
 
@@ -856,7 +898,7 @@
         lldb::FormatCategorySP category;
         if (m_categories_map.Get(category_name, category))
             return category;
-        Categories().Add(category_name,lldb::FormatCategorySP(new FormatCategory(this)));
+        Categories().Add(category_name,lldb::FormatCategorySP(new FormatCategory(this, category_name)));
         return Category(category_name);
     }
     
@@ -866,6 +908,12 @@
     {
         return m_categories_map.Get(vobj, entry);
     }
+    bool
+    Get(ValueObject& vobj,
+        lldb::SyntheticFilterSP& entry)
+    {
+        return m_categories_map.Get(vobj, entry);
+    }
 
     static bool
     GetFormatFromCString (const char *format_cstr,

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Thu Jul 21 19:16:08 2011
@@ -466,7 +466,7 @@
     const ConstString &
     GetName() const;
 
-    lldb::ValueObjectSP
+    virtual lldb::ValueObjectSP
     GetChildAtIndex (uint32_t idx, bool can_create);
 
     virtual lldb::ValueObjectSP
@@ -546,8 +546,14 @@
     GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create);
     
     lldb::ValueObjectSP
+    GetSyntheticExpressionPathChild(const char* expression, bool can_create);
+    
+    lldb::ValueObjectSP
     GetDynamicValue (lldb::DynamicValueType valueType);
     
+    lldb::ValueObjectSP
+    GetSyntheticValue (lldb::SyntheticValueType use_synthetic);
+    
     virtual lldb::ValueObjectSP
     CreateConstantValue (const ConstString &name);
 
@@ -592,6 +598,7 @@
                      bool show_location,
                      bool use_objc,
                      lldb::DynamicValueType use_dynamic,
+                     bool use_synthetic,
                      bool scope_already_checked,
                      bool flat_output,
                      uint32_t omit_summary_depth);
@@ -727,6 +734,7 @@
     std::vector<ValueObject *> m_children;
     std::map<ConstString, ValueObject *> m_synthetic_children;
     ValueObject *m_dynamic_value;
+    ValueObject *m_synthetic_value;
     lldb::ValueObjectSP m_addr_of_valobj_sp; // We have to hold onto a shared pointer to this one because it is created
                                              // as an independent ValueObjectConstResult, which isn't managed by us.
     ValueObject *m_deref_valobj;
@@ -736,6 +744,7 @@
     lldb::SummaryFormatSP   m_last_summary_format;
     lldb::SummaryFormatSP   m_forced_summary_format;
     lldb::ValueFormatSP     m_last_value_format;
+    lldb::SyntheticFilterSP m_last_synthetic_filter;
     lldb::user_id_t         m_user_id_of_forced_summary;
     bool                m_value_is_valid:1,
                         m_value_did_change:1,
@@ -744,7 +753,8 @@
                         m_pointers_point_to_load_addrs:1,
                         m_is_deref_of_parent:1,
                         m_is_array_item_for_pointer:1,
-                        m_is_bitfield_for_scalar:1;
+                        m_is_bitfield_for_scalar:1,
+                        m_is_expression_path_child:1;
     
     // used to prevent endless looping into GetpPrintableRepresentation()
     uint32_t            m_dump_printable_counter;
@@ -782,6 +792,9 @@
     virtual void
     CalculateDynamicValue (lldb::DynamicValueType use_dynamic);
     
+    virtual void
+    CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic);
+    
     // Should only be called by ValueObject::GetChildAtIndex()
     // Returns a ValueObject managed by this ValueObject's manager.
     virtual ValueObject *

Added: lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h?rev=135731&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h (added)
+++ lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h Thu Jul 21 19:16:08 2011
@@ -0,0 +1,122 @@
+//===-- ValueObjectSyntheticFilter.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ValueObjectSyntheticFilter_h_
+#define liblldb_ValueObjectSyntheticFilter_h_
+
+// C Includes
+// C++ Includes
+#include <ostream>
+#include <vector>
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ValueObject.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+// A ValueObject that represents memory at a given address, viewed as some 
+// set lldb type.
+//----------------------------------------------------------------------
+class ValueObjectSyntheticFilter : public ValueObject
+{
+public:
+    virtual
+    ~ValueObjectSyntheticFilter();
+
+    virtual size_t
+    GetByteSize();
+
+    virtual clang::ASTContext *
+    GetClangAST ();
+
+    virtual lldb::clang_type_t
+    GetClangType ();
+
+    virtual ConstString
+    GetTypeName();
+
+    virtual uint32_t
+    CalculateNumChildren();
+
+    virtual lldb::ValueType
+    GetValueType() const;
+    
+    virtual lldb::ValueObjectSP
+    GetChildAtIndex (uint32_t idx, bool can_create);
+    
+    virtual lldb::ValueObjectSP
+    GetChildMemberWithName (const ConstString &name, bool can_create);
+    
+    virtual uint32_t
+    GetIndexOfChildWithName (const ConstString &name);
+
+    virtual bool
+    IsInScope ();
+    
+    virtual bool
+    IsDynamic ()
+    {
+        if (m_parent)
+            return m_parent->IsDynamic();
+        else
+            return false;
+    }
+    
+    virtual ValueObject *
+    GetParent()
+    {
+        if (m_parent)
+            return m_parent->GetParent();
+        else
+            return NULL;
+    }
+
+    virtual const ValueObject *
+    GetParent() const
+    {
+        if (m_parent)
+            return m_parent->GetParent();
+        else
+            return NULL;
+    }
+
+    void
+    SetOwningSP (lldb::ValueObjectSP &owning_sp)
+    {
+        if (m_owning_valobj_sp == owning_sp)
+            return;
+            
+        assert (m_owning_valobj_sp.get() == NULL);
+        m_owning_valobj_sp = owning_sp;
+    }
+    
+protected:
+    virtual bool
+    UpdateValue ();
+
+    Address  m_address;  ///< The variable that this value object is based upon
+    lldb::TypeSP m_type_sp;
+    lldb::ValueObjectSP m_owning_valobj_sp;
+    lldb::SyntheticValueType m_use_synthetic;
+    lldb::SyntheticFilterSP m_synth_filter;
+
+private:
+    friend class ValueObject;
+    ValueObjectSyntheticFilter (ValueObject &parent, lldb::SyntheticFilterSP filter);
+    
+    //------------------------------------------------------------------
+    // For ValueObject only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ValueObjectSyntheticFilter);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_ValueObjectSyntheticFilter_h_

Modified: lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h (original)
+++ lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h Thu Jul 21 19:16:08 2011
@@ -54,6 +54,7 @@
     uint32_t max_depth;
     uint32_t ptr_depth;
     lldb::DynamicValueType use_dynamic;
+    bool use_synth;
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Thu Jul 21 19:16:08 2011
@@ -324,6 +324,12 @@
         eDynamicDontRunTarget   = 2
     } DynamicValueType;
     
+    typedef enum SyntheticValueType
+    {
+        eNoSyntheticFilter = 0,
+        eUseSyntheticFilter = 1
+    } SyntheticValueType;
+    
     typedef enum AccessType
     {
         eAccessNone,

Modified: lldb/trunk/include/lldb/lldb-forward-rtti.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward-rtti.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward-rtti.h (original)
+++ lldb/trunk/include/lldb/lldb-forward-rtti.h Thu Jul 21 19:16:08 2011
@@ -67,6 +67,7 @@
     typedef SharedPtr<lldb_private::SummaryFormat>::Type SummaryFormatSP;
     typedef SharedPtr<lldb_private::SymbolFile>::Type SymbolFileSP;
     typedef SharedPtr<lldb_private::SymbolContextSpecifier>::Type SymbolContextSpecifierSP;
+    typedef SharedPtr<lldb_private::SyntheticFilter>::Type SyntheticFilterSP;
     typedef SharedPtr<lldb_private::Target>::Type TargetSP;
     typedef SharedPtr<lldb_private::Thread>::Type ThreadSP;
     typedef SharedPtr<lldb_private::ThreadPlan>::Type ThreadPlanSP;

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Thu Jul 21 19:16:08 2011
@@ -144,6 +144,7 @@
 class   SymbolFile;
 class   SymbolVendor;
 class   Symtab;
+class   SyntheticFilter;
 class   Target;
 class   TargetList;
 class   Thread;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul 21 19:16:08 2011
@@ -419,6 +419,7 @@
 		94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; };
 		9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; };
 		9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */; };
+		94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; };
 		9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; };
 		9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; };
@@ -1218,6 +1219,8 @@
 		9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = "<group>"; };
 		94A9112B13D5DEF80046D8A6 /* FormatClasses.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatClasses.h; path = include/lldb/Core/FormatClasses.h; sourceTree = "<group>"; };
 		94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatClasses.cpp; path = source/Core/FormatClasses.cpp; sourceTree = "<group>"; };
+		94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectSyntheticFilter.h; path = include/lldb/Core/ValueObjectSyntheticFilter.h; sourceTree = "<group>"; };
+		94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectSyntheticFilter.cpp; path = source/Core/ValueObjectSyntheticFilter.cpp; sourceTree = "<group>"; };
 		961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = "<group>"; };
 		961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = "<group>"; };
 		961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = "<group>"; };
@@ -2079,6 +2082,8 @@
 				4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */,
 				2643343A1110F63C00CDB6C6 /* ValueObjectRegister.h */,
 				264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */,
+				94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */,
+				94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */,
 				26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */,
 				26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */,
 				26BC7D8610F1B77400F91463 /* VMRange.h */,
@@ -3361,6 +3366,7 @@
 				2676045A13D49D2300AB1B6A /* ProcessControl-mig.defs in Sources */,
 				26D7E45D13D5E30A007FD12B /* SocketAddress.cpp in Sources */,
 				B271B11413D6139300C3FEDB /* FormatClasses.cpp in Sources */,
+				94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: lldb/trunk/source/API/SBValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/API/SBValue.cpp (original)
+++ lldb/trunk/source/API/SBValue.cpp Thu Jul 21 19:16:08 2011
@@ -648,6 +648,8 @@
         lldb::DynamicValueType use_dynamic = eNoDynamicValues;
         bool scope_already_checked = false;
         bool flat_output = false;
+        bool use_synthetic = true;
+        uint32_t no_summary_depth = 0;
         ValueObject::DumpValueObject (description.ref(), 
                                       m_opaque_sp.get(), 
                                       m_opaque_sp->GetName().GetCString(), 
@@ -656,10 +658,11 @@
                                       max_depth, 
                                       show_types, show_location, 
                                       use_objc, 
-                                      use_dynamic, 
+                                      use_dynamic,
+                                      use_synthetic,
                                       scope_already_checked, 
                                       flat_output,
-                                      0);
+                                      no_summary_depth);
     }
     else
         description.Printf ("No value");

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu Jul 21 19:16:08 2011
@@ -334,6 +334,7 @@
                                               false,                    // Show locations of variables, no since this is a host address which we don't care to see
                                               m_options.print_object,   // Print the objective C object?
                                               use_dynamic,
+                                              true,                     // Use synthetic children if available
                                               true,                     // Scope is already checked. Const results are always in scope.
                                               false,                    // Don't flatten output
                                               0);                       // Always use summaries (you might want an option --no-summary like there is for frame variable)

Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Thu Jul 21 19:16:08 2011
@@ -499,7 +499,8 @@
                                                                               m_varobj_options.show_types,
                                                                               m_varobj_options.show_location,
                                                                               m_varobj_options.use_objc,
-                                                                              m_varobj_options.use_dynamic, 
+                                                                              m_varobj_options.use_dynamic,
+                                                                              m_varobj_options.use_synth,
                                                                               false,
                                                                               m_varobj_options.flat_output,
                                                                               m_varobj_options.no_summary_depth);                                        
@@ -552,6 +553,7 @@
                                                               m_varobj_options.show_location,
                                                               m_varobj_options.use_objc,
                                                               m_varobj_options.use_dynamic,
+                                                              m_varobj_options.use_synth,
                                                               false,
                                                               m_varobj_options.flat_output,
                                                               m_varobj_options.no_summary_depth);
@@ -643,6 +645,7 @@
                                                                       m_varobj_options.show_location,
                                                                       m_varobj_options.use_objc,
                                                                       m_varobj_options.use_dynamic, 
+                                                                      m_varobj_options.use_synth,
                                                                       false,
                                                                       m_varobj_options.flat_output,
                                                                       m_varobj_options.no_summary_depth);                                        

Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectMemory.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectMemory.cpp Thu Jul 21 19:16:08 2011
@@ -657,6 +657,7 @@
                                                   m_varobj_options.show_location,
                                                   m_varobj_options.use_objc,
                                                   m_varobj_options.use_dynamic,
+                                                  m_varobj_options.use_synth,
                                                   scope_already_checked,
                                                   m_varobj_options.flat_output,
                                                   0);

Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Thu Jul 21 19:16:08 2011
@@ -488,6 +488,7 @@
                                       m_varobj_options.show_location,
                                       m_varobj_options.use_objc,
                                       m_varobj_options.use_dynamic,
+                                      m_varobj_options.use_synth,
                                       false,
                                       m_varobj_options.flat_output,
                                       m_varobj_options.no_summary_depth);                                        

Modified: lldb/trunk/source/Commands/CommandObjectType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectType.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectType.cpp Thu Jul 21 19:16:08 2011
@@ -1226,7 +1226,7 @@
         lldb::FormatCategorySP category;
         Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
         
-        bool delete_category = category->Delete(typeCS.GetCString());
+        bool delete_category = category->DeleteSummaries(typeCS.GetCString());
         bool delete_named = Debugger::Formatting::NamedSummaryFormats::Delete(typeCS);
         
         if (delete_category || delete_named)
@@ -1359,7 +1359,7 @@
             }
             else
                 Debugger::Formatting::Categories::Get(ConstString(NULL), category);
-            category->Clear();
+            category->ClearSummaries();
         }
         
         Debugger::Formatting::NamedSummaryFormats::Clear();
@@ -1885,6 +1885,670 @@
     
 };
 
+//-------------------------------------------------------------------------
+// CommandObjectTypeSynthList
+//-------------------------------------------------------------------------
+
+bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry);
+
+class CommandObjectTypeSynthList;
+
+struct CommandObjectTypeSynthList_LoopCallbackParam {
+    CommandObjectTypeSynthList* self;
+    CommandReturnObject* result;
+    RegularExpression* regex;
+    RegularExpression* cate_regex;
+    CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R,
+                                                 RegularExpression* X = NULL,
+                                                 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
+};
+
+class CommandObjectTypeSynthList : public CommandObject
+{
+    
+    class CommandOptions : public Options
+    {
+    public:
+        
+        CommandOptions (CommandInterpreter &interpreter) :
+        Options (interpreter)
+        {
+        }
+        
+        virtual
+        ~CommandOptions (){}
+        
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            
+            switch (short_option)
+            {
+                case 'w':
+                    m_category_regex = std::string(option_arg);
+                    break;
+                default:
+                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+                    break;
+            }
+            
+            return error;
+        }
+        
+        void
+        OptionParsingStarting ()
+        {
+            m_category_regex = "";
+        }
+        
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+        
+        // Options table: Required for subclasses of Options.
+        
+        static OptionDefinition g_option_table[];
+        
+        // Instance variables to hold the values for command options.
+        
+        std::string m_category_regex;
+        
+    };
+    
+    CommandOptions m_options;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+    
+public:
+    CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type synth list",
+                   "Show a list of current synthetic providers.",
+                   NULL), m_options(interpreter)
+    {
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatOptional;
+        
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (type_arg);
+    }
+    
+    ~CommandObjectTypeSynthList ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        CommandObjectTypeSynthList_LoopCallbackParam *param;
+        RegularExpression* cate_regex = 
+        m_options.m_category_regex.empty() ? NULL :
+        new RegularExpression(m_options.m_category_regex.c_str());
+        
+        if (argc == 1) {
+            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
+            regex->Compile(command.GetArgumentAtIndex(0));
+            param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex);
+        }
+        else
+            param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex);
+        
+        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback,param);
+                
+        if (cate_regex)
+            delete cate_regex;
+        
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+private:
+    
+    static bool
+    PerCategoryCallback(void* param_vp,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        
+        CommandObjectTypeSynthList_LoopCallbackParam* param = 
+        (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp;
+        CommandReturnObject* result = param->result;
+        
+        // if the category is disabled or empty and there is no regex, just skip it
+        if ((cate->IsEnabled() == false || cate->Filter()->GetCount() == 0) && param->cate_regex == NULL)
+            return true;
+        
+        // if we have a regex and this category does not match it, just skip it
+        if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
+            return true;
+        
+        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
+                                         cate_name,
+                                         (cate->IsEnabled() ? "enabled" : "disabled"));
+        
+        cate->Filter()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp);
+        
+        return true;
+    }
+    
+    bool
+    LoopCallback (const char* type,
+                  const SyntheticFilter::SharedPointer& entry,
+                  RegularExpression* regex,
+                  CommandReturnObject *result)
+    {
+        if (regex == NULL || regex->Execute(type)) 
+            result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
+        return true;
+    }
+    
+    friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry);
+};
+
+bool
+CommandObjectTypeSynthList_LoopCallback (void* pt2self,
+                                         const char* type,
+                                         const SyntheticFilter::SharedPointer& entry)
+{
+    CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
+    return param->self->LoopCallback(type, entry, param->regex, param->result);
+}
+
+
+OptionDefinition
+CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
+    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSynthDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSynthDelete : public CommandObject
+{
+private:
+    class CommandOptions : public Options
+    {
+    public:
+        
+        CommandOptions (CommandInterpreter &interpreter) :
+        Options (interpreter)
+        {
+        }
+        
+        virtual
+        ~CommandOptions (){}
+        
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            
+            switch (short_option)
+            {
+                case 'a':
+                    m_delete_all = true;
+                    break;
+                case 'w':
+                    m_category = ConstString(option_arg).GetCString();
+                    break;
+                default:
+                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+                    break;
+            }
+            
+            return error;
+        }
+        
+        void
+        OptionParsingStarting ()
+        {
+            m_delete_all = false;
+            m_category = NULL;
+        }
+        
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+        
+        // Options table: Required for subclasses of Options.
+        
+        static OptionDefinition g_option_table[];
+        
+        // Instance variables to hold the values for command options.
+        
+        bool m_delete_all;
+        const char* m_category;
+        
+    };
+    
+    CommandOptions m_options;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+    
+    static bool
+    PerCategoryCallback(void* param,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        const char* name = (const char*)param;
+        cate->Filter()->Delete(name);
+        return true;
+    }
+    
+public:
+    CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type synth delete",
+                   "Delete an existing synthetic provider for a type.",
+                   NULL), m_options(interpreter)
+    {
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatPlain;
+        
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (type_arg);
+        
+    }
+    
+    ~CommandObjectTypeSynthDelete ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        if (argc != 1)
+        {
+            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        const char* typeA = command.GetArgumentAtIndex(0);
+        ConstString typeCS(typeA);
+        
+        if (!typeCS)
+        {
+            result.AppendError("empty typenames not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        if (m_options.m_delete_all)
+        {
+            Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString());
+            result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            return result.Succeeded();
+        }
+        
+        lldb::FormatCategorySP category;
+        Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
+        
+        bool delete_category = category->Filter()->Delete(typeCS.GetCString());
+        
+        if (delete_category)
+        {
+            result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            return result.Succeeded();
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+    }
+};
+
+OptionDefinition
+CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Delete from every category."},
+    { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
+    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSynthClear
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSynthClear : public CommandObject
+{
+private:
+    
+    class CommandOptions : public Options
+    {
+    public:
+        
+        CommandOptions (CommandInterpreter &interpreter) :
+        Options (interpreter)
+        {
+        }
+        
+        virtual
+        ~CommandOptions (){}
+        
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            
+            switch (short_option)
+            {
+                case 'a':
+                    m_delete_all = true;
+                    break;
+                default:
+                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+                    break;
+            }
+            
+            return error;
+        }
+        
+        void
+        OptionParsingStarting ()
+        {
+            m_delete_all = false;
+        }
+        
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+        
+        // Options table: Required for subclasses of Options.
+        
+        static OptionDefinition g_option_table[];
+        
+        // Instance variables to hold the values for command options.
+        
+        bool m_delete_all;
+        bool m_delete_named;
+    };
+    
+    CommandOptions m_options;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+    
+    static bool
+    PerCategoryCallback(void* param,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        cate->Filter()->Clear();
+        return true;
+        
+    }
+    
+public:
+    CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type synth clear",
+                   "Delete all existing synthetic providers.",
+                   NULL), m_options(interpreter)
+    {
+    }
+    
+    ~CommandObjectTypeSynthClear ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        
+        if (m_options.m_delete_all)
+            Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL);
+        
+        else
+        {        
+            lldb::FormatCategorySP category;
+            if (command.GetArgumentCount() > 0)
+            {
+                const char* cat_name = command.GetArgumentAtIndex(0);
+                ConstString cat_nameCS(cat_name);
+                Debugger::Formatting::Categories::Get(cat_nameCS, category);
+            }
+            else
+                Debugger::Formatting::Categories::Get(ConstString(NULL), category);
+            category->Filter()->Clear();
+        }
+        
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+};
+
+OptionDefinition
+CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Clear every category."},
+    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSynthAdd
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSynthAdd : public CommandObject
+{
+    
+private:
+    
+    class CommandOptions : public Options
+    {
+        typedef std::vector<std::string> option_vector;
+    public:
+        
+        CommandOptions (CommandInterpreter &interpreter) :
+        Options (interpreter)
+        {
+        }
+        
+        virtual
+        ~CommandOptions (){}
+        
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            bool success;
+            
+            switch (short_option)
+            {
+                case 'C':
+                    m_cascade = Args::StringToBoolean(option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg);
+                    break;
+                case 'c':
+                    m_expr_paths.push_back(option_arg);
+                    break;
+                case 'p':
+                    m_skip_pointers = true;
+                    break;
+                case 'r':
+                    m_skip_references = true;
+                    break;
+                case 'w':
+                    m_category = ConstString(option_arg).GetCString();
+                    break;
+                default:
+                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+                    break;
+            }
+            
+            return error;
+        }
+        
+        void
+        OptionParsingStarting ()
+        {
+            m_cascade = true;
+            m_expr_paths.clear();
+            m_skip_pointers = false;
+            m_skip_references = false;
+            m_category = NULL;
+        }
+        
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+        
+        // Options table: Required for subclasses of Options.
+        
+        static OptionDefinition g_option_table[];
+        
+        // Instance variables to hold the values for command options.
+        
+        bool m_cascade;
+        bool m_skip_references;
+        bool m_skip_pointers;
+        option_vector m_expr_paths;
+        const char* m_category;
+        
+        typedef option_vector::iterator ExpressionPathsIterator;
+    };
+    
+    CommandOptions m_options;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+    
+public:
+    CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type synth add",
+                   "Add a new synthetic provider for a type.",
+                   NULL), m_options (interpreter)
+    {
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatPlus;
+        
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (type_arg);
+        
+    }
+    
+    ~CommandObjectTypeSynthAdd ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        if (argc < 1)
+        {
+            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        if (m_options.m_expr_paths.size() == 0)
+        {
+            result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        SyntheticFilterSP entry;
+        
+        entry.reset(new SyntheticFilter(m_options.m_cascade,
+                                        m_options.m_skip_pointers,
+                                        m_options.m_skip_references));
+        
+        // go through the expression paths
+        CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
+        
+        for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
+            entry->AddExpressionPath(*begin);
+        
+        
+        // now I have a valid provider, let's add it to every type
+        
+        lldb::FormatCategorySP category;
+        Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
+        
+        for (size_t i = 0; i < argc; i++) {
+            const char* typeA = command.GetArgumentAtIndex(i);
+            ConstString typeCS(typeA);
+            if (typeCS)
+                category->Filter()->Add(typeCS.GetCString(), entry);
+            else
+            {
+                result.AppendError("empty typenames not allowed");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+        }
+        
+        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+        return result.Succeeded();
+    }
+};
+
+OptionDefinition
+CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
+    { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeName,    "Include this expression path in the synthetic view."},
+    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for pointers-to-type objects."},
+    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for references-to-type objects."},
+    { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
+    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
 class CommandObjectTypeFormat : public CommandObjectMultiword
 {
 public:
@@ -1906,6 +2570,27 @@
     }
 };
 
+class CommandObjectTypeSynth : public CommandObjectMultiword
+{
+public:
+    CommandObjectTypeSynth (CommandInterpreter &interpreter) :
+    CommandObjectMultiword (interpreter,
+                            "type synth",
+                            "A set of commands for operating on synthetic type representations",
+                            "type synth [<sub-command-options>] ")
+    {
+        LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter)));
+        LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
+        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
+        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
+    }
+    
+    
+    ~CommandObjectTypeSynth ()
+    {
+    }
+};
+
 class CommandObjectTypeCategory : public CommandObjectMultiword
 {
 public:
@@ -1961,6 +2646,7 @@
     LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
     LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
+    LoadSubCommand ("synth",     CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
 }
 
 

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Thu Jul 21 19:16:08 2011
@@ -733,8 +733,12 @@
             // if this is a V, print the value using the default format
             if (*format_name == 'V')
                 *val_obj_display = ValueObject::eDisplayValue;
+            // if this is an L, print the location of the value
             if (*format_name == 'L')
                 *val_obj_display = ValueObject::eDisplayLocation;
+            // if this is an S, print the summary after all
+            if (*format_name == 'S')
+                *val_obj_display = ValueObject::eDisplaySummary;
         }
         // a good custom format tells us to print the value using it
         else
@@ -1761,6 +1765,12 @@
 {
     return GetFormatManager().Get(vobj, entry);
 }
+bool
+Debugger::Formatting::GetSyntheticFilter(ValueObject& vobj,
+                                         lldb::SyntheticFilterSP& entry)
+{
+    return GetFormatManager().Get(vobj, entry);
+}
 
 bool
 Debugger::Formatting::Categories::Get(const ConstString &category, lldb::FormatCategorySP &entry)
@@ -1791,7 +1801,7 @@
 void
 Debugger::Formatting::Categories::Clear(ConstString &category)
 {
-    GetFormatManager().Category(category.GetCString())->Clear();
+    GetFormatManager().Category(category.GetCString())->ClearSummaries();
 }
 
 void

Modified: lldb/trunk/source/Core/FormatClasses.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatClasses.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatClasses.cpp (original)
+++ lldb/trunk/source/Core/FormatClasses.cpp Thu Jul 21 19:16:08 2011
@@ -66,14 +66,15 @@
     
     if (m_show_members_oneliner)
     {
-        const uint32_t num_children = object->GetNumChildren();
+        ValueObjectSP synth_vobj = object->GetSyntheticValue(lldb::eUseSyntheticFilter);
+        const uint32_t num_children = synth_vobj->GetNumChildren();
         if (num_children)
         {
             s.PutChar('(');
             
             for (uint32_t idx=0; idx<num_children; ++idx)
             {
-                lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true));
+                lldb::ValueObjectSP child_sp(synth_vobj->GetChildAtIndex(idx, true));
                 if (child_sp.get())
                 {
                     if (idx)
@@ -137,4 +138,21 @@
     
 }
 
-
+std::string
+SyntheticFilter::GetDescription()
+{
+    StreamString sstr;
+    sstr.Printf("%s%s%s {\n",
+                m_cascades ? "" : " (not cascading)",
+                m_skip_pointers ? " (skip pointers)" : "",
+                m_skip_references ? " (skip references)" : "");
+    
+    for (int i = 0; i < GetCount(); i++)
+    {
+        sstr.Printf("    %s\n",
+                    GetExpressionPathAtIndex(i).c_str());
+    }
+                    
+    sstr.Printf("}");
+    return sstr.GetString();
+}

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Thu Jul 21 19:16:08 2011
@@ -26,6 +26,7 @@
 #include "lldb/Core/ValueObjectDynamicValue.h"
 #include "lldb/Core/ValueObjectList.h"
 #include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Core/ValueObjectSyntheticFilter.h"
 
 #include "lldb/Host/Endian.h"
 
@@ -70,12 +71,14 @@
     m_children (),
     m_synthetic_children (),
     m_dynamic_value (NULL),
+    m_synthetic_value(NULL),
     m_deref_valobj(NULL),
     m_format (eFormatDefault),
     m_last_format_mgr_revision(0),
     m_last_summary_format(),
     m_forced_summary_format(),
     m_last_value_format(),
+    m_last_synthetic_filter(),
     m_user_id_of_forced_summary(0),
     m_value_is_valid (false),
     m_value_did_change (false),
@@ -85,6 +88,7 @@
     m_is_deref_of_parent (false),
     m_is_array_item_for_pointer(false),
     m_is_bitfield_for_scalar(false),
+    m_is_expression_path_child(false),
     m_dump_printable_counter(0)
 {
     m_manager->ManageObject(this);
@@ -110,12 +114,14 @@
     m_children (),
     m_synthetic_children (),
     m_dynamic_value (NULL),
+    m_synthetic_value(NULL),
     m_deref_valobj(NULL),
     m_format (eFormatDefault),
     m_last_format_mgr_revision(0),
     m_last_summary_format(),
     m_forced_summary_format(),
     m_last_value_format(),
+    m_last_synthetic_filter(),
     m_user_id_of_forced_summary(0),
     m_value_is_valid (false),
     m_value_did_change (false),
@@ -125,6 +131,7 @@
     m_is_deref_of_parent (false),
     m_is_array_item_for_pointer(false),
     m_is_bitfield_for_scalar(false),
+    m_is_expression_path_child(false),
     m_dump_printable_counter(0)
 {
     m_manager = new ValueObjectManager();
@@ -209,14 +216,13 @@
         if (m_last_summary_format.get())
             m_last_summary_format.reset((StringSummaryFormat*)NULL);
         if (m_last_value_format.get())
-            m_last_value_format.reset((ValueFormat*)NULL);
-        Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format);
-        // to find a summary we look for a direct summary, then if there is none
-        // we look for a regex summary. if there is none we look for a system
-        // summary (direct), and if also that fails, we look for a system
-        // regex summary
+            m_last_value_format.reset(/*(ValueFormat*)NULL*/);
+        if (m_last_synthetic_filter.get())
+            m_last_synthetic_filter.reset(/*(SyntheticFilter*)NULL*/);
         
+        Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format);
         Debugger::Formatting::GetSummaryFormat(*this, m_last_summary_format);
+        Debugger::Formatting::GetSyntheticFilter(*this, m_last_synthetic_filter);
 
         m_last_format_mgr_revision = Debugger::Formatting::ValueFormats::GetCurrentRevision();
 
@@ -1423,6 +1429,63 @@
     return synthetic_child_sp;
 }
 
+// your expression path needs to have a leading . or ->
+// (unless it somehow "looks like" an array, in which case it has
+// a leading [ symbol). while the [ is meaningful and should be shown
+// to the user, . and -> are just parser design, but by no means
+// added information for the user.. strip them off
+static const char*
+SkipLeadingExpressionPathSeparators(const char* expression)
+{
+    if (!expression || !expression[0])
+        return expression;
+    if (expression[0] == '.')
+        return expression+1;
+    if (expression[0] == '-' && expression[1] == '>')
+        return expression+2;
+    return expression;
+}
+
+lldb::ValueObjectSP
+ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_create)
+{
+    ValueObjectSP synthetic_child_sp;
+    ConstString name_const_string(expression);
+    // 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 (name_const_string);
+    if (!synthetic_child_sp)
+    {
+        // We haven't made a synthetic array member for expression yet, so
+        // lets make one and cache it for any future reference.
+        synthetic_child_sp = GetValueForExpressionPath(expression);
+        
+        // Cache the value if we got one back...
+        if (synthetic_child_sp.get())
+        {
+            AddSyntheticChild(name_const_string, synthetic_child_sp.get());
+            synthetic_child_sp->SetName(SkipLeadingExpressionPathSeparators(expression));
+            synthetic_child_sp->m_is_expression_path_child = true;
+        }
+    }
+    return synthetic_child_sp;
+}
+
+void
+ValueObject::CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic)
+{
+    if (use_synthetic == lldb::eNoSyntheticFilter)
+        return;
+    
+    UpdateFormatsIfNeeded();
+    
+    if (m_last_synthetic_filter.get() == NULL)
+        return;
+    
+    m_synthetic_value = new ValueObjectSyntheticFilter(*this, m_last_synthetic_filter);
+    
+}
+
 void
 ValueObject::CalculateDynamicValue (lldb::DynamicValueType use_dynamic)
 {
@@ -1483,6 +1546,29 @@
         return ValueObjectSP();
 }
 
+// GetDynamicValue() returns a NULL SharedPointer if the object is not dynamic
+// or we do not really want a dynamic VO. this method instead returns this object
+// itself when making it synthetic has no meaning. this makes it much simpler
+// to replace the SyntheticValue for the ValueObject
+ValueObjectSP
+ValueObject::GetSyntheticValue (SyntheticValueType use_synthetic)
+{
+    if (use_synthetic == lldb::eNoSyntheticFilter)
+        return GetSP();
+    
+    UpdateFormatsIfNeeded();
+    
+    if (m_last_synthetic_filter.get() == NULL)
+        return GetSP();
+    
+    CalculateSyntheticValue(use_synthetic);
+    
+    if (m_synthetic_value)
+        return m_synthetic_value->GetSP();
+    else
+        return GetSP();
+}
+
 bool
 ValueObject::GetBaseClassPath (Stream &s)
 {
@@ -2398,6 +2484,7 @@
     bool show_location,
     bool use_objc,
     lldb::DynamicValueType use_dynamic,
+    bool use_synth,
     bool scope_already_checked,
     bool flat_output,
     uint32_t omit_summary_depth
@@ -2545,7 +2632,10 @@
                 
                 if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr))
                 {
-                    const uint32_t num_children = valobj->GetNumChildren();
+                    ValueObjectSP synth_vobj = valobj->GetSyntheticValue(use_synth ?
+                                                                         lldb::eUseSyntheticFilter : 
+                                                                         lldb::eNoSyntheticFilter);
+                    const uint32_t num_children = synth_vobj->GetNumChildren();
                     if (num_children)
                     {
                         if (flat_output)
@@ -2562,7 +2652,7 @@
 
                         for (uint32_t idx=0; idx<num_children; ++idx)
                         {
-                            ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
+                            ValueObjectSP child_sp(synth_vobj->GetChildAtIndex(idx, true));
                             if (child_sp.get())
                             {
                                 DumpValueObject (s,
@@ -2575,6 +2665,7 @@
                                                  show_location,
                                                  false,
                                                  use_dynamic,
+                                                 use_synth,
                                                  true,
                                                  flat_output,
                                                  omit_summary_depth > 1 ? omit_summary_depth - 1 : 0);

Added: lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp?rev=135731&view=auto
==============================================================================
--- lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp (added)
+++ lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp Thu Jul 21 19:16:08 2011
@@ -0,0 +1,170 @@
+//===-- ValueObjectSyntheticFilter.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/Core/ValueObjectSyntheticFilter.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/FormatClasses.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+
+using namespace lldb_private;
+
+ValueObjectSyntheticFilter::ValueObjectSyntheticFilter (ValueObject &parent, lldb::SyntheticFilterSP filter) :
+    ValueObject(parent),
+    m_address (),
+    m_type_sp(),
+m_use_synthetic (lldb::eUseSyntheticFilter),
+    m_synth_filter(filter)
+{
+    SetName (parent.GetName().AsCString());
+}
+
+ValueObjectSyntheticFilter::~ValueObjectSyntheticFilter()
+{
+    m_owning_valobj_sp.reset();
+}
+
+lldb::clang_type_t
+ValueObjectSyntheticFilter::GetClangType ()
+{
+    if (m_type_sp)
+        return m_value.GetClangType();
+    else
+        return m_parent->GetClangType();
+}
+
+ConstString
+ValueObjectSyntheticFilter::GetTypeName()
+{
+    const bool success = UpdateValueIfNeeded();
+    if (success && m_type_sp)
+        return ClangASTType::GetConstTypeName (GetClangType());
+    else
+        return m_parent->GetTypeName();
+}
+
+uint32_t
+ValueObjectSyntheticFilter::CalculateNumChildren()
+{
+    const bool success = UpdateValueIfNeeded();
+    if (!success)
+        return 0;
+    if (m_synth_filter.get())
+        return m_synth_filter->GetCount();
+    return 0;
+    if (success && m_type_sp)
+        return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
+    else
+        return m_parent->GetNumChildren();
+}
+
+clang::ASTContext *
+ValueObjectSyntheticFilter::GetClangAST ()
+{
+    const bool success = UpdateValueIfNeeded(false);
+    if (success && m_type_sp)
+        return m_type_sp->GetClangAST();
+    else
+        return m_parent->GetClangAST ();
+}
+
+size_t
+ValueObjectSyntheticFilter::GetByteSize()
+{
+    const bool success = UpdateValueIfNeeded();
+    if (success && m_type_sp)
+        return m_value.GetValueByteSize(GetClangAST(), NULL);
+    else
+        return m_parent->GetByteSize();
+}
+
+lldb::ValueType
+ValueObjectSyntheticFilter::GetValueType() const
+{
+    return m_parent->GetValueType();
+}
+
+bool
+ValueObjectSyntheticFilter::UpdateValue ()
+{
+    SetValueIsValid (false);
+    m_error.Clear();
+
+    if (!m_parent->UpdateValueIfNeeded())
+    {
+        // our parent could not update.. as we are meaningless without a parent, just stop
+        if (m_error.Success() && m_parent->GetError().Fail())
+            m_error = m_parent->GetError();
+        return false;
+    }
+
+    SetValueIsValid(true);
+    return true;
+}
+
+lldb::ValueObjectSP
+ValueObjectSyntheticFilter::GetChildAtIndex (uint32_t idx, bool can_create)
+{
+    if (!m_synth_filter.get())
+        return lldb::ValueObjectSP();
+    if (idx >= m_synth_filter->GetCount())
+        return lldb::ValueObjectSP();
+    return m_parent->GetSyntheticExpressionPathChild(m_synth_filter->GetExpressionPathAtIndex(idx).c_str(), can_create);
+}
+
+lldb::ValueObjectSP
+ValueObjectSyntheticFilter::GetChildMemberWithName (const ConstString &name, bool can_create)
+{
+    if (!m_synth_filter.get())
+        return lldb::ValueObjectSP();
+    uint32_t idx = GetIndexOfChildWithName(name);
+    if (idx >= m_synth_filter->GetCount())
+        return lldb::ValueObjectSP();
+    return m_parent->GetSyntheticExpressionPathChild(name.GetCString(), can_create);
+}
+
+uint32_t
+ValueObjectSyntheticFilter::GetIndexOfChildWithName (const ConstString &name)
+{
+    const char* name_cstr = name.GetCString();
+    for (int i = 0; i < m_synth_filter->GetCount(); i++)
+    {
+        const char* expr_cstr = m_synth_filter->GetExpressionPathAtIndex(i).c_str();
+        if (::strcmp(name_cstr, expr_cstr))
+            return i;
+    }
+    return UINT32_MAX;
+}
+
+bool
+ValueObjectSyntheticFilter::IsInScope ()
+{
+    return m_parent->IsInScope();
+}
+

Modified: lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp Thu Jul 21 19:16:08 2011
@@ -31,7 +31,8 @@
 g_option_table[] =
 {
     { LLDB_OPT_SET_1, false, "dynamic-type",    'd', required_argument, TargetInstanceSettings::g_dynamic_value_types, 
-                                                                              0, eArgTypeNone,   "Show the object as its full dynamic type, not its static type, if available."},
+                                                                              0, eArgTypeNone,      "Show the object as its full dynamic type, not its static type, if available."},
+    { LLDB_OPT_SET_1, false, "synthetic-type",  'S', required_argument, NULL, 0, eArgTypeBoolean,   "Show the object obeying its synthetic provider, if available."},
     { LLDB_OPT_SET_1, false, "depth",           'D', required_argument, NULL, 0, eArgTypeCount,     "Set the max recurse depth when dumping aggregate types (default is infinity)."},
     { LLDB_OPT_SET_1, false, "flat",            'F', no_argument,       NULL, 0, eArgTypeNone,      "Display results in a flat format that uses expression paths for each variable or member."},
     { LLDB_OPT_SET_1, false, "location",        'L', no_argument,       NULL, 0, eArgTypeNone,      "Show variable location information."},
@@ -105,7 +106,12 @@
             else
                 no_summary_depth = 1;
             break;
-
+            
+        case 'S':
+            use_synth = Args::StringToBoolean(option_arg, true, &success);
+            if (!success)
+                error.SetErrorStringWithFormat("Invalid synthetic-type '%s'.\n", option_arg);
+            break;
         default:
             error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
             break;
@@ -124,6 +130,7 @@
     use_objc          = false;
     max_depth         = UINT32_MAX;
     ptr_depth         = 0;
+    use_synth         = true;
     
     Target *target = interpreter.GetExecutionContext().target;
     if (target != NULL)

Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py Thu Jul 21 19:16:08 2011
@@ -319,8 +319,23 @@
                                'AShape',
                                'ARectangleStar'])
 
+        # check that synthetic children work into categories
+        self.runCmd("type synth add Rectangle --child w --category RectangleCategory")
+        self.runCmd("type category enable RectangleCategory")
+        self.runCmd("type summary add Rectangle -f \" \" -e --category RectangleCategory")
+        self.expect('frame variable r2',
+            substrs = ['w = 9'])
+        self.runCmd("type summary add Rectangle -f \" \" -e")
+        self.expect('frame variable r2', matching=False,
+                    substrs = ['h = 16'])
+
         # Now delete all categories
-        self.runCmd("type category delete CircleCategory RectangleStarCategory BaseCategory")
+        self.runCmd("type category delete CircleCategory RectangleStarCategory BaseCategory RectangleCategory")
+
+        # last of all, check that a deleted category with synth does not blow us up
+        self.expect('frame variable r2',
+                    substrs = ['w = 9',
+                               'h = 16'])
 
 if __name__ == '__main__':
     import atexit

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=135731&r1=135730&r2=135731&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 Thu Jul 21 19:16:08 2011
@@ -182,7 +182,25 @@
         self.expect("frame variable cool_pointer",
             substrs = ['3,0,0'])
 
+        # test special symbols for formatting variables into summaries
+        self.runCmd("type summary add -f \"cool object @ ${var%L}\" i_am_cool")
+        self.runCmd("type summary delete \"i_am_cool [5]\"")
         
+        # 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] = cool object @ 0x',
+                       '[1] = cool object @ 0x',
+                       '[2] = cool object @ 0x',
+                       '[3] = cool object @ 0x',
+                       '[4] = cool object @ 0x'])
+            
+        self.runCmd("type summary add -f \"goofy\" i_am_cool")
+        self.runCmd("type summary add -f \"${var.second_cool%S}\" i_am_cooler")
+
+        self.expect("frame variable the_coolest_guy",
+            substrs = ['(i_am_cooler) the_coolest_guy = goofy'])
 
 if __name__ == '__main__':
     import atexit

Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp Thu Jul 21 19:16:08 2011
@@ -110,6 +110,8 @@
     
     char  strarr[32] = "Hello world!";
     char* strptr     = "Hello world!";
+    
+    i_am_cooler the_coolest_guy(1,2,3.14,6.28,'E','G');
         
     return 0; // Set break point at this line.
 }

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/Makefile?rev=135731&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/Makefile Thu Jul 21 19:16:08 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py?rev=135731&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py Thu Jul 21 19:16:08 2011
@@ -0,0 +1,203 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class DataFormatterTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "data-formatter", "data-formatter-synth")
+
+    @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 format clear', check=False)
+            self.runCmd('type summary clear', check=False)
+            self.runCmd('type synth clear', check=False)
+
+        # Execute the cleanup function during test case tear down.
+        self.addTearDownHook(cleanup)
+
+        # Pick some values and check that the basics work
+        self.runCmd("type synth add BagOfInts --child x --child z")
+        self.expect("frame variable int_bag",
+            substrs = ['x = 6',
+                       'z = 8'])
+
+        # Check we can still access the missing child by summary
+        self.runCmd("type summary add BagOfInts -f \"y=${var.y}\"")
+        self.expect('frame variable int_bag',
+            substrs = ['y=7'])
+            
+        # Even if we have synth children, the summary prevails            
+        self.expect("frame variable int_bag", matching=False,
+                    substrs = ['x = 6',
+                               'z = 8'])
+    
+        # Summary+Synth must work together
+        self.runCmd("type summary add BagOfInts -f \"y=${var.y}\" -e")
+        self.expect('frame variable int_bag',
+                    substrs = ['y=7',
+                               'x = 6',
+                               'z = 8'])
+        
+        # Same output, but using Python
+        self.runCmd("type summary add BagOfInts -s \"return 'y='+valobj.GetChildMemberWithName('y').GetValue()\" -e")
+        self.expect('frame variable int_bag',
+                    substrs = ['y=7',
+                               'x = 6',
+                               'z = 8'])
+
+        # If I skip summaries, still give me the artificial children
+        self.expect("frame variable int_bag -Y1",
+                    substrs = ['x = 6',
+                               'z = 8'])
+
+        # Delete synth and check that the view reflects it immediately
+        self.runCmd("type synth delete BagOfInts")
+        self.expect("frame variable int_bag",
+                    substrs = ['x = 6',
+                               'y = 7',
+                               'z = 8'])
+
+        # Add the synth again and check that it's honored deeper in the hierarchy
+        self.runCmd("type synth add BagOfInts --child x --child z")
+        self.expect('frame variable bag_bag',
+            substrs = ['x = y=70 {',
+                       'x = 69',
+                       'z = 71',
+                       'y = y=67 {',
+                       'x = 66',
+                       'z = 68'])
+        self.expect('frame variable bag_bag', matching=False,
+                    substrs = ['y = 70',
+                               'y = 67'])
+
+        # Check that a synth can expand nested stuff
+        self.runCmd("type synth add BagOfBags --child x.y --child y.z")
+        self.expect('frame variable bag_bag',
+                    substrs = ['x.y = 70',
+                               'y.z = 68'])
+
+        # ...even if we get -> and . wrong
+        self.runCmd("type synth add BagOfBags --child x.y --child \"y->z\"")
+        self.expect('frame variable bag_bag',
+                    substrs = ['x.y = 70',
+                               'y->z = 68'])
+
+        # ...even bitfields
+        self.runCmd("type synth add BagOfBags --child x.y --child \"y->z[1-2]\"")
+        self.expect('frame variable bag_bag -T',
+                    substrs = ['x.y = 70',
+                               '(int:2) y->z[1-2] = 2'])
+
+        # ...even if we format the bitfields
+        self.runCmd("type synth add BagOfBags --child x.y --child \"y->y[0-0]\"")
+        self.runCmd("type format add \"int:1\" -f bool")
+        self.expect('frame variable bag_bag -T',
+                    substrs = ['x.y = 70',
+                               '(int:1) y->y[0-0] = true'])
+        
+        # ...even if we use one-liner summaries
+        self.runCmd("type summary add -c BagOfBags")
+        self.expect('frame variable bag_bag',
+            substrs = ['(BagOfBags) bag_bag = (x.y=70, y->y[0-0]=true)'])
+        
+        self.runCmd("type summary delete BagOfBags")
+
+        # now check we are dynamic (and arrays work)
+        self.runCmd("type synth add Plenty --child bitfield --child array[0] --child array[2]")
+        self.expect('frame variable plenty_of_stuff',
+            substrs = ['bitfield = 1',
+                       'array[0] = 5',
+                       'array[2] = 3'])
+    
+        self.runCmd("n")
+        self.expect('frame variable plenty_of_stuff',
+                    substrs = ['bitfield = 17',
+                               'array[0] = 5',
+                               'array[2] = 3'])
+        
+        # skip synthetic children
+        self.expect('frame variable plenty_of_stuff -S no',
+                    substrs = ['some_values = 0x0',
+                               'array = 0x',
+                               'array_size = 5'])
+
+        
+        # check flat printing with synthetic children
+        self.expect('frame variable plenty_of_stuff --flat',
+            substrs = ['plenty_of_stuff.bitfield = 17',
+                       '*(plenty_of_stuff.array) = 5',
+                       '*(plenty_of_stuff.array) = 3'])
+        
+        # check that we do not lose location information for our children
+        self.expect('frame variable plenty_of_stuff -L',
+                    substrs = ['0x',
+                               ':   bitfield = 17'])
+
+        # check we work across pointer boundaries
+        self.expect('frame variable plenty_of_stuff.some_values -P1',
+                    substrs = ['(BagOfInts *) plenty_of_stuff.some_values',
+                               'x = 5',
+                               'z = 7'])
+
+        # but not if we don't want to
+        self.runCmd("type synth add BagOfInts --child x --child z -p")
+        self.expect('frame variable plenty_of_stuff.some_values -P1',
+                    substrs = ['(BagOfInts *) plenty_of_stuff.some_values',
+                               'x = 5',
+                               'y = 6',
+                               'z = 7'])
+
+        # check we're dynamic even if nested
+        self.runCmd("type synth add BagOfBags --child x.z")
+        self.expect('frame variable bag_bag',
+            substrs = ['x.z = 71'])
+
+        self.runCmd("n")
+        self.expect('frame variable bag_bag',
+                    substrs = ['x.z = 12'])
+
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/main.cpp?rev=135731&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/main.cpp (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/main.cpp Thu Jul 21 19:16:08 2011
@@ -0,0 +1,83 @@
+//===-- 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>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct BagOfInts
+{
+    int x;
+    int y;
+    int z;
+    BagOfInts(int X) :
+    x(X),
+    y(X+1),
+    z(X+2) {}
+};
+
+struct BagOfFloats
+{
+    float x;
+    float y;
+    float z;
+    BagOfFloats(float X) :
+    x(X+0.334),
+    y(X+0.500),
+    z(X+0.667) {}
+};
+
+struct BagOfBags
+{
+    BagOfInts x;
+    BagOfInts y;
+    BagOfFloats z;
+    BagOfFloats q;
+    BagOfBags() : 
+    x('E'),
+    y('B'),
+    z(1.1),
+    q(20.11) {}
+};
+
+struct Plenty
+{
+    BagOfInts *some_values;
+    int* array;
+    int array_size;
+    int bitfield;
+    
+    Plenty(int N, bool flagA, bool flagB) :
+    some_values(new BagOfInts(N)),
+    array(new int[N]),
+    array_size(N),
+    bitfield( (flagA ? 0x01 : 0x00) | (flagB ? 0x10 : 0x00) )
+    {
+        for (int j = 0; j < N; j++)
+            array[j] = N-j;
+    }
+};
+
+int main (int argc, const char * argv[])
+{
+    BagOfInts int_bag(6);
+    BagOfFloats float_bag(2.71);
+    
+    BagOfBags bag_bag;
+    
+    Plenty plenty_of_stuff(5,true,false);
+    
+    plenty_of_stuff.bitfield = 0x11; // Set break point at this line.
+    
+    bag_bag.x.z = 12;
+    
+    return 0;
+    
+}
+

Modified: lldb/trunk/www/varformats.html
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=135731&r1=135730&r2=135731&view=diff
==============================================================================
--- lldb/trunk/www/varformats.html (original)
+++ lldb/trunk/www/varformats.html Thu Jul 21 19:16:08 2011
@@ -495,20 +495,38 @@
                 in fact it has a similar effect. If you add a % sign
                 followed by any one format name or abbreviation from the
                 above table after an expression path, the resulting
-                object will be displyed using the chosen format (this is
-                applicable to non-aggregate types only, with a few
-                special exceptions discussed below). </p>
-              <p>There are two more special format symbols that you can
-                use only as part of a summary string: <code>%V</code>
-                and <code>%@</code>. The first one tells LLDB to ignore
-                summary strings for the type of the object referred by
-                the expression path and instead print the object's
-                value. The second is only applicable to Objective-C
-                classes, and tells LLDB to get the object's description
-                from the Objective-C runtime. By default, if no format
-                is provided, LLDB will try to get the object's summary,
-                and if empty the object's value. If neither can be
-                obtained, nothing will be displayed.</p>
+                object will be displyed using the chosen format.</p>
+                
+            <p>You can also use some other special format markers, not available
+            for type formatters, but which carry a special meaning when used in this
+            context:</p>
+            
+            <table border="1">
+                <tbody>
+                  <tr valign="top">
+                    <td width="23%"><b>Symbol</b></td>
+                    <td><b>Description</b></td>
+                  </tr>
+                  <tr valign="top">
+                    <td><b>%S</b></td>
+                    <td>Use this object's summary (the default for aggregate types)</td>
+                  </tr>
+                  <tr valign="top">
+                    <td><b>%V</b></td>
+                    <td>Use this object's value (the default for non-aggregate types)</td>
+                  </tr>
+                  <tr valign="top">
+                    <td><b>%@</b></td>
+                    <td>Use a language-runtime specific description (for C++ this does nothing,
+                    for Objective-C it calls the NSPrintForDebugger API)</td>
+                  </tr>
+                  <tr valign="top">
+                    <td><b>%L</b></td>
+                    <td>Use this object's location (memory address, register name, ...)</td>
+                  </tr>
+				</tbody>
+			</table>
+                
               <p>As previously said, pointers and values are treated the
                 same way when getting to their members in an expression
                 path. However, if your expression path leads to a





More information about the lldb-commits mailing list