@@ -2274,9 +2274,9 @@ static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) {
22742274 }
22752275}
22762276
2277- void ItaniumRecordLayoutBuilder:: CheckFieldPadding (
2278- uint64_t Offset, uint64_t UnpaddedOffset , uint64_t UnpackedOffset ,
2279- unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
2277+ static void CheckFieldPadding (const ASTContext &Context, bool IsUnion,
2278+ uint64_t Offset , uint64_t UnpaddedOffset ,
2279+ const FieldDecl *D) {
22802280 // We let objc ivars without warning, objc interfaces generally are not used
22812281 // for padding tricks.
22822282 if (isa<ObjCIvarDecl>(D))
@@ -2300,23 +2300,31 @@ void ItaniumRecordLayoutBuilder::CheckFieldPadding(
23002300 if (D->getIdentifier ()) {
23012301 auto Diagnostic = D->isBitField () ? diag::warn_padded_struct_bitfield
23022302 : diag::warn_padded_struct_field;
2303- Diag (D->getLocation (), Diagnostic)
2303+ Context.getDiagnostics ().Report (D->getLocation (),
2304+ Diagnostic)
23042305 << getPaddingDiagFromTagKind (D->getParent ()->getTagKind ())
23052306 << Context.getTypeDeclType (D->getParent ()) << PadSize
23062307 << (InBits ? 1 : 0 ) // (byte|bit)
23072308 << D->getIdentifier ();
23082309 } else {
23092310 auto Diagnostic = D->isBitField () ? diag::warn_padded_struct_anon_bitfield
23102311 : diag::warn_padded_struct_anon_field;
2311- Diag (D->getLocation (), Diagnostic)
2312+ Context.getDiagnostics ().Report (D->getLocation (),
2313+ Diagnostic)
23122314 << getPaddingDiagFromTagKind (D->getParent ()->getTagKind ())
23132315 << Context.getTypeDeclType (D->getParent ()) << PadSize
23142316 << (InBits ? 1 : 0 ); // (byte|bit)
23152317 }
2316- }
2317- if (isPacked && Offset != UnpackedOffset) {
2318- HasPackedField = true ;
2319- }
2318+ }
2319+ }
2320+
2321+ void ItaniumRecordLayoutBuilder::CheckFieldPadding (
2322+ uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2323+ unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
2324+ ::CheckFieldPadding (Context, IsUnion, Offset, UnpaddedOffset, D);
2325+ if (isPacked && Offset != UnpackedOffset) {
2326+ HasPackedField = true ;
2327+ }
23202328}
23212329
23222330static const CXXMethodDecl *computeKeyFunction (ASTContext &Context,
@@ -2642,8 +2650,6 @@ struct MicrosoftRecordLayoutBuilder {
26422650 // / virtual base classes and their offsets in the record.
26432651 ASTRecordLayout::VBaseOffsetsMapTy VBases;
26442652 // / The number of remaining bits in our last bitfield allocation.
2645- // / This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is
2646- // / true.
26472653 unsigned RemainingBitsInField;
26482654 bool IsUnion : 1 ;
26492655 // / True if the last field laid out was a bitfield and was not 0
@@ -3004,6 +3010,15 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
30043010 } else {
30053011 FieldOffset = Size.alignTo (Info.Alignment );
30063012 }
3013+
3014+ uint64_t UnpaddedFielddOffsetInBits =
3015+ Context.toBits (DataSize) - RemainingBitsInField;
3016+
3017+ ::CheckFieldPadding (Context, IsUnion, Context.toBits(FieldOffset),
3018+ UnpaddedFielddOffsetInBits, FD);
3019+
3020+ RemainingBitsInField = 0 ;
3021+
30073022 placeFieldAtOffset (FieldOffset);
30083023
30093024 if (!IsOverlappingEmptyField)
@@ -3049,10 +3064,14 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
30493064 } else {
30503065 // Allocate a new block of memory and place the bitfield in it.
30513066 CharUnits FieldOffset = Size.alignTo (Info.Alignment );
3067+ uint64_t UnpaddedFieldOffsetInBits =
3068+ Context.toBits (DataSize) - RemainingBitsInField;
30523069 placeFieldAtOffset (FieldOffset);
30533070 Size = FieldOffset + Info.Size ;
30543071 Alignment = std::max (Alignment, Info.Alignment );
30553072 RemainingBitsInField = Context.toBits (Info.Size ) - Width;
3073+ ::CheckFieldPadding (Context, IsUnion, Context.toBits(FieldOffset),
3074+ UnpaddedFieldOffsetInBits, FD);
30563075 }
30573076 DataSize = Size;
30583077}
@@ -3076,9 +3095,14 @@ MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {
30763095 } else {
30773096 // Round up the current record size to the field's alignment boundary.
30783097 CharUnits FieldOffset = Size.alignTo (Info.Alignment );
3098+ uint64_t UnpaddedFieldOffsetInBits =
3099+ Context.toBits (DataSize) - RemainingBitsInField;
30793100 placeFieldAtOffset (FieldOffset);
3101+ RemainingBitsInField = 0 ;
30803102 Size = FieldOffset;
30813103 Alignment = std::max (Alignment, Info.Alignment );
3104+ ::CheckFieldPadding (Context, IsUnion, Context.toBits(FieldOffset),
3105+ UnpaddedFieldOffsetInBits, FD);
30823106 }
30833107 DataSize = Size;
30843108}
@@ -3203,6 +3227,9 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
32033227}
32043228
32053229void MicrosoftRecordLayoutBuilder::finalizeLayout (const RecordDecl *RD) {
3230+ uint64_t UnpaddedSizeInBits = Context.toBits (DataSize);
3231+ UnpaddedSizeInBits -= RemainingBitsInField;
3232+
32063233 // Respect required alignment. Note that in 32-bit mode Required alignment
32073234 // may be 0 and cause size not to be updated.
32083235 DataSize = Size;
@@ -3231,6 +3258,22 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
32313258 Size = Context.toCharUnitsFromBits (External.Size );
32323259 if (External.Align )
32333260 Alignment = Context.toCharUnitsFromBits (External.Align );
3261+ return ;
3262+ }
3263+ unsigned CharBitNum = Context.getTargetInfo ().getCharWidth ();
3264+ uint64_t SizeInBits = Context.toBits (Size);
3265+ if (SizeInBits > UnpaddedSizeInBits) {
3266+ unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;
3267+ bool InBits = true ;
3268+ if (PadSize % CharBitNum == 0 ) {
3269+ PadSize = PadSize / CharBitNum;
3270+ InBits = false ;
3271+ }
3272+
3273+ Context.getDiagnostics ().Report (RD->getLocation (),
3274+ diag::warn_padded_struct_size)
3275+ << Context.getTypeDeclType (RD) << PadSize
3276+ << (InBits ? 1 : 0 ); // (byte|bit)
32343277 }
32353278}
32363279
0 commit comments