diff options
author | Oliver Hunt <oliver@apple.com> | 2025-05-13 14:00:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-13 14:00:20 -0700 |
commit | 8a05c20c963db27db0c93b422dab061a0d53a91f (patch) | |
tree | 98712f74b9ee6f8bd283d151c9dfc74f6624d2e2 /clang/lib/Sema/SemaDecl.cpp | |
parent | 22fac63bde4a4a1cdae2ab2500d66dd3a6ce5a59 (diff) | |
download | llvm-8a05c20c963db27db0c93b422dab061a0d53a91f.zip llvm-8a05c20c963db27db0c93b422dab061a0d53a91f.tar.gz llvm-8a05c20c963db27db0c93b422dab061a0d53a91f.tar.bz2 |
Add an off-by-default warning to complain about MSVC bitfield padding (#117428)
This just adds a warning for bitfields placed next to other bitfields
where the underlying type has different storage. Under the MS struct
bitfield packing ABI such bitfields are not packed.
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 152f3f3..a7d59ec2 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19399,9 +19399,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Verify that all the fields are okay. SmallVector<FieldDecl*, 32> RecFields; - + const FieldDecl *PreviousField = nullptr; for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); - i != end; ++i) { + i != end; PreviousField = cast<FieldDecl>(*i), ++i) { FieldDecl *FD = cast<FieldDecl>(*i); // Get the type for the field. @@ -19617,6 +19617,29 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (Record && FD->getType().isVolatileQualified()) Record->setHasVolatileMember(true); + bool ReportMSBitfieldStoragePacking = + Record && PreviousField && + !Diags.isIgnored(diag::warn_ms_bitfield_mismatched_storage_packing, + Record->getLocation()); + auto IsNonDependentBitField = [](const FieldDecl *FD) { + return FD->isBitField() && !FD->getType()->isDependentType(); + }; + + if (ReportMSBitfieldStoragePacking && IsNonDependentBitField(FD) && + IsNonDependentBitField(PreviousField)) { + CharUnits FDStorageSize = Context.getTypeSizeInChars(FD->getType()); + CharUnits PreviousFieldStorageSize = + Context.getTypeSizeInChars(PreviousField->getType()); + if (FDStorageSize != PreviousFieldStorageSize) { + Diag(FD->getLocation(), + diag::warn_ms_bitfield_mismatched_storage_packing) + << FD << FD->getType() << FDStorageSize.getQuantity() + << PreviousFieldStorageSize.getQuantity(); + Diag(PreviousField->getLocation(), + diag::note_ms_bitfield_mismatched_storage_size_previous) + << PreviousField << PreviousField->getType(); + } + } // Keep track of the number of named members. if (FD->getIdentifier()) ++NumNamedMembers; |