diff --git a/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/lldb/include/lldb/Core/ValueObjectDynamicValue.h index a76ca10d637d..fd174e1d11d2 100644 --- a/lldb/include/lldb/Core/ValueObjectDynamicValue.h +++ b/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -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 @@ public: virtual ConstString GetTypeName(); + virtual ConstString + GetQualifiedTypeName(); + virtual uint32_t CalculateNumChildren(); @@ -97,7 +101,7 @@ protected: 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; diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 40bbd10b83a1..f3b381efd396 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -340,6 +340,12 @@ public: 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 @@ public: bool IsEmpty (); + bool + HasName (); + + bool + HasTypeSP (); + + void + Clear (); + + operator + bool () + { + return !IsEmpty(); + } + private: lldb::TypeSP m_type_sp; ConstString m_type_name; diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index 5a4dc7ae7f62..cafbff03a038 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -44,6 +44,7 @@ public: 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, diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 449e49c0720a..92d2c36415e0 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -3336,38 +3336,7 @@ DumpValueObject_Impl (Stream &s, show_type = options.m_show_types || (curr_depth == 0 && !options.m_flat_output); if (show_type) - { - const char* typeName = valobj->GetQualifiedTypeName().AsCString(""); - //const char* typeName = valobj->GetTypeName().AsCString(""); - 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("")); if (options.m_flat_output) { diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index 9eb63b83a48e..8cd1d1f547b4 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -38,7 +38,7 @@ using namespace lldb_private; 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 @@ ValueObjectDynamicValue::~ValueObjectDynamicValue() 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 @@ ConstString 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 @@ clang::ASTContext * 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 @@ size_t 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 @@ ValueObjectDynamicValue::UpdateValue () // 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 @@ ValueObjectDynamicValue::UpdateValue () } } - 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 @@ ValueObjectDynamicValue::UpdateValue () // 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 @@ ValueObjectDynamicValue::UpdateValue () 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 @@ ValueObjectDynamicValue::UpdateValue () 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 @@ ValueObjectDynamicValue::UpdateValue () 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. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 44b8468428c5..2cd340980c10 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -59,6 +59,8 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, // 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 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, } } - return false; + return class_type_or_name.IsEmpty() == false; } bool diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index f194ac3d2d91..cfe7d13c697e 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -329,6 +329,8 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, // 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 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, class_type_or_name.SetTypeSP (type_sp); } } - - if (type_sp) - return true; } } - return false; + return class_type_or_name.IsEmpty() == false; } //------------------------------------------------------------------ diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index c2d1cddcc363..03fc429bb454 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -828,6 +828,26 @@ TypeAndOrName::operator= (const TypeAndOrName &rhs) 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 @@ TypeAndOrName::IsEmpty() 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() diff --git a/lldb/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py b/lldb/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py index 40a1281a8af3..2fb73fba6b67 100644 --- a/lldb/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py +++ b/lldb/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py @@ -116,10 +116,10 @@ class ObjCDynamicValueTestCase(TestBase): # 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: