Timm =?utf-8?q?Bäder?= <tbae...@redhat.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/141...@github.com>
================ @@ -1741,57 +1741,65 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, void Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, Expr *SrcExpr) { + + const auto *ET = DstType->getAs<EnumType>(); + if (!ET) + return; + + if (!SrcType->isIntegerType() || + Context.hasSameUnqualifiedType(SrcType, DstType)) + return; + + if (SrcExpr->isTypeDependent() || SrcExpr->isValueDependent()) + return; + + const EnumDecl *ED = ET->getDecl(); + if (!ED->isClosed()) + return; + if (Diags.isIgnored(diag::warn_not_in_enum_assignment, SrcExpr->getExprLoc())) return; - if (const EnumType *ET = DstType->getAs<EnumType>()) - if (!Context.hasSameUnqualifiedType(SrcType, DstType) && - SrcType->isIntegerType()) { - if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() && - SrcExpr->isIntegerConstantExpr(Context)) { - // Get the bitwidth of the enum value before promotions. - unsigned DstWidth = Context.getIntWidth(DstType); - bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType(); + std::optional<llvm::APSInt> RHSVal = SrcExpr->getIntegerConstantExpr(Context); + if (!RHSVal) + return; - llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); - AdjustAPSInt(RhsVal, DstWidth, DstIsSigned); - const EnumDecl *ED = ET->getDecl(); + // Get the bitwidth of the enum value before promotions. + unsigned DstWidth = Context.getIntWidth(DstType); + bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType(); + AdjustAPSInt(*RHSVal, DstWidth, DstIsSigned); - if (!ED->isClosed()) - return; + if (ED->hasAttr<FlagEnumAttr>()) { + if (!IsValueInFlagEnum(ED, *RHSVal, /*AllowMask=*/true)) + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) + << DstType.getUnqualifiedType(); + return; + } - if (ED->hasAttr<FlagEnumAttr>()) { - if (!IsValueInFlagEnum(ED, RhsVal, true)) - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) - << DstType.getUnqualifiedType(); - } else { - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> - EnumValsTy; - EnumValsTy EnumVals; - - // Gather all enum values, set their type and sort them, - // allowing easier comparison with rhs constant. - for (auto *EDI : ED->enumerators()) { - llvm::APSInt Val = EDI->getInitVal(); - AdjustAPSInt(Val, DstWidth, DstIsSigned); - EnumVals.push_back(std::make_pair(Val, EDI)); - } - if (EnumVals.empty()) - return; - llvm::stable_sort(EnumVals, CmpEnumVals); - EnumValsTy::iterator EIend = llvm::unique(EnumVals, EqEnumVals); - - // See which values aren't in the enum. - EnumValsTy::const_iterator EI = EnumVals.begin(); - while (EI != EIend && EI->first < RhsVal) - EI++; - if (EI == EIend || EI->first != RhsVal) { - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) - << DstType.getUnqualifiedType(); - } - } - } - } + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with rhs constant. + for (auto *EDI : ED->enumerators()) { ---------------- shafik wrote: It would be interesting to test the case in which we have a enum and the enumerators values are out of order to verify the sorting actually works as expected e.g. ```cpp enum E { E1 = 100, E2 = 50, E3 = 75, E4 = 9, E5 = 99 }; ``` I don't see a test that verifies that but I could be missing it. https://github.com/llvm/llvm-project/pull/141471 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits