diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -223,12 +223,16 @@ uint64_t bit_size = 0; uint64_t bit_offset = 0; bool is_bitfield = false; + bool is_artificial = false; FieldInfo() = default; void SetIsBitfield(bool flag) { is_bitfield = flag; } bool IsBitfield() { return is_bitfield; } + void SetIsArtificial(bool flag) { is_artificial = flag; } + bool IsArtificial() const { return is_artificial; } + bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const { // Any subsequent bitfields must not overlap and must be at a higher // bit offset than any previous bitfield + size. 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 @@ -2934,8 +2934,10 @@ // artificial member with (unnamed bitfield) padding. // FIXME: This check should verify that this is indeed an artificial member // we are supposed to ignore. - if (attrs.is_artificial) + if (attrs.is_artificial) { + last_field_info.SetIsArtificial(true); return; + } if (!member_clang_type.IsCompleteType()) member_clang_type.GetCompleteType(); @@ -3699,17 +3701,23 @@ return false; // If we have a base class, we assume there is no unnamed - // bit-field if this is the first field since the gap can be - // attributed to the members from the base class. This assumption - // is not correct if the first field of the derived class is - // indeed an unnamed bit-field. We currently do not have the - // machinary to track the offset of the last field of classes we - // have seen before, so we are not handling this case. + // bit-field if either of the following is true: + // (a) this is the first field since the gap can be + // attributed to the members from the base class. + // FIXME: This assumption is not correct if the first field of + // the derived class is indeed an unnamed bit-field. We currently + // do not have the machinary to track the offset of the last field + // of classes we have seen before, so we are not handling this case. + // (b) Or, the first member of the derived class was a vtable pointer. + // In this case we don't want to create an unnamed bitfield either + // since those will be inserted by clang later. const bool have_base = layout_info.base_offsets.size() != 0; const bool this_is_first_field = last_field_info.bit_offset == 0 && last_field_info.bit_size == 0; + const bool first_field_is_vptr = + last_field_info.bit_offset == 0 && last_field_info.IsArtificial(); - if (have_base && this_is_first_field) + if (have_base && (this_is_first_field || first_field_is_vptr)) return false; return true; diff --git a/lldb/test/API/lang/cpp/bitfields/TestCppBitfields.py b/lldb/test/API/lang/cpp/bitfields/TestCppBitfields.py --- a/lldb/test/API/lang/cpp/bitfields/TestCppBitfields.py +++ b/lldb/test/API/lang/cpp/bitfields/TestCppBitfields.py @@ -168,3 +168,14 @@ result_children=with_vtable_and_unnamed_children) self.expect_var_path("with_vtable_and_unnamed", children=with_vtable_and_unnamed_children) + + derived_with_vtable_children = [ + ValueCheck(name="Base", children=[ + ValueCheck(name="b_a", value="2", type="uint32_t") + ]), + ValueCheck(name="a", value="1", type="unsigned int:1") + ] + self.expect_expr("derived_with_vtable", + result_children=derived_with_vtable_children) + self.expect_var_path("derived_with_vtable", + children=derived_with_vtable_children) diff --git a/lldb/test/API/lang/cpp/bitfields/main.cpp b/lldb/test/API/lang/cpp/bitfields/main.cpp --- a/lldb/test/API/lang/cpp/bitfields/main.cpp +++ b/lldb/test/API/lang/cpp/bitfields/main.cpp @@ -113,6 +113,12 @@ }; HasBaseWithVTable base_with_vtable; +struct DerivedWithVTable : public Base { + virtual ~DerivedWithVTable() {} + unsigned a : 1; +}; +DerivedWithVTable derived_with_vtable; + int main(int argc, char const *argv[]) { lba.a = 2; @@ -153,5 +159,8 @@ base_with_vtable.b = 0; base_with_vtable.c = 5; + derived_with_vtable.b_a = 2; + derived_with_vtable.a = 1; + return 0; // break here }