@@ -10742,6 +10742,45 @@ static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
10742
10742
<< IsDiv << RHS.get()->getSourceRange());
10743
10743
}
10744
10744
10745
+ static void diagnoseScopedEnums(Sema &S, const SourceLocation Loc,
10746
+ const ExprResult &LHS, const ExprResult &RHS,
10747
+ BinaryOperatorKind Opc) {
10748
+ const Expr *LHSExpr = LHS.get();
10749
+ const Expr *RHSExpr = RHS.get();
10750
+ if (!LHSExpr || !RHSExpr)
10751
+ return;
10752
+ const QualType LHSType = LHSExpr->getType();
10753
+ const QualType RHSType = RHSExpr->getType();
10754
+ const bool LHSIsScoped = LHSType->isScopedEnumeralType();
10755
+ const bool RHSIsScoped = RHSType->isScopedEnumeralType();
10756
+ if (!LHSIsScoped && !RHSIsScoped)
10757
+ return;
10758
+ if (!LHSIsScoped && !LHSType->isIntegralOrUnscopedEnumerationType())
10759
+ return;
10760
+ if (!RHSIsScoped && !RHSType->isIntegralOrUnscopedEnumerationType())
10761
+ return;
10762
+ if (BinaryOperator::isAssignmentOp(Opc) && LHSIsScoped)
10763
+ return;
10764
+ if (LHSIsScoped) {
10765
+ SourceLocation LHSBegin = LHSExpr->getBeginLoc();
10766
+ QualType LHSIntType =
10767
+ LHSType->castAs<EnumType>()->getDecl()->getIntegerType();
10768
+ S.Diag(LHSBegin, diag::note_no_implicit_conversion_for_scoped_enum)
10769
+ << FixItHint::CreateInsertion(
10770
+ LHSBegin, "static_cast<" + LHSIntType.getAsString() + ">(")
10771
+ << FixItHint::CreateInsertion(LHSExpr->getEndLoc(), ")");
10772
+ }
10773
+ if (RHSIsScoped) {
10774
+ SourceLocation RHSBegin = RHSExpr->getBeginLoc();
10775
+ QualType RHSIntType =
10776
+ RHSType->castAs<EnumType>()->getDecl()->getIntegerType();
10777
+ S.Diag(RHSBegin, diag::note_no_implicit_conversion_for_scoped_enum)
10778
+ << FixItHint::CreateInsertion(
10779
+ RHSBegin, "static_cast<" + RHSIntType.getAsString() + ">(")
10780
+ << FixItHint::CreateInsertion(RHSExpr->getEndLoc(), ")");
10781
+ }
10782
+ }
10783
+
10745
10784
QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
10746
10785
SourceLocation Loc,
10747
10786
bool IsCompAssign, bool IsDiv) {
@@ -10772,9 +10811,14 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
10772
10811
if (LHS.isInvalid() || RHS.isInvalid())
10773
10812
return QualType();
10774
10813
10775
-
10776
- if (compType.isNull () || !compType->isArithmeticType ())
10777
- return InvalidOperands (Loc, LHS, RHS);
10814
+ if (compType.isNull() || !compType->isArithmeticType()) {
10815
+ InvalidOperands(Loc, LHS, RHS);
10816
+ diagnoseScopedEnums(*this, Loc, LHS, RHS,
10817
+ IsCompAssign ? IsDiv ? BO_DivAssign : BO_MulAssign
10818
+ : IsDiv ? BO_Div
10819
+ : BO_Mul);
10820
+ return QualType();
10821
+ }
10778
10822
if (IsDiv) {
10779
10823
DetectPrecisionLossInComplexDivision(*this, RHS.get()->getType(), Loc);
10780
10824
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
@@ -10837,8 +10881,12 @@ QualType Sema::CheckRemainderOperands(
10837
10881
10838
10882
if (compType.isNull() ||
10839
10883
(!compType->isIntegerType() &&
10840
- !(getLangOpts ().HLSL && compType->isFloatingType ())))
10841
- return InvalidOperands (Loc, LHS, RHS);
10884
+ !(getLangOpts().HLSL && compType->isFloatingType()))) {
10885
+ InvalidOperands(Loc, LHS, RHS);
10886
+ diagnoseScopedEnums(*this, Loc, LHS, RHS,
10887
+ IsCompAssign ? BO_RemAssign : BO_Rem);
10888
+ return QualType();
10889
+ }
10842
10890
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
10843
10891
return compType;
10844
10892
}
@@ -11194,7 +11242,9 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
11194
11242
} else if (PExp->getType()->isObjCObjectPointerType()) {
11195
11243
isObjCPointer = true;
11196
11244
} else {
11197
- return InvalidOperands (Loc, LHS, RHS);
11245
+ InvalidOperands(Loc, LHS, RHS);
11246
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11247
+ return QualType();
11198
11248
}
11199
11249
}
11200
11250
assert(PExp->getType()->isAnyPointerType());
@@ -11251,7 +11301,8 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
11251
11301
// C99 6.5.6
11252
11302
QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
11253
11303
SourceLocation Loc,
11254
- QualType* CompLHSTy) {
11304
+ BinaryOperatorKind Opc,
11305
+ QualType *CompLHSTy) {
11255
11306
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
11256
11307
11257
11308
if (LHS.get()->getType()->isVectorType() ||
@@ -11396,7 +11447,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
11396
11447
}
11397
11448
}
11398
11449
11399
- return InvalidOperands (Loc, LHS, RHS);
11450
+ InvalidOperands(Loc, LHS, RHS);
11451
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11452
+ return QualType();
11400
11453
}
11401
11454
11402
11455
static bool isScopedEnumerationType(QualType T) {
@@ -11744,8 +11797,11 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
11744
11797
// Embedded-C 4.1.6.2.2: The LHS may also be fixed-point.
11745
11798
if ((!LHSType->isFixedPointOrIntegerType() &&
11746
11799
!LHSType->hasIntegerRepresentation()) ||
11747
- !RHSType->hasIntegerRepresentation ())
11748
- return InvalidOperands (Loc, LHS, RHS);
11800
+ !RHSType->hasIntegerRepresentation()) {
11801
+ InvalidOperands(Loc, LHS, RHS);
11802
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11803
+ return QualType();
11804
+ }
11749
11805
11750
11806
// C++0x: Don't allow scoped enums. FIXME: Use something better than
11751
11807
// hasIntegerRepresentation() above instead of this.
@@ -12311,8 +12367,11 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
12311
12367
S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
12312
12368
if (LHS.isInvalid() || RHS.isInvalid())
12313
12369
return QualType();
12314
- if (Type.isNull ())
12315
- return S.InvalidOperands (Loc, LHS, RHS);
12370
+ if (Type.isNull()) {
12371
+ S.InvalidOperands(Loc, LHS, RHS);
12372
+ diagnoseScopedEnums(S, Loc, LHS, RHS, BO_Cmp);
12373
+ return QualType();
12374
+ }
12316
12375
12317
12376
std::optional<ComparisonCategoryType> CCT =
12318
12377
getComparisonCategoryForBuiltinCmp(Type);
@@ -12344,8 +12403,11 @@ static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
12344
12403
S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
12345
12404
if (LHS.isInvalid() || RHS.isInvalid())
12346
12405
return QualType();
12347
- if (Type.isNull ())
12348
- return S.InvalidOperands (Loc, LHS, RHS);
12406
+ if (Type.isNull()) {
12407
+ S.InvalidOperands(Loc, LHS, RHS);
12408
+ diagnoseScopedEnums(S, Loc, LHS, RHS, Opc);
12409
+ return QualType();
12410
+ }
12349
12411
assert(Type->isArithmeticType() || Type->isEnumeralType());
12350
12412
12351
12413
if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
@@ -13355,7 +13417,9 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
13355
13417
13356
13418
if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
13357
13419
return compType;
13358
- return InvalidOperands (Loc, LHS, RHS);
13420
+ InvalidOperands(Loc, LHS, RHS);
13421
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
13422
+ return QualType();
13359
13423
}
13360
13424
13361
13425
// C99 6.5.[13,14]
@@ -13457,13 +13521,19 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
13457
13521
// C++ [expr.log.or]p1
13458
13522
// The operands are both contextually converted to type bool.
13459
13523
ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get());
13460
- if (LHSRes.isInvalid ())
13461
- return InvalidOperands (Loc, LHS, RHS);
13524
+ if (LHSRes.isInvalid()) {
13525
+ InvalidOperands(Loc, LHS, RHS);
13526
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
13527
+ return QualType();
13528
+ }
13462
13529
LHS = LHSRes;
13463
13530
13464
13531
ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get());
13465
- if (RHSRes.isInvalid ())
13466
- return InvalidOperands (Loc, LHS, RHS);
13532
+ if (RHSRes.isInvalid()) {
13533
+ InvalidOperands(Loc, LHS, RHS);
13534
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
13535
+ return QualType();
13536
+ }
13467
13537
RHS = RHSRes;
13468
13538
13469
13539
// C++ [expr.log.and]p2
@@ -15069,7 +15139,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
15069
15139
break;
15070
15140
case BO_Sub:
15071
15141
ConvertHalfVec = true;
15072
- ResultTy = CheckSubtractionOperands (LHS, RHS, OpLoc);
15142
+ ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc );
15073
15143
break;
15074
15144
case BO_Shl:
15075
15145
case BO_Shr:
@@ -15136,7 +15206,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
15136
15206
break;
15137
15207
case BO_SubAssign:
15138
15208
ConvertHalfVec = true;
15139
- CompResultTy = CheckSubtractionOperands (LHS, RHS, OpLoc, &CompLHSTy);
15209
+ CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
15140
15210
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
15141
15211
ResultTy =
15142
15212
CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc);
0 commit comments