-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations #152698
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang] Add diagnostic when scoped enumeration requires an explicit conversion for binary operations #152698
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang Author: Timothy Choi (tinnamchoi) ChangesFixes #24265 Patch is 22.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152698.diff 6 Files Affected:
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);
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..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
@@ -128,7 +129,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}}
}
}
@@ -325,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 {
@@ -364,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 operan...
[truncated]
|
Addressed the first 2 points from #24265 (comment), skipped the third one since it seems unlikely that static casting it in that scenario would give the desired outcome. Assignments currently unsupported as llvm-project/clang/lib/Sema/SemaExpr.cpp Lines 15016 to 15051 in a708b4b
Compound assignments with the scoped enum on the LHS are intentionally skipped as they require operator overloading, not static casting. Maybe this should be addressed in a separate PR. Initializations and unary operators may benefit from this diagnostic too but I reckon they are out of scope for this PR as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your patch! Please add fix-it test. And please add a release note entry to clang/docs/ReleaseNotes.rst
so that users can know the improvement.
Block containing `<=>` kept since it didn't exist prior to C++20
…erations in C++23
✅ With the latest revision this PR passed the C/C++ code formatter. |
…4265-scoped-enum-diagnostics
Ping |
@tinnamchoi Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail here. If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! |
Resolves #24265