[clang] 75cb563 - [clang][Sema] Move computing enum bits into a separate function (#126096)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 11 09:17:56 PST 2025
Author: Ilia Kuklin
Date: 2025-02-11T22:17:52+05:00
New Revision: 75cb5633844deb4e0c6a5c7bdf84013b563818d3
URL: https://github.com/llvm/llvm-project/commit/75cb5633844deb4e0c6a5c7bdf84013b563818d3
DIFF: https://github.com/llvm/llvm-project/commit/75cb5633844deb4e0c6a5c7bdf84013b563818d3.diff
LOG: [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)
Added:
Modified:
clang/include/clang/AST/ASTContext.h
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaDecl.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 65be782c1ba43e8..a96b9c0a17045af 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1733,6 +1733,47 @@ class ASTContext : public RefCountedBase<ASTContext> {
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;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index e3b44bdbe3dc52f..b1b9d56ccca9f48 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 74e0fcec2d911bc..6eedc77ed20a09e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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;
More information about the cfe-commits
mailing list