[Lldb-commits] [lldb] r173216 - in /lldb/trunk: include/lldb/Core/ValueObjectDynamicValue.h include/lldb/Symbol/Type.h include/lldb/Target/LanguageRuntime.h source/Core/ValueObject.cpp source/Core/ValueObjectDynamicValue.cpp source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp source/Symbol/Type.cpp test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py

Enrico Granata egranata at apple.com
Tue Jan 22 17:17:28 PST 2013


Author: enrico
Date: Tue Jan 22 19:17:27 2013
New Revision: 173216

URL: http://llvm.org/viewvc/llvm-project?rev=173216&view=rev
Log:
<rdar://problem/12711206>

Extending ValueObjectDynamicValue so that it stores a TypeAndOrName instead of a TypeSP.
This change allows us to reflect the notion that a ValueObject can have a dynamic type for which we have no debug information.
Previously, we would coalesce that to the static type of the object, potentially losing relevant information or even getting it wrong.
This fix ensures we can correctly report the class name for Cocoa objects whose types are hidden classes that we know nothing about (e.g. __NSArrayI for immutable arrays).
As a side effect, our --show-types argument to frame variable no longer needs to append custom dynamic type information.


Modified:
    lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h
    lldb/trunk/include/lldb/Symbol/Type.h
    lldb/trunk/include/lldb/Target/LanguageRuntime.h
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Symbol/Type.cpp
    lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py

Modified: lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h Tue Jan 22 19:17:27 2013
@@ -15,6 +15,7 @@
 // Other libraries and framework includes
 // Project includes
 #include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/Type.h"
 
 namespace lldb_private {
 
@@ -34,6 +35,9 @@
     virtual ConstString
     GetTypeName();
 
+    virtual ConstString
+    GetQualifiedTypeName();
+    
     virtual uint32_t
     CalculateNumChildren();
 
@@ -97,7 +101,7 @@
     GetClangTypeImpl ();
 
     Address  m_address;  ///< The variable that this value object is based upon
-    lldb::TypeSP m_type_sp;
+    TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name
     lldb::ValueObjectSP m_owning_valobj_sp;
     lldb::DynamicValueType m_use_dynamic;
 

Modified: lldb/trunk/include/lldb/Symbol/Type.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Type.h?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Type.h (original)
+++ lldb/trunk/include/lldb/Symbol/Type.h Tue Jan 22 19:17:27 2013
@@ -340,6 +340,12 @@
     TypeAndOrName &
     operator= (const TypeAndOrName &rhs);
     
+    bool
+    operator==(const TypeAndOrName &other) const;
+    
+    bool
+    operator!=(const TypeAndOrName &other) const;
+    
     ConstString GetName () const;
 
     lldb::TypeSP
@@ -360,6 +366,21 @@
     bool
     IsEmpty ();
     
+    bool
+    HasName ();
+    
+    bool
+    HasTypeSP ();
+    
+    void
+    Clear ();
+    
+    operator
+    bool ()
+    {
+        return !IsEmpty();
+    }
+    
 private:
     lldb::TypeSP m_type_sp;
     ConstString m_type_name;

Modified: lldb/trunk/include/lldb/Target/LanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/LanguageRuntime.h?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/LanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/LanguageRuntime.h Tue Jan 22 19:17:27 2013
@@ -44,6 +44,7 @@
     virtual bool
     GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) = 0;
     
+    // this call should return true if it could set the name and/or the type
     virtual bool
     GetDynamicTypeAndAddress (ValueObject &in_value, 
                               lldb::DynamicValueType use_dynamic, 

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Tue Jan 22 19:17:27 2013
@@ -3336,38 +3336,7 @@
                 show_type = options.m_show_types || (curr_depth == 0 && !options.m_flat_output);
             
             if (show_type)
-            {
-                const char* typeName = valobj->GetQualifiedTypeName().AsCString("<invalid type>");
-                //const char* typeName = valobj->GetTypeName().AsCString("<invalid type>");
-                s.Printf("(%s", typeName);
-                // only show dynamic types if the user really wants to see types
-                if (options.m_show_types && options.m_use_dynamic != eNoDynamicValues &&
-                    (/*strstr(typeName, "id") == typeName ||*/
-                     ClangASTType::GetMinimumLanguage(valobj->GetClangAST(), valobj->GetClangType()) == eLanguageTypeObjC))
-                {
-                    ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
-                    Process *process = exe_ctx.GetProcessPtr();
-                    if (process == NULL)
-                        s.Printf(", dynamic type: unknown) ");
-                    else
-                    {
-                        ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
-                        if (runtime == NULL)
-                            s.Printf(", dynamic type: unknown) ");
-                        else
-                        {
-                            ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetNonKVOClassDescriptor(*valobj));
-                            if (objc_class_sp)
-                                s.Printf(", dynamic type: %s) ", objc_class_sp->GetClassName().GetCString());
-                            else
-                                s.Printf(", dynamic type: unknown) ");
-                        }
-                    }
-                }
-                else
-                    s.Printf(") ");
-            }
-
+                s.Printf("(%s) ", valobj->GetQualifiedTypeName().AsCString("<invalid type>"));
 
             if (options.m_flat_output)
             {

Modified: lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectDynamicValue.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectDynamicValue.cpp Tue Jan 22 19:17:27 2013
@@ -38,7 +38,7 @@
 ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic) :
     ValueObject(parent),
     m_address (),
-    m_type_sp(),
+    m_dynamic_type_info(),
     m_use_dynamic (use_dynamic)
 {
     m_last_format_mgr_dynamic = use_dynamic;
@@ -53,7 +53,7 @@
 lldb::clang_type_t
 ValueObjectDynamicValue::GetClangTypeImpl ()
 {
-    if (m_type_sp)
+    if (m_dynamic_type_info.HasTypeSP())
         return m_value.GetClangType();
     else
         return m_parent->GetClangType();
@@ -63,17 +63,35 @@
 ValueObjectDynamicValue::GetTypeName()
 {
     const bool success = UpdateValueIfNeeded(false);
-    if (success && m_type_sp)
-        return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
-    else
-        return m_parent->GetTypeName();
+    if (success)
+    {
+        if (m_dynamic_type_info.HasTypeSP())
+            return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
+        if (m_dynamic_type_info.HasName())
+            return m_dynamic_type_info.GetName();
+    }
+    return m_parent->GetTypeName();
+}
+
+ConstString
+ValueObjectDynamicValue::GetQualifiedTypeName()
+{
+    const bool success = UpdateValueIfNeeded(false);
+    if (success)
+    {
+        if (m_dynamic_type_info.HasTypeSP())
+            return ClangASTType::GetConstQualifiedTypeName (GetClangAST(), GetClangType());
+        if (m_dynamic_type_info.HasName())
+            return m_dynamic_type_info.GetName();
+    }
+    return m_parent->GetTypeName();
 }
 
 uint32_t
 ValueObjectDynamicValue::CalculateNumChildren()
 {
     const bool success = UpdateValueIfNeeded(false);
-    if (success && m_type_sp)
+    if (success && m_dynamic_type_info.HasTypeSP())
         return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
     else
         return m_parent->GetNumChildren();
@@ -83,8 +101,8 @@
 ValueObjectDynamicValue::GetClangASTImpl ()
 {
     const bool success = UpdateValueIfNeeded(false);
-    if (success && m_type_sp)
-        return m_type_sp->GetClangAST();
+    if (success && m_dynamic_type_info.HasTypeSP())
+        return m_dynamic_type_info.GetTypeSP()->GetClangAST();
     else
         return m_parent->GetClangAST ();
 }
@@ -93,7 +111,7 @@
 ValueObjectDynamicValue::GetByteSize()
 {
     const bool success = UpdateValueIfNeeded(false);
-    if (success && m_type_sp)
+    if (success && m_dynamic_type_info.HasTypeSP())
         return m_value.GetValueByteSize(GetClangAST(), NULL);
     else
         return m_parent->GetByteSize();
@@ -123,7 +141,7 @@
     // parent which is equivalent to not using dynamic values.
     if (m_use_dynamic == lldb::eNoDynamicValues)
     {
-        m_type_sp.reset();
+        m_dynamic_type_info.Clear();
         return true;
     }
     
@@ -165,8 +183,6 @@
         }
     }
     
-    lldb::TypeSP dynamic_type_sp = class_type_or_name.GetTypeSP();
-    
     // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really
     // don't...
     
@@ -176,10 +192,10 @@
     // Or we could return false, and make ourselves an echo of our parent?
     if (!found_dynamic_type)
     {
-        if (m_type_sp)
+        if (m_dynamic_type_info)
             SetValueDidChange(true);
         ClearDynamicTypeInformation();
-        m_type_sp.reset();
+        m_dynamic_type_info.Clear();
         m_value = m_parent->GetValue();
         m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
         return m_error.Success();
@@ -191,15 +207,15 @@
     
     bool has_changed_type = false;
     
-    if (!m_type_sp)
+    if (!m_dynamic_type_info)
     {
-        m_type_sp = dynamic_type_sp;
+        m_dynamic_type_info = class_type_or_name;
         has_changed_type = true;
     }
-    else if (dynamic_type_sp != m_type_sp)
+    else if (class_type_or_name != m_dynamic_type_info)
     {
         // We are another type, we need to tear down our children...
-        m_type_sp = dynamic_type_sp;
+        m_dynamic_type_info = class_type_or_name;
         SetValueDidChange (true);
         has_changed_type = true;
     }
@@ -219,16 +235,34 @@
         m_value.GetScalar() = load_address;
     }
     
-    // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
-    // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
-    // should be okay...
-    lldb::clang_type_t orig_type = m_type_sp->GetClangForwardType();
-    lldb::clang_type_t corrected_type = orig_type;
-    if (m_parent->IsPointerType())
-        corrected_type = ClangASTContext::CreatePointerType (m_type_sp->GetClangAST(), orig_type);
-    else if (m_parent->IsPointerOrReferenceType())
-        corrected_type = ClangASTContext::CreateLValueReferenceType (m_type_sp->GetClangAST(), orig_type);
-        
+    lldb::clang_type_t corrected_type;
+    if (m_dynamic_type_info.HasTypeSP())
+    {
+        // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
+        // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
+        // should be okay...
+        lldb::clang_type_t orig_type;
+        clang::ASTContext* ast;
+        orig_type = m_dynamic_type_info.GetTypeSP()->GetClangForwardType();
+        ast = m_dynamic_type_info.GetTypeSP()->GetClangAST();
+        corrected_type = orig_type;
+        if (m_parent->IsPointerType())
+            corrected_type = ClangASTContext::CreatePointerType (ast, orig_type);
+        else if (m_parent->IsPointerOrReferenceType())
+            corrected_type = ClangASTContext::CreateLValueReferenceType (ast, orig_type);
+    }
+    else /*if (m_dynamic_type_info.HasName())*/
+    {
+        // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
+        std::string type_name_buf (m_dynamic_type_info.GetName().GetCString());
+        if (m_parent->IsPointerType())
+            type_name_buf.append(" *");
+        else if (m_parent->IsPointerOrReferenceType())
+            type_name_buf.append(" &");
+        corrected_type = m_parent->GetClangType();
+        m_dynamic_type_info.SetName(type_name_buf.c_str());
+    }
+    
     m_value.SetContext (Value::eContextTypeClangType, corrected_type);
     
     // Our address is the location of the dynamic type stored in memory.  It isn't a load address,
@@ -241,7 +275,7 @@
                     this,
                     GetTypeName().GetCString());
     
-    if (m_address.IsValid() && m_type_sp)
+    if (m_address.IsValid() && m_dynamic_type_info)
     {
         // The variable value is in the Scalar value inside the m_value.
         // We can point our m_data right to it.

Modified: lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp Tue Jan 22 19:17:27 2013
@@ -59,6 +59,8 @@
     // start of the value object which holds the dynamic type.
     //
     
+    class_type_or_name.Clear();
+    
     // Only a pointer or reference type can have a different dynamic and static type:
     if (CouldHaveDynamicValue (in_value))
     {
@@ -271,7 +273,7 @@
         }
     }
     
-    return false;
+    return class_type_or_name.IsEmpty() == false;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Tue Jan 22 19:17:27 2013
@@ -329,6 +329,8 @@
     // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
     assert (in_value.GetProcessSP().get() == m_process);
     assert (m_process != NULL);
+    
+    class_type_or_name.Clear();
 
     // Make sure we can have a dynamic value before starting...
     if (CouldHaveDynamicValue (in_value))
@@ -354,12 +356,9 @@
                     class_type_or_name.SetTypeSP (type_sp);
                 }
             }
-            
-            if (type_sp)
-                return true;
         }
     }    
-    return false;
+    return class_type_or_name.IsEmpty() == false;
 }
 
 //------------------------------------------------------------------

Modified: lldb/trunk/source/Symbol/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Type.cpp?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Type.cpp (original)
+++ lldb/trunk/source/Symbol/Type.cpp Tue Jan 22 19:17:27 2013
@@ -828,6 +828,26 @@
     return *this;
 }
 
+bool
+TypeAndOrName::operator==(const TypeAndOrName &other) const
+{
+    if (m_type_sp != other.m_type_sp)
+        return false;
+    if (m_type_name != other.m_type_name)
+        return false;
+    return true;
+}
+
+bool
+TypeAndOrName::operator!=(const TypeAndOrName &other) const
+{
+    if (m_type_sp != other.m_type_sp)
+        return true;
+    if (m_type_name != other.m_type_name)
+        return true;
+    return false;
+}
+
 ConstString
 TypeAndOrName::GetName () const
 {    
@@ -866,6 +886,25 @@
         return true;
 }
 
+void
+TypeAndOrName::Clear ()
+{
+    m_type_name.Clear();
+    m_type_sp.reset();
+}
+
+bool
+TypeAndOrName::HasName ()
+{
+    return (bool)m_type_name;
+}
+
+bool
+TypeAndOrName::HasTypeSP ()
+{
+    return m_type_sp.get() != NULL;
+}
+
 TypeImpl::TypeImpl(const lldb_private::ClangASTType& clang_ast_type) :
     m_clang_ast_type(clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType()),
     m_type_sp()

Modified: lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py?rev=173216&r1=173215&r2=173216&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py (original)
+++ lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py Tue Jan 22 19:17:27 2013
@@ -116,10 +116,10 @@
         # check that our ObjC GetISA() does a good job at hiding KVO swizzled classes
         
         self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden',
-                    substrs = ['dynamic type: SourceDerived'])
+                    substrs = ['SourceDerived'])
 
         self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', matching = False,
-                    substrs = ['dynamic type: NSKVONotify'])
+                    substrs = ['NSKVONotify'])
 
         # This test is not entirely related to the main thrust of this test case, but since we're here,
         # try stepping into setProperty, and make sure we get into the version in Source:





More information about the lldb-commits mailing list