https://github.com/tinnamchoi updated 
https://github.com/llvm/llvm-project/pull/152698

>From 214a9541d4becd3dfae00cc33be5d35228455089 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Fri, 8 Aug 2025 14:39:50 +0800
Subject: [PATCH 1/9] [Clang] Add diagnostic when scoped enumeration requires
 an explicit conversion for binary operations

Fixes #24265
---
 .../clang/Basic/DiagnosticSemaKinds.td        |   5 +
 clang/include/clang/Sema/Sema.h               |   2 +-
 clang/lib/Sema/SemaExpr.cpp                   | 112 ++++++++++++++----
 3 files changed, 97 insertions(+), 22 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9ce142e7b37cc..e69ab1b9893d9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4401,6 +4401,11 @@ def warn_impcast_different_enum_types : Warning<
 def warn_impcast_int_to_enum : Warning<
   "implicit conversion from %0 to enumeration type %1 is invalid in C++">,
   InGroup<ImplicitIntToEnumCast>, DefaultIgnore;
+
+def note_no_implicit_conversion_for_scoped_enum
+    : Note<"no implicit conversion for scoped enum; consider casting to "
+           "underlying type">;
+
 def warn_impcast_bool_to_null_pointer : Warning<
     "initialization of pointer of type %0 to null from a constant boolean "
     "expression">, InGroup<BoolConversion>;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5211373367677..3fc8f14eded85 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8065,7 +8065,7 @@ class Sema final : public SemaBase {
       BinaryOperatorKind Opc, QualType *CompLHSTy = nullptr);
   QualType CheckSubtractionOperands( // C99 6.5.6
       ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-      QualType *CompLHSTy = nullptr);
+      BinaryOperatorKind Opc, QualType *CompLHSTy = nullptr);
   QualType CheckShiftOperands( // C99 6.5.7
       ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
       BinaryOperatorKind Opc, bool IsCompAssign = false);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6793d6da85cb1..87a6f448ba581 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10742,6 +10742,45 @@ static void DiagnoseBadDivideOrRemainderValues(Sema& 
S, ExprResult &LHS,
                             << IsDiv << RHS.get()->getSourceRange());
 }
 
+static void diagnoseScopedEnums(Sema &S, const SourceLocation Loc,
+                                const ExprResult &LHS, const ExprResult &RHS,
+                                BinaryOperatorKind Opc) {
+  const Expr *LHSExpr = LHS.get();
+  const Expr *RHSExpr = RHS.get();
+  if (!LHSExpr || !RHSExpr)
+    return;
+  const QualType LHSType = LHSExpr->getType();
+  const QualType RHSType = RHSExpr->getType();
+  const bool LHSIsScoped = LHSType->isScopedEnumeralType();
+  const bool RHSIsScoped = RHSType->isScopedEnumeralType();
+  if (!LHSIsScoped && !RHSIsScoped)
+    return;
+  if (!LHSIsScoped && !LHSType->isIntegralOrUnscopedEnumerationType())
+    return;
+  if (!RHSIsScoped && !RHSType->isIntegralOrUnscopedEnumerationType())
+    return;
+  if (BinaryOperator::isAssignmentOp(Opc) && LHSIsScoped)
+    return;
+  if (LHSIsScoped) {
+    SourceLocation LHSBegin = LHSExpr->getBeginLoc();
+    QualType LHSIntType =
+        LHSType->castAs<EnumType>()->getDecl()->getIntegerType();
+    S.Diag(LHSBegin, diag::note_no_implicit_conversion_for_scoped_enum)
+        << FixItHint::CreateInsertion(
+               LHSBegin, "static_cast<" + LHSIntType.getAsString() + ">(")
+        << FixItHint::CreateInsertion(LHSExpr->getEndLoc(), ")");
+  }
+  if (RHSIsScoped) {
+    SourceLocation RHSBegin = RHSExpr->getBeginLoc();
+    QualType RHSIntType =
+        RHSType->castAs<EnumType>()->getDecl()->getIntegerType();
+    S.Diag(RHSBegin, diag::note_no_implicit_conversion_for_scoped_enum)
+        << FixItHint::CreateInsertion(
+               RHSBegin, "static_cast<" + RHSIntType.getAsString() + ">(")
+        << FixItHint::CreateInsertion(RHSExpr->getEndLoc(), ")");
+  }
+}
+
 QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
                                            SourceLocation Loc,
                                            bool IsCompAssign, bool IsDiv) {
@@ -10772,9 +10811,14 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult 
&LHS, ExprResult &RHS,
   if (LHS.isInvalid() || RHS.isInvalid())
     return QualType();
 
-
-  if (compType.isNull() || !compType->isArithmeticType())
-    return InvalidOperands(Loc, LHS, RHS);
+  if (compType.isNull() || !compType->isArithmeticType()) {
+    InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(*this, Loc, LHS, RHS,
+                        IsCompAssign ? IsDiv ? BO_DivAssign : BO_MulAssign
+                        : IsDiv      ? BO_Div
+                                     : BO_Mul);
+    return QualType();
+  }
   if (IsDiv) {
     DetectPrecisionLossInComplexDivision(*this, RHS.get()->getType(), Loc);
     DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
@@ -10837,8 +10881,12 @@ QualType Sema::CheckRemainderOperands(
 
   if (compType.isNull() ||
       (!compType->isIntegerType() &&
-       !(getLangOpts().HLSL && compType->isFloatingType())))
-    return InvalidOperands(Loc, LHS, RHS);
+       !(getLangOpts().HLSL && compType->isFloatingType()))) {
+    InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(*this, Loc, LHS, RHS,
+                        IsCompAssign ? BO_RemAssign : BO_Rem);
+    return QualType();
+  }
   DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
   return compType;
 }
@@ -11194,7 +11242,9 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, 
ExprResult &RHS,
     } else if (PExp->getType()->isObjCObjectPointerType()) {
       isObjCPointer = true;
     } else {
-      return InvalidOperands(Loc, LHS, RHS);
+      InvalidOperands(Loc, LHS, RHS);
+      diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
+      return QualType();
     }
   }
   assert(PExp->getType()->isAnyPointerType());
@@ -11251,7 +11301,8 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, 
ExprResult &RHS,
 // C99 6.5.6
 QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
                                         SourceLocation Loc,
-                                        QualType* CompLHSTy) {
+                                        BinaryOperatorKind Opc,
+                                        QualType *CompLHSTy) {
   checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
 
   if (LHS.get()->getType()->isVectorType() ||
@@ -11396,7 +11447,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult 
&LHS, ExprResult &RHS,
     }
   }
 
-  return InvalidOperands(Loc, LHS, RHS);
+  InvalidOperands(Loc, LHS, RHS);
+  diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
+  return QualType();
 }
 
 static bool isScopedEnumerationType(QualType T) {
@@ -11744,8 +11797,11 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, 
ExprResult &RHS,
   // Embedded-C 4.1.6.2.2: The LHS may also be fixed-point.
   if ((!LHSType->isFixedPointOrIntegerType() &&
        !LHSType->hasIntegerRepresentation()) ||
-      !RHSType->hasIntegerRepresentation())
-    return InvalidOperands(Loc, LHS, RHS);
+      !RHSType->hasIntegerRepresentation()) {
+    InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
+    return QualType();
+  }
 
   // C++0x: Don't allow scoped enums. FIXME: Use something better than
   // hasIntegerRepresentation() above instead of this.
@@ -12311,8 +12367,11 @@ static QualType 
checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
       S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
   if (LHS.isInvalid() || RHS.isInvalid())
     return QualType();
-  if (Type.isNull())
-    return S.InvalidOperands(Loc, LHS, RHS);
+  if (Type.isNull()) {
+    S.InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(S, Loc, LHS, RHS, BO_Cmp);
+    return QualType();
+  }
 
   std::optional<ComparisonCategoryType> CCT =
       getComparisonCategoryForBuiltinCmp(Type);
@@ -12344,8 +12403,11 @@ static QualType checkArithmeticOrEnumeralCompare(Sema 
&S, ExprResult &LHS,
       S.UsualArithmeticConversions(LHS, RHS, Loc, ArithConvKind::Comparison);
   if (LHS.isInvalid() || RHS.isInvalid())
     return QualType();
-  if (Type.isNull())
-    return S.InvalidOperands(Loc, LHS, RHS);
+  if (Type.isNull()) {
+    S.InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(S, Loc, LHS, RHS, Opc);
+    return QualType();
+  }
   assert(Type->isArithmeticType() || Type->isEnumeralType());
 
   if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
@@ -13355,7 +13417,9 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult 
&LHS, ExprResult &RHS,
 
   if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
     return compType;
-  return InvalidOperands(Loc, LHS, RHS);
+  InvalidOperands(Loc, LHS, RHS);
+  diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
+  return QualType();
 }
 
 // C99 6.5.[13,14]
@@ -13457,13 +13521,19 @@ inline QualType Sema::CheckLogicalOperands(ExprResult 
&LHS, ExprResult &RHS,
   // C++ [expr.log.or]p1
   // The operands are both contextually converted to type bool.
   ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get());
-  if (LHSRes.isInvalid())
-    return InvalidOperands(Loc, LHS, RHS);
+  if (LHSRes.isInvalid()) {
+    InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
+    return QualType();
+  }
   LHS = LHSRes;
 
   ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get());
-  if (RHSRes.isInvalid())
-    return InvalidOperands(Loc, LHS, RHS);
+  if (RHSRes.isInvalid()) {
+    InvalidOperands(Loc, LHS, RHS);
+    diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
+    return QualType();
+  }
   RHS = RHSRes;
 
   // C++ [expr.log.and]p2
@@ -15069,7 +15139,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation 
OpLoc,
     break;
   case BO_Sub:
     ConvertHalfVec = true;
-    ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc);
+    ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc);
     break;
   case BO_Shl:
   case BO_Shr:
@@ -15136,7 +15206,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation 
OpLoc,
     break;
   case BO_SubAssign:
     ConvertHalfVec = true;
-    CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy);
+    CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
     if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
       ResultTy =
           CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc);

>From ab9d87b3d294d6887cd686407dbe1c0df764cca4 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Fri, 8 Aug 2025 15:04:43 +0800
Subject: [PATCH 2/9] [Clang] Update existing tests to reflect new diagnostics
 for scoped enums

---
 .../over/over.match/over.match.funcs/over.match.oper/p3.cpp    | 1 +
 clang/test/SemaCXX/enum-scoped.cpp                             | 3 +++
 .../test/SemaCXX/opaque-enum-declaration-in-class-template.cpp | 2 ++
 3 files changed, 6 insertions(+)

diff --git 
a/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp 
b/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp
index d88d5beb4e99e..7a0cacc2e65be 100644
--- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp
+++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp
@@ -13,6 +13,7 @@ enum class E { e };
 
 template<typename T> int f(T t) { return ~t; } // expected-error {{invalid 
argument type}}
 template<typename T, typename U> int f(T t, U u) { return t % u; } // 
expected-error {{invalid operands to}}
+                                                                   // 
expected-note@-1 {{no implicit conversion for scoped enum}}
 
 int b1 = ~E::e; // expected-error {{invalid argument type}}
 int b2 = f(E::e); // expected-note {{in instantiation of}}
diff --git a/clang/test/SemaCXX/enum-scoped.cpp 
b/clang/test/SemaCXX/enum-scoped.cpp
index 2d7b3c9557ebd..103b3051c46c9 100644
--- a/clang/test/SemaCXX/enum-scoped.cpp
+++ b/clang/test/SemaCXX/enum-scoped.cpp
@@ -128,7 +128,10 @@ namespace rdar9366066 {
 
   void f(X x) {
     x % X::value; // expected-error{{invalid operands to binary expression 
('X' and 'rdar9366066::X')}}
+                  // expected-note@-1{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
+                  // expected-note@-2{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
     x % 8; // expected-error{{invalid operands to binary expression ('X' and 
'int')}}
+           // expected-note@-1{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
   }
 }
 
diff --git a/clang/test/SemaCXX/opaque-enum-declaration-in-class-template.cpp 
b/clang/test/SemaCXX/opaque-enum-declaration-in-class-template.cpp
index 7101a153c6ebb..4257e53ce9af0 100644
--- a/clang/test/SemaCXX/opaque-enum-declaration-in-class-template.cpp
+++ b/clang/test/SemaCXX/opaque-enum-declaration-in-class-template.cpp
@@ -94,7 +94,9 @@ struct S5 {
 };
 
 int X5 = S5<char>::E1{} + '\0'; // expected-error{{invalid operands to binary 
expression}}
+                                // expected-note@-1{{no implicit conversion 
for scoped enum; consider casting to underlying type}}
 int Y5 = S5<char>::E2{} + '\0'; // expected-error{{invalid operands to binary 
expression}}
+                                // expected-note@-1{{no implicit conversion 
for scoped enum; consider casting to underlying type}}
 
 
 template <typename T>

>From 469f5594dc0a8262095842da798232fbf6354504 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Fri, 8 Aug 2025 16:06:45 +0800
Subject: [PATCH 3/9] [Clang] Add tests for new diagnostics for scoped enums

---
 clang/test/SemaCXX/enum-scoped.cpp | 102 +++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/clang/test/SemaCXX/enum-scoped.cpp 
b/clang/test/SemaCXX/enum-scoped.cpp
index 103b3051c46c9..091afff024b4c 100644
--- a/clang/test/SemaCXX/enum-scoped.cpp
+++ b/clang/test/SemaCXX/enum-scoped.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple 
x86_64-apple-darwin %s
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 -verify -triple 
x86_64-apple-darwin %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++20 -verify -triple 
x86_64-apple-darwin %s
 
 enum class E1 {
   Val1 = 1L
@@ -328,8 +329,10 @@ namespace PR18044 {
   int E::*p; // expected-error {{does not point into a class}}
   using E::f; // expected-error {{no member named 'f'}}
 
+  #if __cplusplus < 202002L
   using E::a; // expected-warning {{using declaration naming a scoped 
enumerator is a C++20 extension}}
   E b = a;
+  #endif
 }
 
 namespace test11 {
@@ -367,3 +370,102 @@ S<_Atomic(int)> s; // expected-warning {{'_Atomic' is a 
C11 extension}}
 static_assert(__is_same(__underlying_type(S<_Atomic(long long)>::OhBoy), long 
long), ""); // expected-warning {{'_Atomic' is a C11 extension}}
                                                                                
           // expected-note@-1 {{in instantiation of template class 
'GH147736::S<_Atomic(long long)>' requested here}}
 }
+
+namespace GH24265 {
+  enum class E_int { e };
+  enum class E_long : long { e };
+
+  void f() {
+    E_int::e + E_long::e; // expected-error {{invalid operands to binary 
expression ('GH24265::E_int' and 'GH24265::E_long')}}
+                          // expected-note@-1 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
+                          // expected-note@-2 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
+    E_int::e + 0; // expected-error {{invalid operands to binary expression 
('GH24265::E_int' and 'int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+
+    0 * E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 / E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 % E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 + E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 - E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 << E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 >> E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+
+    #if __cplusplus >= 202002L
+    0 <=> E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    #endif
+
+    0 < E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 > E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 <= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 >= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 == E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 != E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 & E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 ^ E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 | E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 && E_int::e; // expected-error {{value of type 'GH24265::E_int' is not 
contextually convertible to 'bool'}}
+                   // expected-error@-1 {{invalid operands to binary 
expression ('int' and 'GH24265::E_int')}}
+                   // expected-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    0 || E_int::e; // expected-error {{value of type 'GH24265::E_int' is not 
contextually convertible to 'bool'}}
+                   // expected-error@-1 {{invalid operands to binary 
expression ('int' and 'GH24265::E_int')}}
+                   // expected-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+
+    int a;
+    a *= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a /= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a %= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a += E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a -= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a <<= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a >>= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a &= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a ^= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+    a |= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
+                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+
+    // TODO: These do not have the diagnostic yet
+    E_int b;
+    b *= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b /= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b %= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b += 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b -= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b <<= 0; // expected-error {{invalid operands to binary expression 
('E_int' and 'int')}}
+    b >>= 0; // expected-error {{invalid operands to binary expression 
('E_int' and 'int')}}
+    b &= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b ^= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+    b |= 0; // expected-error {{invalid operands to binary expression ('E_int' 
and 'int')}}
+
+    a = E_int::e; // expected-error {{assigning to 'int' from incompatible 
type 'GH24265::E_int'}}
+    b = 0; // expected-error {{assigning to 'E_int' from incompatible type 
'int'}}
+
+    E_int c = 0; // expected-error {{cannot initialize a variable of type 
'E_int' with an rvalue of type 'int'}}
+    int d = E_int::e; // expected-error {{cannot initialize a variable of type 
'int' with an rvalue of type 'GH24265::E_int'}}
+  }
+}

>From 79d4d08bfab5c481557b1f010791af9e09dd8b1d Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Sat, 9 Aug 2025 16:15:40 +0800
Subject: [PATCH 4/9] [Clang] Remove unnecessary if block in scoped enum test

Block containing `<=>` kept since it didn't exist prior to C++20
---
 clang/test/SemaCXX/enum-scoped.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang/test/SemaCXX/enum-scoped.cpp 
b/clang/test/SemaCXX/enum-scoped.cpp
index 091afff024b4c..584c93eabbb22 100644
--- a/clang/test/SemaCXX/enum-scoped.cpp
+++ b/clang/test/SemaCXX/enum-scoped.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple 
x86_64-apple-darwin %s
-// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 -verify -triple 
x86_64-apple-darwin %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 
-verify=expected,cxx11-17 -triple x86_64-apple-darwin %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 
-verify=expected,cxx11-17 -triple x86_64-apple-darwin %s
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++20 -verify -triple 
x86_64-apple-darwin %s
 
 enum class E1 {
@@ -329,10 +329,8 @@ namespace PR18044 {
   int E::*p; // expected-error {{does not point into a class}}
   using E::f; // expected-error {{no member named 'f'}}
 
-  #if __cplusplus < 202002L
-  using E::a; // expected-warning {{using declaration naming a scoped 
enumerator is a C++20 extension}}
+  using E::a; // cxx11-17-warning {{using declaration naming a scoped 
enumerator is a C++20 extension}}
   E b = a;
-  #endif
 }
 
 namespace test11 {

>From e22ad8b07080ad0f2e51ab9f40511b0cb8389c15 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Sat, 9 Aug 2025 17:26:19 +0800
Subject: [PATCH 5/9] [Clang] Add tests for `fix-it`s for scoped enums

---
 clang/test/SemaCXX/enum-scoped.cpp | 67 +++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/clang/test/SemaCXX/enum-scoped.cpp 
b/clang/test/SemaCXX/enum-scoped.cpp
index 584c93eabbb22..49b328f833b9f 100644
--- a/clang/test/SemaCXX/enum-scoped.cpp
+++ b/clang/test/SemaCXX/enum-scoped.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 
-verify=expected,cxx11-17 -triple x86_64-apple-darwin %s
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 
-verify=expected,cxx11-17 -triple x86_64-apple-darwin %s
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++20 -verify -triple 
x86_64-apple-darwin %s
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -std=c++20 
-triple x86_64-apple-darwin %s 2>&1 | FileCheck %s
 
 enum class E1 {
   Val1 = 1L
@@ -376,76 +377,140 @@ namespace GH24265 {
   void f() {
     E_int::e + E_long::e; // expected-error {{invalid operands to binary 
expression ('GH24265::E_int' and 'GH24265::E_long')}}
                           // expected-note@-1 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
-                          // expected-note@-2 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
+                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:5-[[@LINE-2]]:5}:"static_cast<int>("
+                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:")"
+                          // expected-note@-4 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
+                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-5]]:16-[[@LINE-5]]:16}:"static_cast<long>("
+                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-6]]:24-[[@LINE-6]]:24}:")"
     E_int::e + 0; // expected-error {{invalid operands to binary expression 
('GH24265::E_int' and 'int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:5-[[@LINE-2]]:5}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:")"
 
     0 * E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 / E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 % E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 + E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 - E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 << E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     0 >> E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
 
     #if __cplusplus >= 202002L
     0 <=> E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                     // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                    // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
+                    // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
     #endif
 
     0 < E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 > E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 <= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     0 >= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     0 == E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     0 != E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     0 & E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 ^ E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 | E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
     0 && E_int::e; // expected-error {{value of type 'GH24265::E_int' is not 
contextually convertible to 'bool'}}
                    // expected-error@-1 {{invalid operands to binary 
expression ('int' and 'GH24265::E_int')}}
                    // expected-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:17-[[@LINE-4]]:17}:")"
     0 || E_int::e; // expected-error {{value of type 'GH24265::E_int' is not 
contextually convertible to 'bool'}}
                    // expected-error@-1 {{invalid operands to binary 
expression ('int' and 'GH24265::E_int')}}
                    // expected-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:17-[[@LINE-4]]:17}:")"
 
     int a;
     a *= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a /= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a %= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a += E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a -= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a <<= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                     // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                    // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
+                    // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
     a >>= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                     // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                    // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
+                    // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
     a &= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a ^= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
     a |= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
 
     // TODO: These do not have the diagnostic yet
     E_int b;

>From 76baf51ceaad8793697ae30a55467f9bba87c9e3 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Sat, 9 Aug 2025 17:41:14 +0800
Subject: [PATCH 6/9] [Clang]: Refactor Sema::CheckMultiplyDivideOperands for
 clarity

---
 clang/include/clang/Sema/Sema.h |  4 ++--
 clang/lib/Sema/SemaExpr.cpp     | 17 +++++++----------
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3fc8f14eded85..dfa078651883b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8055,8 +8055,8 @@ class Sema final : public SemaBase {
                                         ExprResult &RHS);
 
   QualType CheckMultiplyDivideOperands( // C99 6.5.5
-      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign,
-      bool IsDivide);
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      BinaryOperatorKind Opc);
   QualType CheckRemainderOperands( // C99 6.5.5
       ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
       bool IsCompAssign = false);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 87a6f448ba581..3550ec9a27e98 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10782,8 +10782,10 @@ static void diagnoseScopedEnums(Sema &S, const 
SourceLocation Loc,
 }
 
 QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
-                                           SourceLocation Loc,
-                                           bool IsCompAssign, bool IsDiv) {
+                                           SourceLocation Loc, 
BinaryOperatorKind Opc) {
+  bool IsCompAssign = Opc == BO_MulAssign || Opc == BO_DivAssign;
+  bool IsDiv = Opc == BO_Div || Opc == BO_DivAssign;
+
   checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
 
   QualType LHSTy = LHS.get()->getType();
@@ -10813,10 +10815,7 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult 
&LHS, ExprResult &RHS,
 
   if (compType.isNull() || !compType->isArithmeticType()) {
     InvalidOperands(Loc, LHS, RHS);
-    diagnoseScopedEnums(*this, Loc, LHS, RHS,
-                        IsCompAssign ? IsDiv ? BO_DivAssign : BO_MulAssign
-                        : IsDiv      ? BO_Div
-                                     : BO_Mul);
+    diagnoseScopedEnums(*this, Loc, LHS, RHS, Opc);
     return QualType();
   }
   if (IsDiv) {
@@ -15127,8 +15126,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation 
OpLoc,
   case BO_Mul:
   case BO_Div:
     ConvertHalfVec = true;
-    ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false,
-                                           Opc == BO_Div);
+    ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, Opc);
     break;
   case BO_Rem:
     ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc);
@@ -15183,8 +15181,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation 
OpLoc,
   case BO_MulAssign:
   case BO_DivAssign:
     ConvertHalfVec = true;
-    CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true,
-                                               Opc == BO_DivAssign);
+    CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, Opc);
     CompLHSTy = CompResultTy;
     if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
       ResultTy =

>From 824084e8abb12ac6d48548a41be41f0db3ea3463 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Sat, 9 Aug 2025 18:59:33 +0800
Subject: [PATCH 7/9] [Clang] Suggest using `std::to_underlying` for invalid
 scoped enum operations in C++23

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 ++
 clang/lib/Sema/SemaExpr.cpp                   | 31 ++++++++++---------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e69ab1b9893d9..d212924147871 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4405,6 +4405,9 @@ def warn_impcast_int_to_enum : Warning<
 def note_no_implicit_conversion_for_scoped_enum
     : Note<"no implicit conversion for scoped enum; consider casting to "
            "underlying type">;
+def note_no_implicit_conversion_for_scoped_enum_cxx23
+    : Note<"no implicit conversion for scoped enum; consider using "
+           "std::to_underlying">;
 
 def warn_impcast_bool_to_null_pointer : Warning<
     "initialization of pointer of type %0 to null from a constant boolean "
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3550ec9a27e98..f056437d1124f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10761,23 +10761,26 @@ static void diagnoseScopedEnums(Sema &S, const 
SourceLocation Loc,
     return;
   if (BinaryOperator::isAssignmentOp(Opc) && LHSIsScoped)
     return;
+  bool isCxx23 = S.getLangOpts().CPlusPlus23;
+  unsigned diagID =
+      isCxx23 ? diag::note_no_implicit_conversion_for_scoped_enum_cxx23
+              : diag::note_no_implicit_conversion_for_scoped_enum;
+  auto diagnosticHelper = [&S, isCxx23, diagID](const Expr *expr, const 
QualType type) {
+    SourceLocation beginLoc = expr->getBeginLoc();
+    QualType intType =
+        type->castAs<EnumType>()->getDecl()->getIntegerType();
+    std::string insertionString =
+        isCxx23 ? "std::to_underlying("
+                : "static_cast<" + intType.getAsString() + ">(";
+    S.Diag(beginLoc, diagID)
+        << FixItHint::CreateInsertion(beginLoc, insertionString)
+        << FixItHint::CreateInsertion(expr->getEndLoc(), ")");
+  };
   if (LHSIsScoped) {
-    SourceLocation LHSBegin = LHSExpr->getBeginLoc();
-    QualType LHSIntType =
-        LHSType->castAs<EnumType>()->getDecl()->getIntegerType();
-    S.Diag(LHSBegin, diag::note_no_implicit_conversion_for_scoped_enum)
-        << FixItHint::CreateInsertion(
-               LHSBegin, "static_cast<" + LHSIntType.getAsString() + ">(")
-        << FixItHint::CreateInsertion(LHSExpr->getEndLoc(), ")");
+    diagnosticHelper(LHSExpr, LHSType);
   }
   if (RHSIsScoped) {
-    SourceLocation RHSBegin = RHSExpr->getBeginLoc();
-    QualType RHSIntType =
-        RHSType->castAs<EnumType>()->getDecl()->getIntegerType();
-    S.Diag(RHSBegin, diag::note_no_implicit_conversion_for_scoped_enum)
-        << FixItHint::CreateInsertion(
-               RHSBegin, "static_cast<" + RHSIntType.getAsString() + ">(")
-        << FixItHint::CreateInsertion(RHSExpr->getEndLoc(), ")");
+    diagnosticHelper(RHSExpr, RHSType);
   }
 }
 

>From 6193ea0857a783a5003f9f4936df4f4f21b429f1 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Sat, 9 Aug 2025 21:52:55 +0800
Subject: [PATCH 8/9] [Clang] Add tests for diagnostics for scoped enums in
 C++23

---
 clang/test/SemaCXX/enum-scoped.cpp | 307 +++++++++++++++++++----------
 1 file changed, 204 insertions(+), 103 deletions(-)

diff --git a/clang/test/SemaCXX/enum-scoped.cpp 
b/clang/test/SemaCXX/enum-scoped.cpp
index 49b328f833b9f..fe327ab28f9af 100644
--- a/clang/test/SemaCXX/enum-scoped.cpp
+++ b/clang/test/SemaCXX/enum-scoped.cpp
@@ -1,7 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 
-verify=expected,cxx11-17 -triple x86_64-apple-darwin %s
-// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 
-verify=expected,cxx11-17 -triple x86_64-apple-darwin %s
-// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++20 -verify -triple 
x86_64-apple-darwin %s
-// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -std=c++20 
-triple x86_64-apple-darwin %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 
-verify=expected,cxx11-17,cxx11-20 -triple x86_64-apple-darwin %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 
-verify=expected,cxx11-17,cxx11-20 -triple x86_64-apple-darwin %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++20 
-verify=expected,cxx11-20 -triple x86_64-apple-darwin %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++23 -verify=expected,cxx23 
-triple x86_64-apple-darwin %s
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -std=c++20 
-triple x86_64-apple-darwin %s 2>&1 | FileCheck %s --check-prefix=CXX20
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -std=c++23 
-triple x86_64-apple-darwin %s 2>&1 | FileCheck %s --check-prefix=CXX23
 
 enum class E1 {
   Val1 = 1L
@@ -130,10 +132,13 @@ namespace rdar9366066 {
 
   void f(X x) {
     x % X::value; // expected-error{{invalid operands to binary expression 
('X' and 'rdar9366066::X')}}
-                  // expected-note@-1{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
-                  // expected-note@-2{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
+                  // cxx11-20-note@-1{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
+                  // cxx23-note@-2{{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // cxx11-20-note@-3{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
+                  // cxx23-note@-4{{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
     x % 8; // expected-error{{invalid operands to binary expression ('X' and 
'int')}}
-           // expected-note@-1{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
+           // cxx11-20-note@-1{{no implicit conversion for scoped enum; 
consider casting to underlying type}}
+           // cxx23-note@-2{{no implicit conversion for scoped enum; consider 
using std::to_underlying}}
   }
 }
 
@@ -376,141 +381,237 @@ namespace GH24265 {
 
   void f() {
     E_int::e + E_long::e; // expected-error {{invalid operands to binary 
expression ('GH24265::E_int' and 'GH24265::E_long')}}
-                          // expected-note@-1 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
-                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:5-[[@LINE-2]]:5}:"static_cast<int>("
-                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:")"
-                          // expected-note@-4 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
-                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-5]]:16-[[@LINE-5]]:16}:"static_cast<long>("
-                          // CHECK: 
fix-it:{{.*}}:{[[@LINE-6]]:24-[[@LINE-6]]:24}:")"
+                          // cxx11-20-note@-1 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
+                          // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:5-[[@LINE-2]]:5}:"static_cast<int>("
+                          // CXX20: 
fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:")"
+                          // cxx23-note@-4 {{no implicit conversion for scoped 
enum; consider using std::to_underlying}}
+                          // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:5-[[@LINE-5]]:5}:"std::to_underlying("
+                          // CXX23: 
fix-it:{{.*}}:{[[@LINE-6]]:12-[[@LINE-6]]:12}:")"
+                          // cxx11-20-note@-7 {{no implicit conversion for 
scoped enum; consider casting to underlying type}}
+                          // CXX20: 
fix-it:{{.*}}:{[[@LINE-8]]:16-[[@LINE-8]]:16}:"static_cast<long>("
+                          // CXX20: 
fix-it:{{.*}}:{[[@LINE-9]]:24-[[@LINE-9]]:24}:")"
+                          // cxx23-note@-10 {{no implicit conversion for 
scoped enum; consider using std::to_underlying}}
+                          // CXX23: 
fix-it:{{.*}}:{[[@LINE-11]]:16-[[@LINE-11]]:16}:"std::to_underlying("
+                          // CXX23: 
fix-it:{{.*}}:{[[@LINE-12]]:24-[[@LINE-12]]:24}:")"
     E_int::e + 0; // expected-error {{invalid operands to binary expression 
('GH24265::E_int' and 'int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:5-[[@LINE-2]]:5}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:5-[[@LINE-2]]:5}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:5-[[@LINE-5]]:5}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:12-[[@LINE-6]]:12}:")"
 
     0 * E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 / E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 % E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 + E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 - E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 << E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     0 >> E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
 
     #if __cplusplus >= 202002L
     0 <=> E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                    // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
-                    // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
+                    // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                    // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
+                    // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
+                    // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                    // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:11-[[@LINE-5]]:11}:"std::to_underlying("
+                    // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:18-[[@LINE-6]]:18}:")"
     #endif
 
     0 < E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 > E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 <= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     0 >= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     0 == E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     0 != E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     0 & E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 ^ E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 | E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                  // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                  // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
-                  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                  // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:9-[[@LINE-2]]:9}:"static_cast<int>("
+                  // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:16-[[@LINE-3]]:16}:")"
+                  // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                  // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:9-[[@LINE-5]]:9}:"std::to_underlying("
+                  // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:16-[[@LINE-6]]:16}:")"
     0 && E_int::e; // expected-error {{value of type 'GH24265::E_int' is not 
contextually convertible to 'bool'}}
                    // expected-error@-1 {{invalid operands to binary 
expression ('int' and 'GH24265::E_int')}}
-                   // expected-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:17-[[@LINE-4]]:17}:")"
+                   // cxx11-20-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-4]]:17-[[@LINE-4]]:17}:")"
+                   // cxx23-note@-5 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-6]]:10-[[@LINE-6]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-7]]:17-[[@LINE-7]]:17}:")"
     0 || E_int::e; // expected-error {{value of type 'GH24265::E_int' is not 
contextually convertible to 'bool'}}
                    // expected-error@-1 {{invalid operands to binary 
expression ('int' and 'GH24265::E_int')}}
-                   // expected-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:17-[[@LINE-4]]:17}:")"
+                   // cxx11-20-note@-2 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-4]]:17-[[@LINE-4]]:17}:")"
+                   // cxx23-note@-5 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-6]]:10-[[@LINE-6]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-7]]:17-[[@LINE-7]]:17}:")"
 
     int a;
     a *= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a /= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a %= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a += E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a -= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a <<= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                    // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
-                    // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
+                    // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                    // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
+                    // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
+                    // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                    // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:11-[[@LINE-5]]:11}:"std::to_underlying("
+                    // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:18-[[@LINE-6]]:18}:")"
     a >>= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                    // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                    // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
-                    // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
+                    // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                    // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:11-[[@LINE-2]]:11}:"static_cast<int>("
+                    // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:18-[[@LINE-3]]:18}:")"
+                    // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                    // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:11-[[@LINE-5]]:11}:"std::to_underlying("
+                    // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:18-[[@LINE-6]]:18}:")"
     a &= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a ^= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
     a |= E_int::e; // expected-error {{invalid operands to binary expression 
('int' and 'GH24265::E_int')}}
-                   // expected-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
-                   // CHECK: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
-                   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx11-20-note@-1 {{no implicit conversion for scoped 
enum; consider casting to underlying type}}
+                   // CXX20: 
fix-it:{{.*}}:{[[@LINE-2]]:10-[[@LINE-2]]:10}:"static_cast<int>("
+                   // CXX20: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:")"
+                   // cxx23-note@-4 {{no implicit conversion for scoped enum; 
consider using std::to_underlying}}
+                   // CXX23: 
fix-it:{{.*}}:{[[@LINE-5]]:10-[[@LINE-5]]:10}:"std::to_underlying("
+                   // CXX23: fix-it:{{.*}}:{[[@LINE-6]]:17-[[@LINE-6]]:17}:")"
 
     // TODO: These do not have the diagnostic yet
     E_int b;

>From 45c8c060cc45cd3abfb3d4d4eda676ab6ce30890 Mon Sep 17 00:00:00 2001
From: tinnamchoi <tinnam.c...@gmail.com>
Date: Sat, 9 Aug 2025 23:18:35 +0800
Subject: [PATCH 9/9] [Clang] Update ReleaseNotes.rst

---
 clang/docs/ReleaseNotes.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9231f2cae9bfa..0ba1ad5f85c03 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -125,6 +125,7 @@ Improvements to Clang's diagnostics
   an override of a virtual method.
 - Fixed fix-it hint for fold expressions. Clang now correctly places the 
suggested right 
   parenthesis when diagnosing malformed fold expressions. (#GH151787)
+- Added fix-it hint for when scoped enumerations require explicit conversions 
for binary operations. (#GH24265)
 
 Improvements to Clang's time-trace
 ----------------------------------

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to