From df7c7f99baa027b72e4f56b521dd2a6fc7192f90 Mon Sep 17 00:00:00 2001 From: Enrico Granata Date: Tue, 29 Oct 2013 17:42:02 +0000 Subject: [PATCH] Fixing an issue in yesterday's dynamic type changes where we would not craft a valid SBType given debug information Added a test case to help us detect regression in this realm llvm-svn: 193631 --- lldb/include/lldb/Symbol/ClangASTType.h | 3 ++ lldb/source/Core/ValueObjectDynamicValue.cpp | 29 +++++++++++--- lldb/source/Symbol/ClangASTType.cpp | 15 +++++++ .../objc/objc-dyn-sbtype/TestObjCDynamicSBType.py | 29 ++++++++++++-- lldb/test/lang/objc/objc-dyn-sbtype/main.m | 46 ++++++++++++++++++++++ 5 files changed, 112 insertions(+), 10 deletions(-) diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index e5cced3..19b5d6e 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -201,6 +201,9 @@ public: IsPointerToScalarType () const; bool + IsRuntimeGeneratedType () const; + + bool IsPointerType (ClangASTType *pointee_type = NULL) const; bool diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index 64f9750..ff8a0ed 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -81,7 +81,7 @@ TypeImpl ValueObjectDynamicValue::GetTypeImpl () { const bool success = UpdateValueIfNeeded(false); - if (success) + if (success && m_type_impl.IsValid()) { return m_type_impl; } @@ -225,12 +225,29 @@ ValueObjectDynamicValue::UpdateValue () m_update_point.SetUpdated(); - // if the runtime only vended a ClangASTType, then we have an hollow type that we don't want to use - // but we save it for the TypeImpl, which can still use an hollow type for some questions - if (found_dynamic_type && class_type_or_name.HasType() && !class_type_or_name.HasTypeSP()) + if (found_dynamic_type) + { + if (class_type_or_name.HasType()) + { + // TypeSP are always generated from debug info + if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType()) + { + m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); + class_type_or_name.SetClangASTType(ClangASTType()); + } + else + { + m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); + } + } + else + { + m_type_impl.Clear(); + } + } + else { - m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); - class_type_or_name.SetClangASTType(ClangASTType()); + m_type_impl.Clear(); } // If we don't have a dynamic type, then make ourselves just a echo of our parent. diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index b0413ed..7d66766 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -288,6 +288,21 @@ ClangASTType::IsArrayType (ClangASTType *element_type_ptr, return 0; } +bool +ClangASTType::IsRuntimeGeneratedType () const +{ + if (!IsValid()) + return false; + clang::DeclContext* decl_ctx = GetDeclContextForType(); + if (!decl_ctx) + return false; + if (!llvm::isa(decl_ctx)) + return false; + ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(m_ast, decl_ctx); + if (!ast_metadata) + return false; + return (ast_metadata->GetISAPtr() != 0); +} bool ClangASTType::IsCharType () const diff --git a/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py b/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py index 9dae1e4..3d14339 100644 --- a/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py +++ b/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py @@ -1,5 +1,5 @@ """ -Test that we are able to properly report a usable dynamic type for NSImage +Test that we are able to properly report a usable dynamic type """ import os, time @@ -16,7 +16,7 @@ class ObjCDynamicSBTypeTestCase(TestBase): @dsym_test @skipIfi386 def test_nsimage_dyn_with_dsym(self): - """Test that we are able to properly report a usable dynamic type for NSImage.""" + """Test that we are able to properly report a usable dynamic type.""" d = {'EXE': self.exe_name} self.buildDsym(dictionary=d) self.setTearDownCleanup(dictionary=d) @@ -25,7 +25,7 @@ class ObjCDynamicSBTypeTestCase(TestBase): @dwarf_test @skipIfi386 def test_nsimage_dyn_with_dwarf(self): - """Test that we are able to properly report a usable dynamic type for NSImage.""" + """Test that we are able to properly report a usable dynamic type.""" d = {'EXE': self.exe_name} self.buildDwarf(dictionary=d) self.setTearDownCleanup(dictionary=d) @@ -41,7 +41,7 @@ class ObjCDynamicSBTypeTestCase(TestBase): self.line = line_number(self.main_source, '// Set breakpoint here.') def nsimage_dyn(self, exe_name): - """Test that we are able to properly report a usable dynamic type for NSImage.""" + """Test that we are able to properly report a usable dynamic type.""" exe = os.path.join(os.getcwd(), exe_name) self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -57,6 +57,27 @@ class ObjCDynamicSBTypeTestCase(TestBase): self.assertTrue(image_pointee_type.GetName() == "NSImage", "The dynamic type figures out its pointee type just fine") self.assertTrue(image_pointee_type.GetDirectBaseClassAtIndex(0).GetName() == "NSObject", "The dynamic type can go back to its base class") + v_object = self.frame().FindVariable("object").GetDynamicValue(lldb.eDynamicCanRunTarget) + v_base = self.frame().FindVariable("base").GetDynamicValue(lldb.eDynamicCanRunTarget) + self.assertTrue(v_object.GetTypeName() == "MyDerivedClass *", "The NSObject is properly type-named") + self.assertTrue(v_base.GetTypeName() == "MyDerivedClass *", "The Base is properly type-named") + object_type = v_object.GetType() + base_type = v_base.GetType() + self.assertTrue(object_type.GetName() == "MyDerivedClass *", "The dynamic SBType for NSObject is for the correct type") + self.assertTrue(base_type.GetName() == "MyDerivedClass *", "The dynamic SBType for Base is for the correct type") + object_pointee_type = object_type.GetPointeeType() + base_pointee_type = base_type.GetPointeeType() + self.assertTrue(object_pointee_type.GetName() == "MyDerivedClass", "The dynamic type for NSObject figures out its pointee type just fine") + self.assertTrue(base_pointee_type.GetName() == "MyDerivedClass", "The dynamic type for Base figures out its pointee type just fine") + + self.assertTrue(object_pointee_type.GetDirectBaseClassAtIndex(0).GetName() == "MyBaseClass", "The dynamic type for NSObject can go back to its base class") + self.assertTrue(base_pointee_type.GetDirectBaseClassAtIndex(0).GetName() == "MyBaseClass", "The dynamic type for Base can go back to its base class") + + self.assertTrue(object_pointee_type.GetDirectBaseClassAtIndex(0).GetType().GetDirectBaseClassAtIndex(0).GetName() == "NSObject", "The dynamic type for NSObject can go up the hierarchy") + self.assertTrue(base_pointee_type.GetDirectBaseClassAtIndex(0).GetType().GetDirectBaseClassAtIndex(0).GetName() == "NSObject", "The dynamic type for Base can go up the hierarchy") + + self.assertTrue(object_pointee_type.GetNumberOfFields() == 2, "The dynamic type for NSObject has 2 fields") + self.assertTrue(base_pointee_type.GetNumberOfFields() == 2, "The dynamic type for Base has 2 fields") if __name__ == '__main__': import atexit diff --git a/lldb/test/lang/objc/objc-dyn-sbtype/main.m b/lldb/test/lang/objc/objc-dyn-sbtype/main.m index de757bc..c64f196 100644 --- a/lldb/test/lang/objc/objc-dyn-sbtype/main.m +++ b/lldb/test/lang/objc/objc-dyn-sbtype/main.m @@ -1,12 +1,58 @@ #import #import +@interface MyBaseClass : NSObject +{} +-(id) init; +-(int) getInt; +@end + +@implementation MyBaseClass +- (id) init { + return (self = [super init]); +} + +- (int) getInt { + return 1; +} +@end + +@interface MyDerivedClass : MyBaseClass +{ + int x; + int y; +} +-(id) init; +-(int) getInt; +@end + +@implementation MyDerivedClass +- (id) init { + self = [super init]; + if (self) { + self-> x = 0; + self->y = 1; + } + return self; +} + +- (int) getInt { + y = x++; + return x; +} +@end + + int main (int argc, char const *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSSize size = {10,10}; NSImage *image = [[NSImage alloc] initWithSize:size]; + + NSObject* object = [[MyDerivedClass alloc] init]; + MyBaseClass* base = [[MyDerivedClass alloc] init]; + [pool release]; // Set breakpoint here. return 0; } -- 2.7.4