Skip to content

Commit 2750202

Browse files
author
git apple-llvm automerger
committed
Merge commit '4fbd4147bdef' from swift/release/5.9 into stable/20221013
2 parents 39d73ef + 4fbd414 commit 2750202

File tree

4 files changed

+80
-19
lines changed

4 files changed

+80
-19
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,10 +2839,9 @@ void DWARFASTParserClang::ParseSingleMember(
28392839
die.GetCU()->Supports_unnamed_objc_bitfields();
28402840

28412841
if (detect_unnamed_bitfields) {
2842-
llvm::Optional<FieldInfo> unnamed_field_info;
2843-
uint64_t last_field_end = 0;
2844-
2845-
last_field_end = last_field_info.bit_offset + last_field_info.bit_size;
2842+
std::optional<FieldInfo> unnamed_field_info;
2843+
uint64_t last_field_end =
2844+
last_field_info.bit_offset + last_field_info.bit_size;
28462845

28472846
if (!last_field_info.IsBitfield()) {
28482847
// The last field was not a bit-field...
@@ -2853,20 +2852,8 @@ void DWARFASTParserClang::ParseSingleMember(
28532852
last_field_end += word_width - (last_field_end % word_width);
28542853
}
28552854

2856-
// If we have a gap between the last_field_end and the current
2857-
// field we have an unnamed bit-field.
2858-
// If we have a base class, we assume there is no unnamed
2859-
// bit-field if this is the first field since the gap can be
2860-
// attributed to the members from the base class. This assumption
2861-
// is not correct if the first field of the derived class is
2862-
// indeed an unnamed bit-field. We currently do not have the
2863-
// machinary to track the offset of the last field of classes we
2864-
// have seen before, so we are not handling this case.
2865-
if (this_field_info.bit_offset != last_field_end &&
2866-
this_field_info.bit_offset > last_field_end &&
2867-
!(last_field_info.bit_offset == 0 &&
2868-
last_field_info.bit_size == 0 &&
2869-
layout_info.base_offsets.size() != 0)) {
2855+
if (ShouldCreateUnnamedBitfield(last_field_info, last_field_end,
2856+
this_field_info, layout_info)) {
28702857
unnamed_field_info = FieldInfo{};
28712858
unnamed_field_info->bit_size =
28722859
this_field_info.bit_offset - last_field_end;
@@ -2907,8 +2894,10 @@ void DWARFASTParserClang::ParseSingleMember(
29072894
// artificial member with (unnamed bitfield) padding.
29082895
// FIXME: This check should verify that this is indeed an artificial member
29092896
// we are supposed to ignore.
2910-
if (attrs.is_artificial)
2897+
if (attrs.is_artificial) {
2898+
last_field_info.SetIsArtificial(true);
29112899
return;
2900+
}
29122901

29132902
if (!member_clang_type.IsCompleteType())
29142903
member_clang_type.GetCompleteType();
@@ -3660,3 +3649,35 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
36603649

36613650
return !failures.empty();
36623651
}
3652+
3653+
bool DWARFASTParserClang::ShouldCreateUnnamedBitfield(
3654+
FieldInfo const &last_field_info, uint64_t last_field_end,
3655+
FieldInfo const &this_field_info,
3656+
lldb_private::ClangASTImporter::LayoutInfo const &layout_info) const {
3657+
// If we have a gap between the last_field_end and the current
3658+
// field we have an unnamed bit-field.
3659+
if (this_field_info.bit_offset <= last_field_end)
3660+
return false;
3661+
3662+
// If we have a base class, we assume there is no unnamed
3663+
// bit-field if either of the following is true:
3664+
// (a) this is the first field since the gap can be
3665+
// attributed to the members from the base class.
3666+
// FIXME: This assumption is not correct if the first field of
3667+
// the derived class is indeed an unnamed bit-field. We currently
3668+
// do not have the machinary to track the offset of the last field
3669+
// of classes we have seen before, so we are not handling this case.
3670+
// (b) Or, the first member of the derived class was a vtable pointer.
3671+
// In this case we don't want to create an unnamed bitfield either
3672+
// since those will be inserted by clang later.
3673+
const bool have_base = layout_info.base_offsets.size() != 0;
3674+
const bool this_is_first_field =
3675+
last_field_info.bit_offset == 0 && last_field_info.bit_size == 0;
3676+
const bool first_field_is_vptr =
3677+
last_field_info.bit_offset == 0 && last_field_info.IsArtificial();
3678+
3679+
if (have_base && (this_is_first_field || first_field_is_vptr))
3680+
return false;
3681+
3682+
return true;
3683+
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,19 +206,39 @@ class DWARFASTParserClang : public DWARFASTParser {
206206
uint64_t bit_size = 0;
207207
uint64_t bit_offset = 0;
208208
bool is_bitfield = false;
209+
bool is_artificial = false;
209210

210211
FieldInfo() = default;
211212

212213
void SetIsBitfield(bool flag) { is_bitfield = flag; }
213214
bool IsBitfield() { return is_bitfield; }
214215

216+
void SetIsArtificial(bool flag) { is_artificial = flag; }
217+
bool IsArtificial() const { return is_artificial; }
218+
215219
bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
216220
// Any subsequent bitfields must not overlap and must be at a higher
217221
// bit offset than any previous bitfield + size.
218222
return (bit_size + bit_offset) <= next_bit_offset;
219223
}
220224
};
221225

226+
/// Returns 'true' if we should create an unnamed bitfield
227+
/// and add it to the parser's current AST.
228+
///
229+
/// \param[in] last_field_info FieldInfo of the previous DW_TAG_member
230+
/// we parsed.
231+
/// \param[in] last_field_end Offset (in bits) where the last parsed field
232+
/// ended.
233+
/// \param[in] this_field_info FieldInfo of the current DW_TAG_member
234+
/// being parsed.
235+
/// \param[in] layout_info Layout information of all decls parsed by the
236+
/// current parser.
237+
bool ShouldCreateUnnamedBitfield(
238+
FieldInfo const &last_field_info, uint64_t last_field_end,
239+
FieldInfo const &this_field_info,
240+
lldb_private::ClangASTImporter::LayoutInfo const &layout_info) const;
241+
222242
/// Parses a DW_TAG_APPLE_property DIE and appends the parsed data to the
223243
/// list of delayed Objective-C properties.
224244
///

lldb/test/API/lang/cpp/bitfields/TestCppBitfields.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,14 @@ def test_bitfield_behind_vtable_ptr(self):
168168
result_children=with_vtable_and_unnamed_children)
169169
self.expect_var_path("with_vtable_and_unnamed",
170170
children=with_vtable_and_unnamed_children)
171+
172+
derived_with_vtable_children = [
173+
ValueCheck(name="Base", children=[
174+
ValueCheck(name="b_a", value="2", type="uint32_t")
175+
]),
176+
ValueCheck(name="a", value="1", type="unsigned int:1")
177+
]
178+
self.expect_expr("derived_with_vtable",
179+
result_children=derived_with_vtable_children)
180+
self.expect_var_path("derived_with_vtable",
181+
children=derived_with_vtable_children)

lldb/test/API/lang/cpp/bitfields/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ struct HasBaseWithVTable : BaseWithVTable {
113113
};
114114
HasBaseWithVTable base_with_vtable;
115115

116+
struct DerivedWithVTable : public Base {
117+
virtual ~DerivedWithVTable() {}
118+
unsigned a : 1;
119+
};
120+
DerivedWithVTable derived_with_vtable;
121+
116122
int main(int argc, char const *argv[]) {
117123
lba.a = 2;
118124

@@ -153,5 +159,8 @@ int main(int argc, char const *argv[]) {
153159
base_with_vtable.b = 0;
154160
base_with_vtable.c = 5;
155161

162+
derived_with_vtable.b_a = 2;
163+
derived_with_vtable.a = 1;
164+
156165
return 0; // break here
157166
}

0 commit comments

Comments
 (0)