https://github.com/flash1729 created https://github.com/llvm/llvm-project/pull/220573
In C, a conditional between two enumerators has type int, so returning `(side(), c ? A : B)` from a function returning that enum made `-Wimplicit-int-enum-cast` claim the code is invalid in C++, even though compiling it as C++ accepts it. The comma path converted the whole conditional to the context type, while `CheckConditionalOperand` already checks conditionals branch by branch. Give `CheckCommaOperand` the same behavior: recurse into a conditional right operand so each branch is checked individually. A branch that genuinely needs the conversion still warns. Fixes #185400 >From 317a5819bd05fb8293826cf195860009d343beae Mon Sep 17 00:00:00 2001 From: flash1729 <[email protected]> Date: Mon, 17 Aug 2026 06:22:56 +0530 Subject: [PATCH] [clang][Sema] Check conditional branches inside a comma operand A conditional operator appearing as the right operand of a comma operator was converted to the context type as a whole. In C the type of a conditional between two enumerators is int, so returning '(void)0, c ? E1_One : E1_Zero' from a function returning that enumeration was reported as an int to enum conversion, even though the same code is valid in C++. Recurse into the conditional so each branch is checked against the context type, matching what CheckConditionalOperand already does outside of a comma operator. A branch that genuinely needs the conversion is still diagnosed. Fixes #185400 --- clang/docs/ReleaseNotes.md | 5 +++++ clang/lib/Sema/SemaChecking.cpp | 10 ++++++++++ clang/test/Sema/implicit-int-enum-conversion.c | 12 ++++++++++++ 3 files changed, 27 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index a616bd41f3560..a1492d41b3d1a 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -438,6 +438,11 @@ features cannot lower the translation-unit ABI level; - Clang now diagnoses more details when a constraint evaluates to false. +- `-Wimplicit-int-enum-cast` no longer warns about a conditional operator used + as the right operand of a comma operator when each branch of the conditional + is already of the target enumeration type. The branches are now checked + individually, as they are outside of a comma operator. (#GH185400) + ### Improvements to Clang's time-trace ### Improvements to Coverage Mapping diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5c831e6cdebce..feb2b41f0a84a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -14039,6 +14039,16 @@ static void CheckCommaOperand( bool ExtraCheckForImplicitConversion, llvm::SmallVectorImpl<AnalyzeImplicitConversionsWorkItem> &WorkList) { E = E->IgnoreParenImpCasts(); + + // A conditional operand is fed into the context type branch by branch, the + // same way CheckConditionalOperand does, so that a conditional whose + // branches each convert cleanly is not reported through the type of the + // conditional as a whole. CheckConditionalOperator analyzes the + // subexpressions itself, so do not add this one to the work list. + if (ExtraCheckForImplicitConversion && E->getType() != T) + if (auto *CO = dyn_cast<AbstractConditionalOperator>(E)) + return CheckConditionalOperator(S, CO, CC, T); + WorkList.push_back({E, CC, false}); if (ExtraCheckForImplicitConversion && E->getType() != T) diff --git a/clang/test/Sema/implicit-int-enum-conversion.c b/clang/test/Sema/implicit-int-enum-conversion.c index 36717f36dd083..d452f326ba4ea 100644 --- a/clang/test/Sema/implicit-int-enum-conversion.c +++ b/clang/test/Sema/implicit-int-enum-conversion.c @@ -72,3 +72,15 @@ enum E1 comma4(void) { return ((void)1, 2); // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \ cxx-error {{cannot initialize return object of type 'enum E1' with an rvalue of type 'int'}} } + +// The branches of a conditional operand are each converted to the context +// type, so a conditional between enumerators of the target type is fine in +// C++ and must not be diagnosed here either. +enum E1 comma5(int c) { + return ((void)0, c ? E1_One : E1_Zero); +} + +enum E1 comma6(int c) { + return ((void)0, c ? E1_One : 2); // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \ + cxx-error {{cannot initialize return object of type 'enum E1' with an rvalue of type 'int'}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
