Skip to content

Commit 2340a4e

Browse files
authored
[clang][Sema] Cleanup and optimize DiagnoseAssignmentEnum (#141471)
Reorder the precondition checks to move the costly onces last. Also, only evaluate the RHS once to get the integral value.
1 parent b3873e8 commit 2340a4e

File tree

1 file changed

+53
-45
lines changed

1 file changed

+53
-45
lines changed

clang/lib/Sema/SemaStmt.cpp

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,57 +1741,65 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
17411741
void
17421742
Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
17431743
Expr *SrcExpr) {
1744+
1745+
const auto *ET = DstType->getAs<EnumType>();
1746+
if (!ET)
1747+
return;
1748+
1749+
if (!SrcType->isIntegerType() ||
1750+
Context.hasSameUnqualifiedType(SrcType, DstType))
1751+
return;
1752+
1753+
if (SrcExpr->isTypeDependent() || SrcExpr->isValueDependent())
1754+
return;
1755+
1756+
const EnumDecl *ED = ET->getDecl();
1757+
if (!ED->isClosed())
1758+
return;
1759+
17441760
if (Diags.isIgnored(diag::warn_not_in_enum_assignment, SrcExpr->getExprLoc()))
17451761
return;
17461762

1747-
if (const EnumType *ET = DstType->getAs<EnumType>())
1748-
if (!Context.hasSameUnqualifiedType(SrcType, DstType) &&
1749-
SrcType->isIntegerType()) {
1750-
if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() &&
1751-
SrcExpr->isIntegerConstantExpr(Context)) {
1752-
// Get the bitwidth of the enum value before promotions.
1753-
unsigned DstWidth = Context.getIntWidth(DstType);
1754-
bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType();
1763+
std::optional<llvm::APSInt> RHSVal = SrcExpr->getIntegerConstantExpr(Context);
1764+
if (!RHSVal)
1765+
return;
17551766

1756-
llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context);
1757-
AdjustAPSInt(RhsVal, DstWidth, DstIsSigned);
1758-
const EnumDecl *ED = ET->getDecl();
1767+
// Get the bitwidth of the enum value before promotions.
1768+
unsigned DstWidth = Context.getIntWidth(DstType);
1769+
bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType();
1770+
AdjustAPSInt(*RHSVal, DstWidth, DstIsSigned);
17591771

1760-
if (!ED->isClosed())
1761-
return;
1772+
if (ED->hasAttr<FlagEnumAttr>()) {
1773+
if (!IsValueInFlagEnum(ED, *RHSVal, /*AllowMask=*/true))
1774+
Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
1775+
<< DstType.getUnqualifiedType();
1776+
return;
1777+
}
17621778

1763-
if (ED->hasAttr<FlagEnumAttr>()) {
1764-
if (!IsValueInFlagEnum(ED, RhsVal, true))
1765-
Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
1766-
<< DstType.getUnqualifiedType();
1767-
} else {
1768-
typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
1769-
EnumValsTy;
1770-
EnumValsTy EnumVals;
1771-
1772-
// Gather all enum values, set their type and sort them,
1773-
// allowing easier comparison with rhs constant.
1774-
for (auto *EDI : ED->enumerators()) {
1775-
llvm::APSInt Val = EDI->getInitVal();
1776-
AdjustAPSInt(Val, DstWidth, DstIsSigned);
1777-
EnumVals.push_back(std::make_pair(Val, EDI));
1778-
}
1779-
if (EnumVals.empty())
1780-
return;
1781-
llvm::stable_sort(EnumVals, CmpEnumVals);
1782-
EnumValsTy::iterator EIend = llvm::unique(EnumVals, EqEnumVals);
1783-
1784-
// See which values aren't in the enum.
1785-
EnumValsTy::const_iterator EI = EnumVals.begin();
1786-
while (EI != EIend && EI->first < RhsVal)
1787-
EI++;
1788-
if (EI == EIend || EI->first != RhsVal) {
1789-
Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
1790-
<< DstType.getUnqualifiedType();
1791-
}
1792-
}
1793-
}
1794-
}
1779+
typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
1780+
EnumValsTy;
1781+
EnumValsTy EnumVals;
1782+
1783+
// Gather all enum values, set their type and sort them,
1784+
// allowing easier comparison with rhs constant.
1785+
for (auto *EDI : ED->enumerators()) {
1786+
llvm::APSInt Val = EDI->getInitVal();
1787+
AdjustAPSInt(Val, DstWidth, DstIsSigned);
1788+
EnumVals.emplace_back(Val, EDI);
1789+
}
1790+
if (EnumVals.empty())
1791+
return;
1792+
llvm::stable_sort(EnumVals, CmpEnumVals);
1793+
EnumValsTy::iterator EIend = llvm::unique(EnumVals, EqEnumVals);
1794+
1795+
// See which values aren't in the enum.
1796+
EnumValsTy::const_iterator EI = EnumVals.begin();
1797+
while (EI != EIend && EI->first < *RHSVal)
1798+
EI++;
1799+
if (EI == EIend || EI->first != *RHSVal) {
1800+
Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
1801+
<< DstType.getUnqualifiedType();
1802+
}
17951803
}
17961804

17971805
StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc,

0 commit comments

Comments
 (0)