[clang][Sema] Move computing enum bits into a separate function (#126096)

Move the code that computes `NumNegativeBits` and `NumPositiveBits` for
an enum to a separate function in `ASTContext.h`.
This function needs to be called from LLDB as well (#115005)
This commit is contained in:
Ilia Kuklin 2025-02-11 22:17:52 +05:00 committed by GitHub
parent c3d8c625af
commit 75cb563384
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 49 deletions

View File

@ -1733,6 +1733,47 @@ public:
unsigned NumPositiveBits, QualType &BestType,
QualType &BestPromotionType);
/// Determine whether the given integral value is representable within
/// the given type T.
bool isRepresentableIntegerValue(llvm::APSInt &Value, QualType T);
/// Compute NumNegativeBits and NumPositiveBits for an enum based on
/// the constant values of its enumerators.
template <typename RangeT>
bool computeEnumBits(RangeT EnumConstants, unsigned &NumNegativeBits,
unsigned &NumPositiveBits) {
NumNegativeBits = 0;
NumPositiveBits = 0;
bool MembersRepresentableByInt = true;
for (auto *Elem : EnumConstants) {
EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elem);
if (!ECD)
continue; // Already issued a diagnostic.
llvm::APSInt InitVal = ECD->getInitVal();
if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
// If the enumerator is zero that should still be counted as a positive
// bit since we need a bit to store the value zero.
unsigned ActiveBits = InitVal.getActiveBits();
NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
} else {
NumNegativeBits =
std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
}
MembersRepresentableByInt &= isRepresentableIntegerValue(InitVal, IntTy);
}
// If we have an empty set of enumerators we still need one bit.
// From [dcl.enum]p8
// If the enumerator-list is empty, the values of the enumeration are as if
// the enumeration had a single enumerator with value 0
if (!NumPositiveBits && !NumNegativeBits)
NumPositiveBits = 1;
return MembersRepresentableByInt;
}
QualType
getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const;

View File

@ -5320,6 +5320,19 @@ bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
return EnumTooLarge;
}
bool ASTContext::isRepresentableIntegerValue(llvm::APSInt &Value, QualType T) {
assert((T->isIntegralType(*this) || T->isEnumeralType()) &&
"Integral type required!");
unsigned BitWidth = getIntWidth(T);
if (Value.isUnsigned() || Value.isNonNegative()) {
if (T->isSignedIntegerOrEnumerationType())
--BitWidth;
return Value.getActiveBits() <= BitWidth;
}
return Value.getSignificantBits() <= BitWidth;
}
QualType ASTContext::getUnresolvedUsingType(
const UnresolvedUsingTypenameDecl *Decl) const {
if (Decl->TypeForDecl)

View File

@ -19633,23 +19633,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
ProcessAPINotes(Record);
}
/// Determine whether the given integral value is representable within
/// the given type T.
static bool isRepresentableIntegerValue(ASTContext &Context,
llvm::APSInt &Value,
QualType T) {
assert((T->isIntegralType(Context) || T->isEnumeralType()) &&
"Integral type required!");
unsigned BitWidth = Context.getIntWidth(T);
if (Value.isUnsigned() || Value.isNonNegative()) {
if (T->isSignedIntegerOrEnumerationType())
--BitWidth;
return Value.getActiveBits() <= BitWidth;
}
return Value.getSignificantBits() <= BitWidth;
}
// Given an integral type, return the next larger integral type
// (or a NULL type of no such type exists).
static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
@ -19723,7 +19706,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// representable in the underlying type of the enumeration. In C++11,
// we perform a non-narrowing conversion as part of converted constant
// expression checking.
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
if (!Context.isRepresentableIntegerValue(EnumVal, EltTy)) {
if (Context.getTargetInfo()
.getTriple()
.isWindowsMSVCEnvironment()) {
@ -19752,7 +19735,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// representable as an int.
// Complain if the value is not representable in an int.
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) {
if (!Context.isRepresentableIntegerValue(EnumVal, Context.IntTy)) {
Diag(IdLoc, getLangOpts().C23
? diag::warn_c17_compat_enum_value_not_int
: diag::ext_c23_enum_value_not_int)
@ -19844,7 +19827,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
: diag::ext_c23_enum_value_not_int)
<< 1 << toString(EnumVal, 10) << 1;
} else if (!getLangOpts().CPlusPlus && !EltTy->isDependentType() &&
!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
!Context.isRepresentableIntegerValue(EnumVal, EltTy)) {
// Enforce C99 6.7.2.2p2 even when we compute the next value.
Diag(IdLoc, getLangOpts().C23 ? diag::warn_c17_compat_enum_value_not_int
: diag::ext_c23_enum_value_not_int)
@ -20171,35 +20154,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
// reverse the list.
unsigned NumNegativeBits = 0;
unsigned NumPositiveBits = 0;
bool MembersRepresentableByInt = true;
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
EnumConstantDecl *ECD =
cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue; // Already issued a diagnostic.
llvm::APSInt InitVal = ECD->getInitVal();
// Keep track of the size of positive and negative values.
if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
// If the enumerator is zero that should still be counted as a positive
// bit since we need a bit to store the value zero.
unsigned ActiveBits = InitVal.getActiveBits();
NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
} else {
NumNegativeBits =
std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
}
MembersRepresentableByInt &=
isRepresentableIntegerValue(Context, InitVal, Context.IntTy);
}
// If we have an empty set of enumerators we still need one bit.
// From [dcl.enum]p8
// If the enumerator-list is empty, the values of the enumeration are as if
// the enumeration had a single enumerator with value 0
if (!NumPositiveBits && !NumNegativeBits)
NumPositiveBits = 1;
bool MembersRepresentableByInt =
Context.computeEnumBits(Elements, NumNegativeBits, NumPositiveBits);
// Figure out the type that should be used for this enum.
QualType BestType;