shafik created this revision.
shafik added reviewers: teemperor, jingham, aprantl.

Currently expressions dealing with bit-fields in Objective-C objects is pretty 
broken. When generating debug-info for Objective-C bit-fields we don't generate 
offsets because the Objective-C runtime is supposed to handle generating the 
offsets for us.

When we parse the DWARF we expect to always have valid bit offsets and if we 
don't we treat that as an error and stop adding bit-fields to the AST.

Later on when we do a name lookup we don't find the `ObjCIvarDecl` in the 
`ObjCInterfaceDecl` in some cases since we never added it and then we don't go 
to the runtime to obtain the offset.

This will fix how we handle bit-fields for the Objective-C case and add tests 
to verify this fix but also to documents areas that still don't work and will 
be addressed in follow-up PRs.


https://reviews.llvm.org/D83433

Files:
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/test/API/lang/objc/bitfield_ivars/Makefile
  lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py
  lldb/test/API/lang/objc/bitfield_ivars/main.m

Index: lldb/test/API/lang/objc/bitfield_ivars/main.m
===================================================================
--- lldb/test/API/lang/objc/bitfield_ivars/main.m
+++ 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
 }
 
Index: lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py
===================================================================
--- lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py
+++ lldb/test/API/lang/objc/bitfield_ivars/TestBitfieldIvars.py
@@ -1,12 +1,32 @@
-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__)
+
+    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")
+
+    @expectedFailureAll()
+    def ExpressionOnObject(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'])
Index: lldb/test/API/lang/objc/bitfield_ivars/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/objc/bitfield_ivars/Makefile
@@ -0,0 +1,4 @@
+OBJC_SOURCES := main.m
+LD_EXTRAS = -framework Foundation
+
+include Makefile.rules
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2609,10 +2609,11 @@
               }
             }
 
-            if ((this_field_info.bit_offset >= parent_bit_size) ||
-                (last_field_info.IsBitfield() &&
-                 !last_field_info.NextBitfieldOffsetIsValid(
-                     this_field_info.bit_offset))) {
+            if (class_language != eLanguageTypeObjC &&
+                ((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 "
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to