@@ -802,8 +802,7 @@ class ItaniumRecordLayoutBuilder {
802
802
// / \param Field The field whose offset is being queried.
803
803
// / \param ComputedOffset The offset that we've computed for this field.
804
804
uint64_t updateExternalFieldOffset (const FieldDecl *Field,
805
- uint64_t ComputedOffset,
806
- uint64_t PreviousOffset);
805
+ uint64_t ComputedOffset);
807
806
808
807
void CheckFieldPadding (uint64_t Offset, uint64_t UnpaddedOffset,
809
808
uint64_t UnpackedOffset, unsigned UnpackedAlign,
@@ -1764,8 +1763,7 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
1764
1763
// If we're using external layout, give the external layout a chance
1765
1764
// to override this information.
1766
1765
if (UseExternalLayout)
1767
- FieldOffset = updateExternalFieldOffset (
1768
- D, FieldOffset, FieldOffsets.empty () ? 0 : FieldOffsets.back ());
1766
+ FieldOffset = updateExternalFieldOffset (D, FieldOffset);
1769
1767
1770
1768
// Okay, place the bitfield at the calculated offset.
1771
1769
FieldOffsets.push_back (FieldOffset);
@@ -2058,9 +2056,8 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
2058
2056
UnpackedFieldOffset = UnpackedFieldOffset.alignTo (UnpackedFieldAlign);
2059
2057
2060
2058
if (UseExternalLayout) {
2061
- FieldOffset = Context.toCharUnitsFromBits (updateExternalFieldOffset (
2062
- D, Context.toBits (FieldOffset),
2063
- FieldOffsets.empty () ? 0 : FieldOffsets.back ()));
2059
+ FieldOffset = Context.toCharUnitsFromBits (
2060
+ updateExternalFieldOffset (D, Context.toBits (FieldOffset)));
2064
2061
2065
2062
if (!IsUnion && EmptySubobjects) {
2066
2063
// Record the fact that we're placing a field at this offset.
@@ -2246,16 +2243,30 @@ void ItaniumRecordLayoutBuilder::UpdateAlignment(
2246
2243
}
2247
2244
}
2248
2245
2249
- uint64_t ItaniumRecordLayoutBuilder::updateExternalFieldOffset (
2250
- const FieldDecl *Field, uint64_t ComputedOffset, uint64_t PreviousOffset) {
2246
+ uint64_t
2247
+ ItaniumRecordLayoutBuilder::updateExternalFieldOffset (const FieldDecl *Field,
2248
+ uint64_t ComputedOffset) {
2251
2249
uint64_t ExternalFieldOffset = External.getExternalFieldOffset (Field);
2252
2250
2253
- // If the externally-supplied field offset is before the field offset we
2254
- // computed. Check against the previous field offset to make sure we don't
2255
- // misinterpret overlapping fields as packedness of the structure.
2251
+ // DWARF doesn't tell us whether a structure was declared as packed.
2252
+ // So we try to figure out if the supplied Field is at a packed offset
2253
+ // (i.e., the externally-supplied offset is less than the layout builder
2254
+ // expected).
2255
+ //
2256
+ // There are cases where fields are placed at overlapping offsets (e.g.,
2257
+ // as a result of [[no_unique_address]]). In those cases we don't want
2258
+ // to incorrectly deduce that they are placed at packed offsets. Hence,
2259
+ // ignore empty fields (which are the only fields that can overlap).
2260
+ //
2261
+ // FIXME: emit enough information in DWARF to get rid of InferAlignment.
2262
+ //
2263
+ CXXRecordDecl *CXX = nullptr ;
2264
+ if (auto *RT = dyn_cast<RecordType>(Field->getType ()))
2265
+ CXX = RT->getAsCXXRecordDecl ();
2266
+
2256
2267
const bool assume_packed = ExternalFieldOffset > 0 &&
2257
2268
ExternalFieldOffset < ComputedOffset &&
2258
- ExternalFieldOffset > PreviousOffset ;
2269
+ !(CXX && CXX-> isEmpty ()) ;
2259
2270
2260
2271
if (InferAlignment && assume_packed) {
2261
2272
Alignment = CharUnits::One ();
0 commit comments