diff options
author | Oliver Hunt <oliver@apple.com> | 2025-04-20 14:16:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-20 14:16:51 -0700 |
commit | 3ac1aa4c88d4fe40166209cad616f4ae867c20a2 (patch) | |
tree | 3475d8e06c196ac877a3a2ddf3b8598279a8b0cb /clang/lib/Sema/SemaChecking.cpp | |
parent | 842e5915778a820c63cf38b75bec932a6ea8c18b (diff) | |
download | llvm-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.cpp | 36 |
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; } } |