forked from OSchip/llvm-project
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:
parent
56d6fdf695
commit
f80bc3f447
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue