Skip to content

Commit f597d34

Browse files
authored
[clang][Sema] Move computing best enum types to a separate function (#120965)
Move the code that computes BestType and BestPromotionType for an enum to a separate function which can be called from outside of Sema.
1 parent d28a4f1 commit f597d34

File tree

3 files changed

+92
-71
lines changed

3 files changed

+92
-71
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
17261726

17271727
QualType getEnumType(const EnumDecl *Decl) const;
17281728

1729+
/// Compute BestType and BestPromotionType for an enum based on the highest
1730+
/// number of negative and positive bits of its elements.
1731+
/// Returns true if enum width is too large.
1732+
bool computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
1733+
unsigned NumPositiveBits, QualType &BestType,
1734+
QualType &BestPromotionType);
1735+
17291736
QualType
17301737
getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const;
17311738

clang/lib/AST/ASTContext.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5209,6 +5209,85 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
52095209
return QualType(newType, 0);
52105210
}
52115211

5212+
bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
5213+
unsigned NumPositiveBits,
5214+
QualType &BestType,
5215+
QualType &BestPromotionType) {
5216+
unsigned IntWidth = Target->getIntWidth();
5217+
unsigned CharWidth = Target->getCharWidth();
5218+
unsigned ShortWidth = Target->getShortWidth();
5219+
bool EnumTooLarge = false;
5220+
unsigned BestWidth;
5221+
if (NumNegativeBits) {
5222+
// If there is a negative value, figure out the smallest integer type (of
5223+
// int/long/longlong) that fits.
5224+
// If it's packed, check also if it fits a char or a short.
5225+
if (IsPacked && NumNegativeBits <= CharWidth &&
5226+
NumPositiveBits < CharWidth) {
5227+
BestType = SignedCharTy;
5228+
BestWidth = CharWidth;
5229+
} else if (IsPacked && NumNegativeBits <= ShortWidth &&
5230+
NumPositiveBits < ShortWidth) {
5231+
BestType = ShortTy;
5232+
BestWidth = ShortWidth;
5233+
} else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
5234+
BestType = IntTy;
5235+
BestWidth = IntWidth;
5236+
} else {
5237+
BestWidth = Target->getLongWidth();
5238+
5239+
if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
5240+
BestType = LongTy;
5241+
} else {
5242+
BestWidth = Target->getLongLongWidth();
5243+
5244+
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
5245+
EnumTooLarge = true;
5246+
BestType = LongLongTy;
5247+
}
5248+
}
5249+
BestPromotionType = (BestWidth <= IntWidth ? IntTy : BestType);
5250+
} else {
5251+
// If there is no negative value, figure out the smallest type that fits
5252+
// all of the enumerator values.
5253+
// If it's packed, check also if it fits a char or a short.
5254+
if (IsPacked && NumPositiveBits <= CharWidth) {
5255+
BestType = UnsignedCharTy;
5256+
BestPromotionType = IntTy;
5257+
BestWidth = CharWidth;
5258+
} else if (IsPacked && NumPositiveBits <= ShortWidth) {
5259+
BestType = UnsignedShortTy;
5260+
BestPromotionType = IntTy;
5261+
BestWidth = ShortWidth;
5262+
} else if (NumPositiveBits <= IntWidth) {
5263+
BestType = UnsignedIntTy;
5264+
BestWidth = IntWidth;
5265+
BestPromotionType = (NumPositiveBits == BestWidth || !LangOpts.CPlusPlus)
5266+
? UnsignedIntTy
5267+
: IntTy;
5268+
} else if (NumPositiveBits <= (BestWidth = Target->getLongWidth())) {
5269+
BestType = UnsignedLongTy;
5270+
BestPromotionType = (NumPositiveBits == BestWidth || !LangOpts.CPlusPlus)
5271+
? UnsignedLongTy
5272+
: LongTy;
5273+
} else {
5274+
BestWidth = Target->getLongLongWidth();
5275+
if (NumPositiveBits > BestWidth) {
5276+
// This can happen with bit-precise integer types, but those are not
5277+
// allowed as the type for an enumerator per C23 6.7.2.2p4 and p12.
5278+
// FIXME: GCC uses __int128_t and __uint128_t for cases that fit within
5279+
// a 128-bit integer, we should consider doing the same.
5280+
EnumTooLarge = true;
5281+
}
5282+
BestType = UnsignedLongLongTy;
5283+
BestPromotionType = (NumPositiveBits == BestWidth || !LangOpts.CPlusPlus)
5284+
? UnsignedLongLongTy
5285+
: LongLongTy;
5286+
}
5287+
}
5288+
return EnumTooLarge;
5289+
}
5290+
52125291
QualType ASTContext::getUnresolvedUsingType(
52135292
const UnresolvedUsingTypenameDecl *Decl) const {
52145293
if (Decl->TypeForDecl)

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -20043,10 +20043,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2004320043
return;
2004420044
}
2004520045

20046-
unsigned IntWidth = Context.getTargetInfo().getIntWidth();
20047-
unsigned CharWidth = Context.getTargetInfo().getCharWidth();
20048-
unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
20049-
2005020046
// Verify that all the values are okay, compute the size of the values, and
2005120047
// reverse the list.
2005220048
unsigned NumNegativeBits = 0;
@@ -20112,73 +20108,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2011220108
BestPromotionType = BestType;
2011320109

2011420110
BestWidth = Context.getIntWidth(BestType);
20115-
}
20116-
else if (NumNegativeBits) {
20117-
// If there is a negative value, figure out the smallest integer type (of
20118-
// int/long/longlong) that fits.
20119-
// If it's packed, check also if it fits a char or a short.
20120-
if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
20121-
BestType = Context.SignedCharTy;
20122-
BestWidth = CharWidth;
20123-
} else if (Packed && NumNegativeBits <= ShortWidth &&
20124-
NumPositiveBits < ShortWidth) {
20125-
BestType = Context.ShortTy;
20126-
BestWidth = ShortWidth;
20127-
} else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
20128-
BestType = Context.IntTy;
20129-
BestWidth = IntWidth;
20130-
} else {
20131-
BestWidth = Context.getTargetInfo().getLongWidth();
20132-
20133-
if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
20134-
BestType = Context.LongTy;
20135-
} else {
20136-
BestWidth = Context.getTargetInfo().getLongLongWidth();
20137-
20138-
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
20139-
Diag(Enum->getLocation(), diag::ext_enum_too_large);
20140-
BestType = Context.LongLongTy;
20141-
}
20142-
}
20143-
BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
2014420111
} else {
20145-
// If there is no negative value, figure out the smallest type that fits
20146-
// all of the enumerator values.
20147-
// If it's packed, check also if it fits a char or a short.
20148-
if (Packed && NumPositiveBits <= CharWidth) {
20149-
BestType = Context.UnsignedCharTy;
20150-
BestPromotionType = Context.IntTy;
20151-
BestWidth = CharWidth;
20152-
} else if (Packed && NumPositiveBits <= ShortWidth) {
20153-
BestType = Context.UnsignedShortTy;
20154-
BestPromotionType = Context.IntTy;
20155-
BestWidth = ShortWidth;
20156-
} else if (NumPositiveBits <= IntWidth) {
20157-
BestType = Context.UnsignedIntTy;
20158-
BestWidth = IntWidth;
20159-
BestPromotionType
20160-
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
20161-
? Context.UnsignedIntTy : Context.IntTy;
20162-
} else if (NumPositiveBits <=
20163-
(BestWidth = Context.getTargetInfo().getLongWidth())) {
20164-
BestType = Context.UnsignedLongTy;
20165-
BestPromotionType
20166-
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
20167-
? Context.UnsignedLongTy : Context.LongTy;
20168-
} else {
20169-
BestWidth = Context.getTargetInfo().getLongLongWidth();
20170-
if (NumPositiveBits > BestWidth) {
20171-
// This can happen with bit-precise integer types, but those are not
20172-
// allowed as the type for an enumerator per C23 6.7.2.2p4 and p12.
20173-
// FIXME: GCC uses __int128_t and __uint128_t for cases that fit within
20174-
// a 128-bit integer, we should consider doing the same.
20175-
Diag(Enum->getLocation(), diag::ext_enum_too_large);
20176-
}
20177-
BestType = Context.UnsignedLongLongTy;
20178-
BestPromotionType
20179-
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
20180-
? Context.UnsignedLongLongTy : Context.LongLongTy;
20181-
}
20112+
bool EnumTooLarge = Context.computeBestEnumTypes(
20113+
Packed, NumNegativeBits, NumPositiveBits, BestType, BestPromotionType);
20114+
BestWidth = Context.getIntWidth(BestType);
20115+
if (EnumTooLarge)
20116+
Diag(Enum->getLocation(), diag::ext_enum_too_large);
2018220117
}
2018320118

2018420119
// Loop over all of the enumerator constants, changing their types to match
@@ -20210,7 +20145,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2021020145
// int; or,
2021120146
// - the enumerated type
2021220147
NewTy = Context.IntTy;
20213-
NewWidth = IntWidth;
20148+
NewWidth = Context.getTargetInfo().getIntWidth();
2021420149
NewSign = true;
2021520150
} else if (ECD->getType() == BestType) {
2021620151
// Already the right type!

0 commit comments

Comments
 (0)