diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index d156dae71245..85c6e39e11f6 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -3458,7 +3458,7 @@ ClangASTContext::GetChildClangTypeAtIndex { if (child_idx == idx) { - const ObjCIvarDecl* ivar_decl = *ivar_pos; + ObjCIvarDecl* ivar_decl = *ivar_pos; QualType ivar_qual_type(ivar_decl->getType()); @@ -3487,12 +3487,26 @@ ClangASTContext::GetChildClangTypeAtIndex } } + // Setting this to UINT32_MAX to make sure we don't compute it twice... + bit_offset = UINT32_MAX; + if (child_byte_offset == LLDB_INVALID_IVAR_OFFSET) { bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); child_byte_offset = bit_offset / 8; } - + + // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset + // of a bitfield within its containing object. So regardless of where we get the byte + // offset from, we still need to get the bit offset for bitfields from the layout. + + if (ClangASTContext::FieldIsBitfield (ast, ivar_decl, child_bitfield_bit_size)) + { + if (bit_offset == UINT32_MAX) + bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); + + child_bitfield_bit_offset = bit_offset % 8; + } return ivar_qual_type.getAsOpaquePtr(); } ++child_idx; diff --git a/lldb/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py b/lldb/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py index 9308658329c2..9b490800d78d 100644 --- a/lldb/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py +++ b/lldb/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py @@ -56,18 +56,34 @@ class TestObjCIvarOffsets(TestBase): # Test the value object value for BaseClass->_backed_int + error = lldb.SBError() + mine_backed_int = mine.GetChildMemberWithName ("_backed_int") self.assertTrue(mine_backed_int, "Found mine->backed_int local variable.") - backed_value = int (mine_backed_int.GetValue (), 0) + backed_value = mine_backed_int.GetValueAsSigned (error) + self.assertTrue (error.Success()) self.assertTrue (backed_value == 1111) # Test the value object value for DerivedClass->_derived_backed_int mine_derived_backed_int = mine.GetChildMemberWithName ("_derived_backed_int") self.assertTrue(mine_derived_backed_int, "Found mine->derived_backed_int local variable.") - derived_backed_value = int (mine_derived_backed_int.GetValue (), 0) + derived_backed_value = mine_derived_backed_int.GetValueAsSigned (error) + self.assertTrue (error.Success()) self.assertTrue (derived_backed_value == 3333) - + + # Make sure we also get bit-field offsets correct: + + mine_flag2 = mine.GetChildMemberWithName ("flag2") + self.assertTrue(mine_flag2, "Found mine->flag2 local variable.") + flag2_value = int (mine_flag2.GetValue (), 0) + self.assertTrue (flag2_value == 7) + + # GetValueAsUnsigned fails for bit-fields: +# flag2_value = mine_flag2.GetValueAsUnsigned (error) +# self.assertTrue (error.Success()) +# self.assertTrue (flag2_value == 7) + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() diff --git a/lldb/test/lang/objc/objc-ivar-offsets/main.m b/lldb/test/lang/objc/objc-ivar-offsets/main.m index 206255f6a213..41943f48aef5 100644 --- a/lldb/test/lang/objc/objc-ivar-offsets/main.m +++ b/lldb/test/lang/objc/objc-ivar-offsets/main.m @@ -8,6 +8,8 @@ main () mine.unbacked_int = 2222; mine.derived_backed_int = 3333; mine.derived_unbacked_int = 4444; + mine->flag1 = 1; + mine->flag2 = 7; return 0; // Set breakpoint here. } diff --git a/lldb/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h b/lldb/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h index 890e04f0d4fa..99bbd427b064 100644 --- a/lldb/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h +++ b/lldb/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h @@ -17,7 +17,11 @@ #if !__OBJC2__ int _derived_unbacked_int; #endif + @public + uint32_t flag1 : 1; + uint32_t flag2 : 3; } + @property int derived_backed_int; @property int derived_unbacked_int; @end