[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-08 Thread Timothy Choi via cfe-commits

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

Fixes #24265 

>From 214a9541d4becd3dfae00cc33be5d35228455089 Mon Sep 17 00:00:00 2001
From: tinnamchoi 
Date: Fri, 8 Aug 2025 14:39:50 +0800
Subject: [PATCH 1/3] [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, 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;
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()->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()->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) {
 

[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-08 Thread Timothy Choi via cfe-commits

https://github.com/tinnamchoi edited 
https://github.com/llvm/llvm-project/pull/152698
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Remove redundant check for scoped enums in shift operators (PR #152865)

2025-08-09 Thread Timothy Choi via cfe-commits

tinnamchoi wrote:

The tests to be introduced in #152698 should cover this, running them locally 
seems fine.

https://github.com/llvm/llvm-project/blob/45c8c060cc45cd3abfb3d4d4eda676ab6ce30890/clang/test/SemaCXX/enum-scoped.cpp#L439-L452

https://github.com/llvm/llvm-project/blob/45c8c060cc45cd3abfb3d4d4eda676ab6ce30890/clang/test/SemaCXX/enum-scoped.cpp#L580-L593

https://github.com/llvm/llvm-project/blob/45c8c060cc45cd3abfb3d4d4eda676ab6ce30890/clang/test/SemaCXX/enum-scoped.cpp#L623-L624

https://github.com/llvm/llvm-project/pull/152865
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Remove redundant check for scoped enums in shift operators (PR #152865)

2025-08-09 Thread Timothy Choi via cfe-commits

tinnamchoi wrote:

What would the tests in C look like? Scoped enums don't exist in C.

Other than that, the tests to be introduced in #152698 should cover this, 
running locally seems fine.

https://github.com/llvm/llvm-project/blob/45c8c060cc45cd3abfb3d4d4eda676ab6ce30890/clang/test/SemaCXX/enum-scoped.cpp#L439-L452

https://github.com/llvm/llvm-project/blob/45c8c060cc45cd3abfb3d4d4eda676ab6ce30890/clang/test/SemaCXX/enum-scoped.cpp#L580-L593

https://github.com/llvm/llvm-project/blob/45c8c060cc45cd3abfb3d4d4eda676ab6ce30890/clang/test/SemaCXX/enum-scoped.cpp#L623-L624

https://github.com/llvm/llvm-project/pull/152865
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-15 Thread Timothy Choi via cfe-commits


@@ -10742,9 +10742,53 @@ 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;
+  bool isCxx23 = S.getLangOpts().CPlusPlus23;
+  unsigned diagID =

tinnamchoi wrote:

Would something like `no implicit conversion for scoped enum; consider casting 
to underlying type, or using std::to_underlying in standards >= C++23` 
regardless of language mode be good? It's more verbose than I'd like but feels 
better than suggesting something outdated.

Also, I recently found out `std::underlying_type` is a thing. I don't think 
it's useful enough to add and feels a bit cluttering, but I'd like to hear some 
feedback on it as it feels more semantically correct. 

https://github.com/llvm/llvm-project/pull/152698
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Remove redundant check for scoped enums in shift operators (PR #152865)

2025-08-10 Thread Timothy Choi via cfe-commits

tinnamchoi wrote:

I prefer keeping my PRs atomic. All of my changes in that PR are necessary 
towards the primary goal of that PR, whereas this change wouldn't be. If I 
allowed myself to make refactors whenever I'm working on a feature it would 
introduce quite a bit of noise, which seems like a bad habit to have.

https://github.com/llvm/llvm-project/pull/152865
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Remove redundant check for scoped enums in shift operators (PR #152865)

2025-08-10 Thread Timothy Choi via cfe-commits

tinnamchoi wrote:

Agreed, let's wait for that then.

https://github.com/llvm/llvm-project/pull/152865
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-08 Thread Timothy Choi via cfe-commits

https://github.com/tinnamchoi edited 
https://github.com/llvm/llvm-project/pull/152698
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-09 Thread Timothy Choi via cfe-commits

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

>From 214a9541d4becd3dfae00cc33be5d35228455089 Mon Sep 17 00:00:00 2001
From: tinnamchoi 
Date: Fri, 8 Aug 2025 14:39:50 +0800
Subject: [PATCH 1/8] [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, 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;
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()->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()->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) {
 DetectPreci

[clang] [Clang] Remove redundant check for scoped enums in shift operators (PR #152865)

2025-08-09 Thread Timothy Choi via cfe-commits

https://github.com/tinnamchoi created 
https://github.com/llvm/llvm-project/pull/152865

This check, introduced in 0bf3140424a0a13a928a4e6bf0f112e6167a5636, has not 
been necessary since 21673c4e7ec08457b53798b9879b7cc9a5909eb8

https://github.com/llvm/llvm-project/blob/0bf3140424a0a13a928a4e6bf0f112e6167a5636/clang/lib/Sema/SemaExpr.cpp#L5432-L5442

https://github.com/llvm/llvm-project/blob/21673c4e7ec08457b53798b9879b7cc9a5909eb8/clang/lib/AST/Type.cpp#L513-L529

>From fc0a4c73dc2abb74f200619d78f9b0baab1de7b7 Mon Sep 17 00:00:00 2001
From: tinnamchoi 
Date: Sat, 9 Aug 2025 12:02:43 +0800
Subject: [PATCH] [Clang] Remove redundant check for scoped enums in shift
 operators

This check, introduced in 0bf3140424a0a13a928a4e6bf0f112e6167a5636, has not 
been necessary since 21673c4e7ec08457b53798b9879b7cc9a5909eb8
---
 clang/lib/Sema/SemaExpr.cpp | 6 --
 1 file changed, 6 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6793d6da85cb1..c805ef205beba 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11747,12 +11747,6 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, 
ExprResult &RHS,
   !RHSType->hasIntegerRepresentation())
 return InvalidOperands(Loc, LHS, RHS);
 
-  // C++0x: Don't allow scoped enums. FIXME: Use something better than
-  // hasIntegerRepresentation() above instead of this.
-  if (isScopedEnumerationType(LHSType) ||
-  isScopedEnumerationType(RHSType)) {
-return InvalidOperands(Loc, LHS, RHS);
-  }
   DiagnoseBadShiftValues(*this, LHS, RHS, Loc, Opc, LHSType);
 
   // "The type of the result is that of the promoted left operand."

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


[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-09 Thread Timothy Choi via cfe-commits

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

>From 214a9541d4becd3dfae00cc33be5d35228455089 Mon Sep 17 00:00:00 2001
From: tinnamchoi 
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, 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;
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()->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()->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) {
 DetectPreci

[clang] [Clang] Remove redundant check for scoped enums in shift operators (PR #152865)

2025-08-23 Thread Timothy Choi via cfe-commits

tinnamchoi wrote:

@Sirraide The other PR got merged, this should be good upon green CI rerun 

https://github.com/llvm/llvm-project/pull/152865
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-08 Thread Timothy Choi via cfe-commits


@@ -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);

tinnamchoi wrote:

Would it be acceptable to change `CheckMultiplyDivideOperands` to take 
`BinaryOperatorKind Opc` instead of `bool IsCompAssign, bool IsDiv`? It should 
be even cleaner but I was trying to avoid changing existing function 
signatures. A lot of these `Check[Operation]Operands` functions have similar 
inconsistencies where sometimes they take a `BinaryOperatorKind`, `bool`s, or 
nothing at all. Maybe this can do with a bit of refactoring in the future.

https://github.com/llvm/llvm-project/pull/152698
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations (PR #152698)

2025-08-15 Thread Timothy Choi via cfe-commits


@@ -13,6 +13,7 @@ enum class E { e };
 
 template int f(T t) { return ~t; } // expected-error {{invalid 
argument type}}
 template int f(T t, U u) { return t % u; } // 
expected-error {{invalid operands to}}
+   // 
expected-note@-1 {{no implicit conversion for scoped enum}}

tinnamchoi wrote:

The test fails without it
```
error: 'expected-note' diagnostics seen but not expected: 
  File 
/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp
 Line 15: no implicit conversion for scoped enum; consider casting to 
underlying type
```

https://github.com/llvm/llvm-project/pull/152698
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits