@@ -10748,9 +10748,50 @@ static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
1074810748 << IsDiv << RHS.get()->getSourceRange());
1074910749}
1075010750
10751+ static void diagnoseScopedEnums(Sema &S, const SourceLocation Loc,
10752+ const ExprResult &LHS, const ExprResult &RHS,
10753+ BinaryOperatorKind Opc) {
10754+ if (!LHS.isUsable() || !RHS.isUsable())
10755+ return;
10756+ const Expr *LHSExpr = LHS.get();
10757+ const Expr *RHSExpr = RHS.get();
10758+ const QualType LHSType = LHSExpr->getType();
10759+ const QualType RHSType = RHSExpr->getType();
10760+ const bool LHSIsScoped = LHSType->isScopedEnumeralType();
10761+ const bool RHSIsScoped = RHSType->isScopedEnumeralType();
10762+ if (!LHSIsScoped && !RHSIsScoped)
10763+ return;
10764+ if (BinaryOperator::isAssignmentOp(Opc) && LHSIsScoped)
10765+ return;
10766+ if (!LHSIsScoped && !LHSType->isIntegralOrUnscopedEnumerationType())
10767+ return;
10768+ if (!RHSIsScoped && !RHSType->isIntegralOrUnscopedEnumerationType())
10769+ return;
10770+ auto DiagnosticHelper = [&S](const Expr *expr, const QualType type) {
10771+ SourceLocation BeginLoc = expr->getBeginLoc();
10772+ QualType IntType = type->castAs<EnumType>()
10773+ ->getOriginalDecl()
10774+ ->getDefinitionOrSelf()
10775+ ->getIntegerType();
10776+ std::string InsertionString = "static_cast<" + IntType.getAsString() + ">(";
10777+ S.Diag(BeginLoc, diag::note_no_implicit_conversion_for_scoped_enum)
10778+ << FixItHint::CreateInsertion(BeginLoc, InsertionString)
10779+ << FixItHint::CreateInsertion(expr->getEndLoc(), ")");
10780+ };
10781+ if (LHSIsScoped) {
10782+ DiagnosticHelper(LHSExpr, LHSType);
10783+ }
10784+ if (RHSIsScoped) {
10785+ DiagnosticHelper(RHSExpr, RHSType);
10786+ }
10787+ }
10788+
1075110789QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
1075210790 SourceLocation Loc,
10753- bool IsCompAssign, bool IsDiv) {
10791+ BinaryOperatorKind Opc) {
10792+ bool IsCompAssign = Opc == BO_MulAssign || Opc == BO_DivAssign;
10793+ bool IsDiv = Opc == BO_Div || Opc == BO_DivAssign;
10794+
1075410795 checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
1075510796
1075610797 QualType LHSTy = LHS.get()->getType();
@@ -10778,9 +10819,11 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
1077810819 if (LHS.isInvalid() || RHS.isInvalid())
1077910820 return QualType();
1078010821
10781-
10782- if (compType.isNull() || !compType->isArithmeticType())
10783- return InvalidOperands(Loc, LHS, RHS);
10822+ if (compType.isNull() || !compType->isArithmeticType()) {
10823+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
10824+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
10825+ return ResultTy;
10826+ }
1078410827 if (IsDiv) {
1078510828 DetectPrecisionLossInComplexDivision(*this, RHS.get()->getType(), Loc);
1078610829 DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
@@ -10843,8 +10886,12 @@ QualType Sema::CheckRemainderOperands(
1084310886
1084410887 if (compType.isNull() ||
1084510888 (!compType->isIntegerType() &&
10846- !(getLangOpts().HLSL && compType->isFloatingType())))
10847- return InvalidOperands(Loc, LHS, RHS);
10889+ !(getLangOpts().HLSL && compType->isFloatingType()))) {
10890+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
10891+ diagnoseScopedEnums(*this, Loc, LHS, RHS,
10892+ IsCompAssign ? BO_RemAssign : BO_Rem);
10893+ return ResultTy;
10894+ }
1084810895 DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
1084910896 return compType;
1085010897}
@@ -11200,7 +11247,9 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
1120011247 } else if (PExp->getType()->isObjCObjectPointerType()) {
1120111248 isObjCPointer = true;
1120211249 } else {
11203- return InvalidOperands(Loc, LHS, RHS);
11250+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
11251+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11252+ return ResultTy;
1120411253 }
1120511254 }
1120611255 assert(PExp->getType()->isAnyPointerType());
@@ -11257,7 +11306,8 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
1125711306// C99 6.5.6
1125811307QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
1125911308 SourceLocation Loc,
11260- QualType* CompLHSTy) {
11309+ BinaryOperatorKind Opc,
11310+ QualType *CompLHSTy) {
1126111311 checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
1126211312
1126311313 if (LHS.get()->getType()->isVectorType() ||
@@ -11402,7 +11452,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
1140211452 }
1140311453 }
1140411454
11405- return InvalidOperands(Loc, LHS, RHS);
11455+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
11456+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11457+ return ResultTy;
1140611458}
1140711459
1140811460static bool isScopedEnumerationType(QualType T) {
@@ -11750,8 +11802,11 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
1175011802 // Embedded-C 4.1.6.2.2: The LHS may also be fixed-point.
1175111803 if ((!LHSType->isFixedPointOrIntegerType() &&
1175211804 !LHSType->hasIntegerRepresentation()) ||
11753- !RHSType->hasIntegerRepresentation())
11754- return InvalidOperands(Loc, LHS, RHS);
11805+ !RHSType->hasIntegerRepresentation()) {
11806+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
11807+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11808+ return ResultTy;
11809+ }
1175511810
1175611811 // C++0x: Don't allow scoped enums. FIXME: Use something better than
1175711812 // hasIntegerRepresentation() above instead of this.
@@ -12319,8 +12374,11 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
1231912374 S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
1232012375 if (LHS.isInvalid() || RHS.isInvalid())
1232112376 return QualType();
12322- if (Type.isNull())
12323- return S.InvalidOperands(Loc, LHS, RHS);
12377+ if (Type.isNull()) {
12378+ QualType ResultTy = S.InvalidOperands(Loc, LHS, RHS);
12379+ diagnoseScopedEnums(S, Loc, LHS, RHS, BO_Cmp);
12380+ return ResultTy;
12381+ }
1232412382
1232512383 std::optional<ComparisonCategoryType> CCT =
1232612384 getComparisonCategoryForBuiltinCmp(Type);
@@ -12352,8 +12410,11 @@ static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
1235212410 S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
1235312411 if (LHS.isInvalid() || RHS.isInvalid())
1235412412 return QualType();
12355- if (Type.isNull())
12356- return S.InvalidOperands(Loc, LHS, RHS);
12413+ if (Type.isNull()) {
12414+ QualType ResultTy = S.InvalidOperands(Loc, LHS, RHS);
12415+ diagnoseScopedEnums(S, Loc, LHS, RHS, Opc);
12416+ return ResultTy;
12417+ }
1235712418 assert(Type->isArithmeticType() || Type->isEnumeralType());
1235812419
1235912420 if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
@@ -13363,7 +13424,9 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
1336313424
1336413425 if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
1336513426 return compType;
13366- return InvalidOperands(Loc, LHS, RHS);
13427+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
13428+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
13429+ return ResultTy;
1336713430}
1336813431
1336913432// C99 6.5.[13,14]
@@ -13465,13 +13528,19 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
1346513528 // C++ [expr.log.or]p1
1346613529 // The operands are both contextually converted to type bool.
1346713530 ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get());
13468- if (LHSRes.isInvalid())
13469- return InvalidOperands(Loc, LHS, RHS);
13531+ if (LHSRes.isInvalid()) {
13532+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
13533+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
13534+ return ResultTy;
13535+ }
1347013536 LHS = LHSRes;
1347113537
1347213538 ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get());
13473- if (RHSRes.isInvalid())
13474- return InvalidOperands(Loc, LHS, RHS);
13539+ if (RHSRes.isInvalid()) {
13540+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
13541+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
13542+ return ResultTy;
13543+ }
1347513544 RHS = RHSRes;
1347613545
1347713546 // C++ [expr.log.and]p2
@@ -15067,8 +15136,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
1506715136 case BO_Mul:
1506815137 case BO_Div:
1506915138 ConvertHalfVec = true;
15070- ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false,
15071- Opc == BO_Div);
15139+ ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, Opc);
1507215140 break;
1507315141 case BO_Rem:
1507415142 ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc);
@@ -15079,7 +15147,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
1507915147 break;
1508015148 case BO_Sub:
1508115149 ConvertHalfVec = true;
15082- ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc);
15150+ ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc );
1508315151 break;
1508415152 case BO_Shl:
1508515153 case BO_Shr:
@@ -15123,8 +15191,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
1512315191 case BO_MulAssign:
1512415192 case BO_DivAssign:
1512515193 ConvertHalfVec = true;
15126- CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true,
15127- Opc == BO_DivAssign);
15194+ CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, Opc);
1512815195 CompLHSTy = CompResultTy;
1512915196 if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
1513015197 ResultTy =
@@ -15146,7 +15213,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
1514615213 break;
1514715214 case BO_SubAssign:
1514815215 ConvertHalfVec = true;
15149- CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy);
15216+ CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
1515015217 if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
1515115218 ResultTy =
1515215219 CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc);
0 commit comments