@@ -10748,9 +10748,50 @@ static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
10748
10748
<< IsDiv << RHS.get()->getSourceRange());
10749
10749
}
10750
10750
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
+
10751
10789
QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
10752
10790
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
+
10754
10795
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
10755
10796
10756
10797
QualType LHSTy = LHS.get()->getType();
@@ -10778,9 +10819,11 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
10778
10819
if (LHS.isInvalid() || RHS.isInvalid())
10779
10820
return QualType();
10780
10821
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
+ }
10784
10827
if (IsDiv) {
10785
10828
DetectPrecisionLossInComplexDivision(*this, RHS.get()->getType(), Loc);
10786
10829
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
@@ -10843,8 +10886,12 @@ QualType Sema::CheckRemainderOperands(
10843
10886
10844
10887
if (compType.isNull() ||
10845
10888
(!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
+ }
10848
10895
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
10849
10896
return compType;
10850
10897
}
@@ -11200,7 +11247,9 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
11200
11247
} else if (PExp->getType()->isObjCObjectPointerType()) {
11201
11248
isObjCPointer = true;
11202
11249
} else {
11203
- return InvalidOperands(Loc, LHS, RHS);
11250
+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
11251
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11252
+ return ResultTy;
11204
11253
}
11205
11254
}
11206
11255
assert(PExp->getType()->isAnyPointerType());
@@ -11257,7 +11306,8 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
11257
11306
// C99 6.5.6
11258
11307
QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
11259
11308
SourceLocation Loc,
11260
- QualType* CompLHSTy) {
11309
+ BinaryOperatorKind Opc,
11310
+ QualType *CompLHSTy) {
11261
11311
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
11262
11312
11263
11313
if (LHS.get()->getType()->isVectorType() ||
@@ -11402,7 +11452,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
11402
11452
}
11403
11453
}
11404
11454
11405
- return InvalidOperands(Loc, LHS, RHS);
11455
+ QualType ResultTy = InvalidOperands(Loc, LHS, RHS);
11456
+ diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
11457
+ return ResultTy;
11406
11458
}
11407
11459
11408
11460
static bool isScopedEnumerationType(QualType T) {
@@ -11750,8 +11802,11 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
11750
11802
// Embedded-C 4.1.6.2.2: The LHS may also be fixed-point.
11751
11803
if ((!LHSType->isFixedPointOrIntegerType() &&
11752
11804
!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
+ }
11755
11810
11756
11811
// C++0x: Don't allow scoped enums. FIXME: Use something better than
11757
11812
// hasIntegerRepresentation() above instead of this.
@@ -12319,8 +12374,11 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
12319
12374
S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
12320
12375
if (LHS.isInvalid() || RHS.isInvalid())
12321
12376
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
+ }
12324
12382
12325
12383
std::optional<ComparisonCategoryType> CCT =
12326
12384
getComparisonCategoryForBuiltinCmp(Type);
@@ -12352,8 +12410,11 @@ static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
12352
12410
S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
12353
12411
if (LHS.isInvalid() || RHS.isInvalid())
12354
12412
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
+ }
12357
12418
assert(Type->isArithmeticType() || Type->isEnumeralType());
12358
12419
12359
12420
if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
@@ -13363,7 +13424,9 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
13363
13424
13364
13425
if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
13365
13426
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;
13367
13430
}
13368
13431
13369
13432
// C99 6.5.[13,14]
@@ -13465,13 +13528,19 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
13465
13528
// C++ [expr.log.or]p1
13466
13529
// The operands are both contextually converted to type bool.
13467
13530
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
+ }
13470
13536
LHS = LHSRes;
13471
13537
13472
13538
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
+ }
13475
13544
RHS = RHSRes;
13476
13545
13477
13546
// C++ [expr.log.and]p2
@@ -15067,8 +15136,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
15067
15136
case BO_Mul:
15068
15137
case BO_Div:
15069
15138
ConvertHalfVec = true;
15070
- ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false,
15071
- Opc == BO_Div);
15139
+ ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, Opc);
15072
15140
break;
15073
15141
case BO_Rem:
15074
15142
ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc);
@@ -15079,7 +15147,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
15079
15147
break;
15080
15148
case BO_Sub:
15081
15149
ConvertHalfVec = true;
15082
- ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc);
15150
+ ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc );
15083
15151
break;
15084
15152
case BO_Shl:
15085
15153
case BO_Shr:
@@ -15123,8 +15191,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
15123
15191
case BO_MulAssign:
15124
15192
case BO_DivAssign:
15125
15193
ConvertHalfVec = true;
15126
- CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true,
15127
- Opc == BO_DivAssign);
15194
+ CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, Opc);
15128
15195
CompLHSTy = CompResultTy;
15129
15196
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
15130
15197
ResultTy =
@@ -15146,7 +15213,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
15146
15213
break;
15147
15214
case BO_SubAssign:
15148
15215
ConvertHalfVec = true;
15149
- CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy);
15216
+ CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
15150
15217
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
15151
15218
ResultTy =
15152
15219
CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc);
0 commit comments