diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2578,10 +2578,14 @@ } } - if ((this_field_info.bit_offset >= parent_bit_size) || - (last_field_info.IsBitfield() && - !last_field_info.NextBitfieldOffsetIsValid( - this_field_info.bit_offset))) { + // The ObjC runtime knows the byte offset but we still need to provide + // the bit-offset in the layout. It just means something different then + // what it does in C and C++. So we skip this check for ObjC types. + if (!TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type) && + ((this_field_info.bit_offset >= parent_bit_size) || + (last_field_info.IsBitfield() && + !last_field_info.NextBitfieldOffsetIsValid( + this_field_info.bit_offset)))) { ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); objfile->GetModule()->ReportWarning( "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid " diff --git a/lldb/test/API/lang/objc/bitfield_ivars/Makefile b/lldb/test/API/lang/objc/bitfield_ivars/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/objc/bitfield_ivars/Makefile @@ -0,0 +1,4 @@ +OBJC_SOURCES := main.m +LD_EXTRAS = -framework Foundation + +include Makefile.rules diff --git a/lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py b/lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py --- a/lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py +++ b/lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py @@ -1,12 +1,39 @@ -from lldbsuite.test import lldbinline -from lldbsuite.test import decorators - -lldbinline.MakeInlineTest( - __file__, - globals(), - [ - # This is a Darwin-only failure related to incorrect expression- - # evaluation for single-bit ObjC bitfields. - decorators.skipUnlessDarwin, - decorators.expectedFailureAll( - bugnumber="rdar://problem/17990991")]) +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBitfieldIvars(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + + @skipUnlessDarwin + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.m")) + + self.expect_expr("chb->hb->field1", result_type="unsigned int", result_value="0") + + ## FIXME field2 should have a value of 1 + self.expect("expr chb->hb->field2", matching=False, substrs = ["= 1"]) # this must happen second + + self.expect_expr("hb2->field1", result_type="unsigned int", result_value="10") + self.expect_expr("hb2->field2", result_type="unsigned int", result_value="3") + self.expect_expr("hb2->field3", result_type="unsigned int", result_value="4") + + self.expect("frame var *hb2", substrs = [ 'x =', '100', + 'field1 =', '10', + 'field2 =', '3', + 'field3 =', '4']) + + @expectedFailureAll() + def testExprWholeObject(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.m")) + + ## FIXME expression with individual bit-fields obtains correct values but not with the whole object + self.expect("expr *hb2", substrs = [ 'x =', '100', + 'field1 =', '10', + 'field2 =', '3', + 'field3 =', '4']) diff --git a/lldb/test/API/lang/objc/bitfield_ivars/main.m b/lldb/test/API/lang/objc/bitfield_ivars/main.m --- a/lldb/test/API/lang/objc/bitfield_ivars/main.m +++ b/lldb/test/API/lang/objc/bitfield_ivars/main.m @@ -34,10 +34,31 @@ @end +@interface HasBitfield2 : NSObject { +@public + unsigned int x; + + unsigned field1 : 15; + unsigned field2 : 4; + unsigned field3 : 4; +} +@end + +@implementation HasBitfield2 +- (id)init { + return (self = [super init]); +} +@end + int main(int argc, const char * argv[]) { ContainsAHasBitfield *chb = [[ContainsAHasBitfield alloc] init]; - printf("%d\n", chb->hb->field2); //% self.expect("expression -- chb->hb->field1", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["= 0"]) - //% self.expect("expression -- chb->hb->field2", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["= 1"]) # this must happen second - return 0; + HasBitfield2 *hb2 = [[HasBitfield2 alloc] init]; + + hb2->x = 100; + hb2->field1 = 10; + hb2->field2 = 3; + hb2->field3 = 4; + + return 0; // break here }