aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey <andrey.a.davydov@gmail.com>2025-08-08 06:51:36 +0200
committerGitHub <noreply@github.com>2025-08-08 07:51:36 +0300
commit2d4bac867552aa361c16db26a01d36f27507994f (patch)
tree21b025cef6b18946254724af634757e1bb7370dd
parent2422972eeaebe94f591be2325563785ab7254d4e (diff)
downloadllvm-2d4bac867552aa361c16db26a01d36f27507994f.zip
llvm-2d4bac867552aa361c16db26a01d36f27507994f.tar.gz
llvm-2d4bac867552aa361c16db26a01d36f27507994f.tar.bz2
Reland "[clang-tidy] fix bugprone-narrowing-conversions false positive for conditional expression" (#151874)
This is another attempt to merge previously [reverted](https://github.com/llvm/llvm-project/pull/139474#issuecomment-3148339124) PR #139474. The added tests `narrowing-conversions-conditional-expressions.c[pp]` failed on [different (non x86_64) platforms](https://github.com/llvm/llvm-project/pull/139474#issuecomment-3148334280) because the expected warning is implementation-defined. That's why the test must explicitly specify target (the line `// RUN: -- -target x86_64-unknown-linux`).
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp15
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h2
-rw-r--r--clang-tools-extra/docs/ReleaseNotes.rst4
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.c22
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.cpp22
5 files changed, 61 insertions, 4 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp
index 5378223..249c77c 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp
@@ -555,15 +555,22 @@ bool NarrowingConversionsCheck::handleConditionalOperator(
// We have an expression like so: `output = cond ? lhs : rhs`
// From the point of view of narrowing conversion we treat it as two
// expressions `output = lhs` and `output = rhs`.
- handleBinaryOperator(Context, CO->getLHS()->getExprLoc(), Lhs,
- *CO->getLHS());
- handleBinaryOperator(Context, CO->getRHS()->getExprLoc(), Lhs,
- *CO->getRHS());
+ handleConditionalOperatorArgument(Context, Lhs, CO->getLHS());
+ handleConditionalOperatorArgument(Context, Lhs, CO->getRHS());
return true;
}
return false;
}
+void NarrowingConversionsCheck::handleConditionalOperatorArgument(
+ const ASTContext &Context, const Expr &Lhs, const Expr *Arg) {
+ if (const auto *ICE = llvm::dyn_cast<ImplicitCastExpr>(Arg))
+ if (!Arg->getIntegerConstantExpr(Context))
+ Arg = ICE->getSubExpr();
+
+ handleBinaryOperator(Context, Arg->getExprLoc(), Lhs, *Arg);
+}
+
void NarrowingConversionsCheck::handleImplicitCast(
const ASTContext &Context, const ImplicitCastExpr &Cast) {
if (Cast.getExprLoc().isMacroID())
diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h
index 20403f9..116a8cba 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h
@@ -85,6 +85,8 @@ private:
bool handleConditionalOperator(const ASTContext &Context, const Expr &Lhs,
const Expr &Rhs);
+ void handleConditionalOperatorArgument(const ASTContext &Context,
+ const Expr &Lhs, const Expr *Arg);
void handleImplicitCast(const ASTContext &Context,
const ImplicitCastExpr &Cast);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2dc5c73..8b636018 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -134,6 +134,10 @@ Changes in existing checks
<clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for
variables introduced by structured bindings.
+- Improved :doc:`bugprone-narrowing-conversions
+ <clang-tidy/checks/bugprone/narrowing-conversions>` check by fixing
+ false positive from analysis of a conditional expression in C.
+
- Improved :doc:`bugprone-reserved-identifier
<clang-tidy/checks/bugprone/reserved-identifier>` check by ignoring
declarations in system headers.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.c
new file mode 100644
index 0000000..ce26b78
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.c
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s bugprone-narrowing-conversions %t -- \
+// RUN: -- -target x86_64-unknown-linux
+
+char test_char(int cond, char c) {
+ char ret = cond > 0 ? ':' : c;
+ return ret;
+}
+
+short test_short(int cond, short s) {
+ short ret = cond > 0 ? ':' : s;
+ return ret;
+}
+
+int test_int(int cond, int i) {
+ int ret = cond > 0 ? ':' : i;
+ return ret;
+}
+
+void test(int cond, int i) {
+ char x = cond > 0 ? ':' : i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions]
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.cpp
new file mode 100644
index 0000000..ce26b78
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/narrowing-conversions-conditional-expressions.cpp
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s bugprone-narrowing-conversions %t -- \
+// RUN: -- -target x86_64-unknown-linux
+
+char test_char(int cond, char c) {
+ char ret = cond > 0 ? ':' : c;
+ return ret;
+}
+
+short test_short(int cond, short s) {
+ short ret = cond > 0 ? ':' : s;
+ return ret;
+}
+
+int test_int(int cond, int i) {
+ int ret = cond > 0 ? ':' : i;
+ return ret;
+}
+
+void test(int cond, int i) {
+ char x = cond > 0 ? ':' : i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions]
+}