Filter non-external static members from SBType::GetFieldAtIndex.
authorSigurur sgeirsson <siggi@alpheus.dev>
Mon, 9 May 2022 09:53:23 +0000 (11:53 +0200)
committerPavel Labath <pavel@labath.sk>
Mon, 9 May 2022 10:34:13 +0000 (12:34 +0200)
See [[ https://github.com/llvm/llvm-project/issues/55040 | issue 55040 ]] where static members of classes declared in the anonymous namespace are incorrectly returned as member fields from lldb::SBType::GetFieldAtIndex(). It appears that attrs.member_byte_offset contains a sentinel value for members that don't have a DW_AT_data_member_location.

Reviewed By: labath

Differential Revision: https://reviews.llvm.org/D124409

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/test/Shell/SymbolFile/DWARF/x86/debug_static-member-anonymous-namespace.s [new file with mode: 0644]

index 4ec5013..f7164d0 100644 (file)
@@ -2408,8 +2408,6 @@ struct MemberAttributes {
   /// structure.
   uint32_t member_byte_offset;
   bool is_artificial = false;
-  /// On DW_TAG_members, this means the member is static.
-  bool is_external = false;
 };
 
 /// Parsed form of all attributes that are relevant for parsing Objective-C
@@ -2485,9 +2483,6 @@ MemberAttributes::MemberAttributes(const DWARFDIE &die,
       case DW_AT_artificial:
         is_artificial = form_value.Boolean();
         break;
-      case DW_AT_external:
-        is_external = form_value.Boolean();
-        break;
       default:
         break;
       }
@@ -2632,8 +2627,10 @@ void DWARFASTParserClang::ParseSingleMember(
   if (class_is_objc_object_or_interface)
     attrs.accessibility = eAccessNone;
 
-  // Handle static members
-  if (attrs.is_external && attrs.member_byte_offset == UINT32_MAX) {
+  // Handle static members, which is any member that doesn't have a bit or a
+  // byte member offset.
+  if (attrs.member_byte_offset == UINT32_MAX &&
+      attrs.data_bit_offset == UINT64_MAX) {
     Type *var_type = die.ResolveTypeUID(attrs.encoding_form.Reference());
 
     if (var_type) {
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_static-member-anonymous-namespace.s b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_static-member-anonymous-namespace.s
new file mode 100644 (file)
index 0000000..bbe36eb
--- /dev/null
@@ -0,0 +1,173 @@
+# RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj %s -o %t
+# RUN: %lldb -o "target variable ug U::s" -b %t | FileCheck %s
+
+# CHECK: (lldb) target variable ug
+# CHECK: (U) ug = (m = 14159265)
+# CHECK: (int) U::s = 65295141
+
+# This tests that a static member in a class declared in the anonymous namespace
+# does not appear as a field of the class. There is a difference between the
+# debug info generated by gcc and clang, where clang flags the static member
+# with DW_AT_external, but gcc does not.
+#
+# Roughly corresponds to this source code:
+#
+# namespace {
+# struct U {
+#   static int s;
+#   int m = 14159265;
+# };
+# int U::s = 65295141;
+# }
+#
+# U ug;
+
+        .file   "test.cpp"
+        .data
+        .quad 0
+ug:
+        .long 14159265
+.Lug_s:
+        .long 65295141
+
+        .section        .debug_info,"",@progbits
+.Ldebug_info0:
+        .long   .Lcu_end-.Lcu_begin
+.Lcu_begin:
+        .value  0x4
+        .long   .Ldebug_abbrev0
+        .byte   0x8
+        .uleb128 0x1
+        .asciz  "GCC DWARF reduced by hand"
+        .byte   0x4
+        .asciz  "test.cpp"
+        .uleb128 0x2
+.LU:
+        .uleb128 0x3
+        .string "U"
+        .byte   0x4
+.LU_s:
+        .uleb128 0x4
+        .string "s"
+        .long   .Lint-.Ldebug_info0
+        .uleb128 0x5
+        .string "m"
+        .long   .Lint-.Ldebug_info0
+        .byte   0
+        .byte   0
+        .byte   0
+        .uleb128 0x6
+        .long   0x2d
+.Lint:
+        .uleb128 0x7
+        .byte   0x4
+        .byte   0x5
+        .string "int"
+        .uleb128 0x9
+        .string "ug"
+        .long   .LU-.Ldebug_info0
+        .uleb128 0x9
+        .byte   0x3
+        .quad   ug
+        .uleb128 0xa
+        .long   .LU_s-.Ldebug_info0
+        .uleb128 0x9
+        .byte   0x3
+        .quad .Lug_s
+        .byte   0
+.Lcu_end:
+        .section        .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+        .uleb128 0x1
+        .uleb128 0x11
+        .byte   0x1
+        .uleb128 0x25
+        .uleb128 0x8
+        .uleb128 0x13
+        .uleb128 0xb
+        .uleb128 0x3
+        .uleb128 0x8
+        .byte   0
+        .byte   0
+        .uleb128 0x2
+        .uleb128 0x39
+        .byte   0x1
+        .byte   0
+        .byte   0
+        .uleb128 0x3
+        .uleb128 0x13
+        .byte   0x1
+        .uleb128 0x3
+        .uleb128 0x8
+        .uleb128 0xb
+        .uleb128 0xb
+        .byte   0
+        .byte   0
+        .uleb128 0x4
+        .uleb128 0xd
+        .byte   0
+        .uleb128 0x3
+        .uleb128 0x8
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x3c
+        .uleb128 0x19
+        .byte   0
+        .byte   0
+        .uleb128 0x5
+        .uleb128 0xd
+        .byte   0
+        .uleb128 0x3
+        .uleb128 0x8
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x38
+        .uleb128 0xb
+        .byte   0
+        .byte   0
+        .uleb128 0x6
+        .uleb128 0x3a
+        .byte   0
+        .uleb128 0x18
+        .uleb128 0x13
+        .byte   0
+        .byte   0
+        .uleb128 0x7
+        .uleb128 0x24
+        .byte   0
+        .uleb128 0xb
+        .uleb128 0xb
+        .uleb128 0x3e
+        .uleb128 0xb
+        .uleb128 0x3
+        .uleb128 0x8
+        .byte   0
+        .byte   0
+        .uleb128 0x8
+        .uleb128 0x26
+        .byte   0
+        .uleb128 0x49
+        .uleb128 0x13
+        .byte   0
+        .byte   0
+        .uleb128 0x9
+        .uleb128 0x34
+        .byte   0
+        .uleb128 0x3
+        .uleb128 0x8
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x2
+        .uleb128 0x18
+        .byte   0
+        .byte   0
+       .uleb128 0xa
+       .uleb128 0x34
+       .byte   0
+       .uleb128 0x47
+       .uleb128 0x13
+       .uleb128 0x2
+       .uleb128 0x18
+       .byte   0
+       .byte   0
+        .byte   0