aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorOliver Hunt <oliver@apple.com>2025-04-20 14:16:51 -0700
committerGitHub <noreply@github.com>2025-04-20 14:16:51 -0700
commit3ac1aa4c88d4fe40166209cad616f4ae867c20a2 (patch)
tree3475d8e06c196ac877a3a2ddf3b8598279a8b0cb /clang/lib/Sema/SemaChecking.cpp
parent842e5915778a820c63cf38b75bec932a6ea8c18b (diff)
downloadllvm-3ac1aa4c88d4fe40166209cad616f4ae867c20a2.zip
llvm-3ac1aa4c88d4fe40166209cad616f4ae867c20a2.tar.gz
llvm-3ac1aa4c88d4fe40166209cad616f4ae867c20a2.tar.bz2
[Clang] Consider preferred_type in bitfield warnings (#116760) (#116785)
Very simply extends the bitfield sema checks for assignment to fields with a preferred type specified to consider the preferred type if the decl storage type is not explicitly an enum type. This does mean that if the preferred and explicit types have different storage requirements we may not warn in all possible cases, but that's a scenario for which the warnings are much more complex and confusing.
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp36
1 files changed, 29 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c48e009..b2b26a2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11293,9 +11293,16 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
// The RHS is not constant. If the RHS has an enum type, make sure the
// bitfield is wide enough to hold all the values of the enum without
// truncation.
- if (const auto *EnumTy = OriginalInit->getType()->getAs<EnumType>()) {
+ const auto *EnumTy = OriginalInit->getType()->getAs<EnumType>();
+ const PreferredTypeAttr *PTAttr = nullptr;
+ if (!EnumTy) {
+ PTAttr = Bitfield->getAttr<PreferredTypeAttr>();
+ if (PTAttr)
+ EnumTy = PTAttr->getType()->getAs<EnumType>();
+ }
+ if (EnumTy) {
EnumDecl *ED = EnumTy->getDecl();
- bool SignedBitfield = BitfieldType->isSignedIntegerType();
+ bool SignedBitfield = BitfieldType->isSignedIntegerOrEnumerationType();
// Enum types are implicitly signed on Windows, so check if there are any
// negative enumerators to see if the enum was intended to be signed or
@@ -11309,12 +11316,18 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
// on Windows where unfixed enums always use an underlying type of 'int'.
unsigned DiagID = 0;
if (SignedEnum && !SignedBitfield) {
- DiagID = diag::warn_unsigned_bitfield_assigned_signed_enum;
+ DiagID =
+ PTAttr == nullptr
+ ? diag::warn_unsigned_bitfield_assigned_signed_enum
+ : diag::
+ warn_preferred_type_unsigned_bitfield_assigned_signed_enum;
} else if (SignedBitfield && !SignedEnum &&
ED->getNumPositiveBits() == FieldWidth) {
- DiagID = diag::warn_signed_bitfield_enum_conversion;
+ DiagID =
+ PTAttr == nullptr
+ ? diag::warn_signed_bitfield_enum_conversion
+ : diag::warn_preferred_type_signed_bitfield_enum_conversion;
}
-
if (DiagID) {
S.Diag(InitLoc, DiagID) << Bitfield << ED;
TypeSourceInfo *TSI = Bitfield->getTypeSourceInfo();
@@ -11322,6 +11335,9 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange();
S.Diag(Bitfield->getTypeSpecStartLoc(), diag::note_change_bitfield_sign)
<< SignedEnum << TypeRange;
+ if (PTAttr)
+ S.Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
+ << ED;
}
// Compute the required bitwidth. If the enum has negative values, we need
@@ -11334,10 +11350,16 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
// Check the bitwidth.
if (BitsNeeded > FieldWidth) {
Expr *WidthExpr = Bitfield->getBitWidth();
- S.Diag(InitLoc, diag::warn_bitfield_too_small_for_enum)
- << Bitfield << ED;
+ auto DiagID =
+ PTAttr == nullptr
+ ? diag::warn_bitfield_too_small_for_enum
+ : diag::warn_preferred_type_bitfield_too_small_for_enum;
+ S.Diag(InitLoc, DiagID) << Bitfield << ED;
S.Diag(WidthExpr->getExprLoc(), diag::note_widen_bitfield)
<< BitsNeeded << ED << WidthExpr->getSourceRange();
+ if (PTAttr)
+ S.Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
+ << ED;
}
}