[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:
parent
c3d8c625af
commit
75cb563384
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user