[Lldb-commits] [lldb] r137097 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Target/StackFrame.h source/Core/ValueObject.cpp source/Symbol/ClangASTType.cpp source/Target/StackFrame.cpp source/Target/Target.cpp test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py

Enrico Granata granata.enrico at gmail.com
Mon Aug 8 18:04:57 PDT 2011


Author: enrico
Date: Mon Aug  8 20:04:56 2011
New Revision: 137097

URL: http://llvm.org/viewvc/llvm-project?rev=137097&view=rev
Log:
Basic support for reading synthetic children by index:
 if your datatype provides synthetic children, "frame variable object[index]" should now do the right thing
 in cases where the above syntax would have been rejected before, i.e.
  object is not a pointer nor an array (frame variable ignores potential overload of [])
  object is a pointer to an Objective-C class (which cannot be dereferenced)
 expression will still run operator[] if available and complain if it cannot do so
 synthetic children by name do not work yet

Modified:
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Target/StackFrame.h
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Symbol/ClangASTType.cpp
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/source/Target/Target.cpp
    lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Mon Aug  8 20:04:56 2011
@@ -122,13 +122,16 @@
         bool m_check_dot_vs_arrow_syntax;
         bool m_no_fragile_ivar;
         bool m_allow_bitfields_syntax;
+        bool m_no_synthetic_children;
         
         GetValueForExpressionPathOptions(bool dot = false,
                                          bool no_ivar = false,
-                                         bool bitfield = true) :
+                                         bool bitfield = true,
+                                         bool no_synth = false) :
             m_check_dot_vs_arrow_syntax(dot),
             m_no_fragile_ivar(no_ivar),
-            m_allow_bitfields_syntax(bitfield)
+            m_allow_bitfields_syntax(bitfield),
+            m_no_synthetic_children(no_synth)
         {
         }
         
@@ -174,6 +177,20 @@
             return *this;
         }
         
+        GetValueForExpressionPathOptions&
+        DoAllowSyntheticChildren()
+        {
+            m_no_synthetic_children = false;
+            return *this;
+        }
+        
+        GetValueForExpressionPathOptions&
+        DontAllowSyntheticChildren()
+        {
+            m_no_synthetic_children = true;
+            return *this;
+        }
+        
         static const GetValueForExpressionPathOptions
         DefaultOptions()
         {
@@ -565,6 +582,9 @@
     lldb::ValueObjectSP
     GetSyntheticValue (lldb::SyntheticValueType use_synthetic);
     
+    bool
+    HasSyntheticValue();
+    
     virtual lldb::ValueObjectSP
     CreateConstantValue (const ConstString &name);
 

Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Mon Aug  8 20:04:56 2011
@@ -32,8 +32,9 @@
 public:
     enum ExpressionPathOption
     {
-        eExpressionPathOptionCheckPtrVsMember   = (1u << 0),
-        eExpressionPathOptionsNoFragileObjcIvar = (1u << 1)
+        eExpressionPathOptionCheckPtrVsMember     = (1u << 0),
+        eExpressionPathOptionsNoFragileObjcIvar   = (1u << 1),
+        eExpressionPathOptionsNoSyntheticChildren = (1u << 2)
     };
     //------------------------------------------------------------------
     // Constructors and Destructors

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Mon Aug  8 20:04:56 2011
@@ -1668,6 +1668,22 @@
 }
 
 bool
+ValueObject::HasSyntheticValue()
+{
+    UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
+    
+    if (m_last_synthetic_filter.get() == NULL)
+        return false;
+    
+    CalculateSyntheticValue(lldb::eUseSyntheticFilter);
+    
+    if (m_synthetic_value)
+        return true;
+    else
+        return false;
+}
+
+bool
 ValueObject::GetBaseClassPath (Stream &s)
 {
     if (IsBaseClass())
@@ -2042,12 +2058,15 @@
             {
                 if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T*
                 {
-                    if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong!
+                    if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar...
                     {
-                        *first_unparsed = expression_cstr;
-                        *reason_to_stop = ValueObject::eRangeOperatorInvalid;
-                        *final_result = ValueObject::eInvalid;
-                        return ValueObjectSP();
+                        if (options.m_no_synthetic_children) // ...only chance left is synthetic
+                        {
+                            *first_unparsed = expression_cstr;
+                            *reason_to_stop = ValueObject::eRangeOperatorInvalid;
+                            *final_result = ValueObject::eInvalid;
+                            return ValueObjectSP();
+                        }
                     }
                     else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
                     {
@@ -2117,6 +2136,9 @@
                         ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
                         if (!child_valobj_sp)
                             child_valobj_sp = root->GetSyntheticArrayMemberFromArray(index, true);
+                        if (!child_valobj_sp)
+                            if (root->HasSyntheticValue() && root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetNumChildren() > index)
+                                child_valobj_sp = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
                         if (child_valobj_sp)
                         {
                             root = child_valobj_sp;
@@ -2154,7 +2176,19 @@
                         }
                         else
                         {
-                            root = root->GetSyntheticArrayMemberFromPointer(index, true);
+                            if (ClangASTType::GetMinimumLanguage(root->GetClangAST(),
+                                                                    root->GetClangType()) == lldb::eLanguageTypeObjC
+                                &&
+                                ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false
+                                &&
+                                root->HasSyntheticValue()
+                                &&
+                                options.m_no_synthetic_children == false)
+                            {
+                                root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
+                            }
+                            else
+                                root = root->GetSyntheticArrayMemberFromPointer(index, true);
                             if (!root.get())
                             {
                                 *first_unparsed = expression_cstr;
@@ -2170,7 +2204,7 @@
                             }
                         }
                     }
-                    else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
+                    else if (ClangASTContext::IsScalarType(root_clang_type))
                     {
                         root = root->GetSyntheticBitFieldChild(index, index, true);
                         if (!root.get())
@@ -2188,6 +2222,24 @@
                             return root;
                         }
                     }
+                    else if (root->HasSyntheticValue() && options.m_no_synthetic_children)
+                    {
+                        root = root->GetSyntheticValue(lldb::eUseSyntheticFilter)->GetChildAtIndex(index, true);
+                        if (!root.get())
+                        {
+                            *first_unparsed = expression_cstr;
+                            *reason_to_stop = ValueObject::eNoSuchChild;
+                            *final_result = ValueObject::eInvalid;
+                            return ValueObjectSP();
+                        }
+                    }
+                    else
+                    {
+                        *first_unparsed = expression_cstr;
+                        *reason_to_stop = ValueObject::eNoSuchChild;
+                        *final_result = ValueObject::eInvalid;
+                        return ValueObjectSP();
+                    }
                 }
                 else // we have a low and a high index
                 {

Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Mon Aug  8 20:04:56 2011
@@ -115,6 +115,8 @@
 ConstString
 ClangASTType::GetConstTypeName ()
 {
+    if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type))
+        return ConstString("<invalid>");
     return GetConstTypeName (m_type);
 }
 

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Mon Aug  8 20:04:56 2011
@@ -525,6 +525,7 @@
     {
         const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
         const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+        const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
         error.Clear();
         bool deref = false;
         bool address_of = false;
@@ -718,14 +719,55 @@
                                 
                                 if (valobj_sp->IsPointerType ())
                                 {
-                                    child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
-                                    if (!child_valobj_sp)
+                                    if (no_synth_child == false
+                                        && 
+                                        ClangASTType::GetMinimumLanguage(valobj_sp->GetClangAST(),
+                                                                         valobj_sp->GetClangType()) == lldb::eLanguageTypeObjC /* is ObjC pointer */
+                                        &&
+                                        ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(valobj_sp->GetClangType())) == false /* is not double-ptr */)
                                     {
-                                        valobj_sp->GetExpressionPath (var_expr_path_strm, false);
-                                        error.SetErrorStringWithFormat ("failed to use pointer as array for index %i for \"(%s) %s\"", 
-                                                                        child_index, 
-                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
-                                                                        var_expr_path_strm.GetString().c_str());
+                                        // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children
+                                        lldb::ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter);
+                                        if (synthetic.get() == NULL /* no synthetic */
+                                            || synthetic == valobj_sp) /* synthetic is the same as the original object */
+                                        {
+                                            valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                            error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 
+                                                                            valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                            var_expr_path_strm.GetString().c_str());
+                                        }
+                                        else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+                                        {
+                                            valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                            error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"", 
+                                                                            child_index, 
+                                                                            valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                            var_expr_path_strm.GetString().c_str());
+                                        }
+                                        else
+                                        {
+                                            child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+                                            if (!child_valobj_sp)
+                                            {
+                                                valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                                error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"", 
+                                                                                child_index, 
+                                                                                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                                var_expr_path_strm.GetString().c_str());
+                                            }
+                                        }
+                                    }
+                                    else
+                                    {
+                                        child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+                                        if (!child_valobj_sp)
+                                        {
+                                            valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                            error.SetErrorStringWithFormat ("failed to use pointer as array for index %i for \"(%s) %s\"", 
+                                                                            child_index, 
+                                                                            valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                            var_expr_path_strm.GetString().c_str());
+                                        }
                                     }
                                 }
                                 else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
@@ -757,10 +799,36 @@
                                 }
                                 else
                                 {
-                                    valobj_sp->GetExpressionPath (var_expr_path_strm, false);
-                                    error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 
-                                                                    valobj_sp->GetTypeName().AsCString("<invalid type>"),
-                                                                    var_expr_path_strm.GetString().c_str());
+                                    lldb::ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(lldb::eUseSyntheticFilter);
+                                    if (no_synth_child /* synthetic is forbidden */ ||
+                                        synthetic.get() == NULL /* no synthetic */
+                                        || synthetic == valobj_sp) /* synthetic is the same as the original object */
+                                    {
+                                        valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                        error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 
+                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                        var_expr_path_strm.GetString().c_str());
+                                    }
+                                    else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+                                    {
+                                        valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                        error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"", 
+                                                                        child_index, 
+                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                        var_expr_path_strm.GetString().c_str());
+                                    }
+                                    else
+                                    {
+                                        child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+                                        if (!child_valobj_sp)
+                                        {
+                                            valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+                                            error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"", 
+                                                                            child_index, 
+                                                                            valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                            var_expr_path_strm.GetString().c_str());
+                                        }
+                                    }
                                 }
 
                                 if (!child_valobj_sp)

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Mon Aug  8 20:04:56 2011
@@ -1035,7 +1035,8 @@
         frame->CalculateExecutionContext(exe_ctx);
         Error error;
         const uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
-                                           StackFrame::eExpressionPathOptionsNoFragileObjcIvar;
+                                           StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+                                           StackFrame::eExpressionPathOptionsNoSyntheticChildren;
         lldb::VariableSP var_sp;
         result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr, 
                                                                      use_dynamic, 

Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py?rev=137097&r1=137096&r2=137097&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py Mon Aug  8 20:04:56 2011
@@ -164,6 +164,22 @@
                                '[5] = 123456',
                                '[6] = 1234567',
                                '}'])
+        
+        # check access-by-index
+        self.expect("frame variable numbers[0]",
+                    substrs = ['1']);
+        self.expect("frame variable numbers[1]",
+                    substrs = ['12']);
+        self.expect("frame variable numbers[2]",
+                    substrs = ['123']);
+        self.expect("frame variable numbers[3]",
+                    substrs = ['1234']);
+        
+        # but check that expression does not rely on us
+        # (when expression gets to call into STL code correctly, we will have to find
+        # another way to check this)
+        self.expect("expression numbers[6]", matching=False, error=True,
+            substrs = ['1234567'])
 
         # clear out the vector and see that we do the right thing once again
         self.runCmd("n")
@@ -202,6 +218,18 @@
 
         self.expect("frame variable strings",
                     substrs = ['vector has 4 items'])
+        
+        # check access-by-index
+        self.expect("frame variable strings[0]",
+                    substrs = ['goofy']);
+        self.expect("frame variable strings[1]",
+                    substrs = ['is']);
+        
+        # but check that expression does not rely on us
+        # (when expression gets to call into STL code correctly, we will have to find
+        # another way to check this)
+        self.expect("expression strings[0]", matching=False, error=True,
+                    substrs = ['goofy'])
 
         self.runCmd("n")
 
@@ -255,6 +283,16 @@
                                '0x0abcdef0',
                                '[5] =',
                                '0x0cab0cab'])
+        
+        # check access-by-index
+        self.expect("frame variable numbers_list[0]",
+                    substrs = ['0x12345678']);
+        self.expect("frame variable numbers_list[1]",
+                    substrs = ['0x11223344']);
+        
+        # but check that expression does not rely on us
+        self.expect("expression numbers_list[0]", matching=False, error=True,
+                    substrs = ['0x12345678'])
 
         self.runCmd("n")
             
@@ -298,6 +336,16 @@
                                '[1] = \"is\"',
                                '[2] = \"smart\"',
                                '[3] = \"!!!\"'])
+        
+        # check access-by-index
+        self.expect("frame variable text_list[0]",
+                    substrs = ['goofy']);
+        self.expect("frame variable text_list[3]",
+                    substrs = ['!!!']);
+        
+        # but check that expression does not rely on us
+        self.expect("expression text_list[0]", matching=False, error=True,
+                    substrs = ['goofy'])
 
         # now std::map<K,V>
         # also take a chance to test regex synth here
@@ -347,6 +395,18 @@
                                '[7] = {',
                                'first = 7',
                                'second = 1'])
+        
+        # check access-by-index
+        self.expect("frame variable ii[0]",
+                    substrs = ['first = 0',
+                               'second = 0']);
+        self.expect("frame variable ii[3]",
+                    substrs = ['first =',
+                               'second =']);
+        
+        # but check that expression does not rely on us
+        self.expect("expression ii[0]", matching=False, error=True,
+                    substrs = ['first = 0'])
 
         self.runCmd("n")
         
@@ -391,6 +451,15 @@
                                 '[4] = ',
                                 'first = \"four\"',
                                 'second = 4'])
+        
+        # check access-by-index
+        self.expect("frame variable si[0]",
+                    substrs = ['first = ', 'four',
+                               'second = 4']);
+        
+        # but check that expression does not rely on us
+        self.expect("expression si[0]", matching=False, error=True,
+                    substrs = ['first = ', 'zero'])
 
         self.runCmd("n")
         
@@ -424,6 +493,15 @@
                                '[3] = ',
                                'second = \"!!!\"',
                                'first = 3'])
+        
+        # check access-by-index
+        self.expect("frame variable is[0]",
+                    substrs = ['first = ', '0',
+                               'second =', 'goofy']);
+        
+        # but check that expression does not rely on us
+        self.expect("expression is[0]", matching=False, error=True,
+                    substrs = ['first = ', 'goofy'])
 
         self.runCmd("n")
         
@@ -457,6 +535,14 @@
                                '[3] = ',
                                'second = \"..is always a Mac!\"',
                                'first = \"a Mac..\"'])
+        
+        # check access-by-index
+        self.expect("frame variable ss[3]",
+                    substrs = ['gatto', 'cat']);
+        
+        # but check that expression does not rely on us
+        self.expect("expression ss[3]", matching=False, error=True,
+                    substrs = ['gatto'])
 
         self.runCmd("n")
         





More information about the lldb-commits mailing list