Get the bit-field offset & size for ObjC ivars that are bitfields.

<rdar://problem/10535460> lldb expression evaluation doesn't handle bit fields in ObjC classes properly

llvm-svn: 146134
This commit is contained in:
Jim Ingham 2011-12-08 02:53:10 +00:00
parent 56d6fdf695
commit f80bc3f447
4 changed files with 41 additions and 5 deletions

View File

@ -3458,7 +3458,7 @@ ClangASTContext::GetChildClangTypeAtIndex
{ {
if (child_idx == idx) if (child_idx == idx)
{ {
const ObjCIvarDecl* ivar_decl = *ivar_pos; ObjCIvarDecl* ivar_decl = *ivar_pos;
QualType ivar_qual_type(ivar_decl->getType()); 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) if (child_byte_offset == LLDB_INVALID_IVAR_OFFSET)
{ {
bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
child_byte_offset = bit_offset / 8; 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(); return ivar_qual_type.getAsOpaquePtr();
} }
++child_idx; ++child_idx;

View File

@ -56,18 +56,34 @@ class TestObjCIvarOffsets(TestBase):
# Test the value object value for BaseClass->_backed_int # Test the value object value for BaseClass->_backed_int
error = lldb.SBError()
mine_backed_int = mine.GetChildMemberWithName ("_backed_int") mine_backed_int = mine.GetChildMemberWithName ("_backed_int")
self.assertTrue(mine_backed_int, "Found mine->backed_int local variable.") 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) self.assertTrue (backed_value == 1111)
# Test the value object value for DerivedClass->_derived_backed_int # Test the value object value for DerivedClass->_derived_backed_int
mine_derived_backed_int = mine.GetChildMemberWithName ("_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.") 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) 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__': if __name__ == '__main__':
import atexit import atexit
lldb.SBDebugger.Initialize() lldb.SBDebugger.Initialize()

View File

@ -8,6 +8,8 @@ main ()
mine.unbacked_int = 2222; mine.unbacked_int = 2222;
mine.derived_backed_int = 3333; mine.derived_backed_int = 3333;
mine.derived_unbacked_int = 4444; mine.derived_unbacked_int = 4444;
mine->flag1 = 1;
mine->flag2 = 7;
return 0; // Set breakpoint here. return 0; // Set breakpoint here.
} }

View File

@ -17,7 +17,11 @@
#if !__OBJC2__ #if !__OBJC2__
int _derived_unbacked_int; int _derived_unbacked_int;
#endif #endif
@public
uint32_t flag1 : 1;
uint32_t flag2 : 3;
} }
@property int derived_backed_int; @property int derived_backed_int;
@property int derived_unbacked_int; @property int derived_unbacked_int;
@end @end