[clang] Implement Wpointer-bool-conversion-strict (PR #131523)
Yutong Zhu via cfe-commits
cfe-commits at lists.llvm.org
Sun Mar 16 08:27:24 PDT 2025
https://github.com/YutongZhuu created https://github.com/llvm/llvm-project/pull/131523
This PR implements the feature request from issue #9500. From the original issue:
```c
_Bool foo(void) {
_Bool x = (void *)0; // warn on this
return (void *)0; // warn on this
}
```
However, I believe that using null checks like if ``(!p) return;`` is a common practice in C/C++ code. Because of this, I made the option ignored by default.
Additionally, the issue creator appears to be requesting more than just pointer-to-bool conversion checks. Please let me know your thoughts on this.
>From f99d61ef3353e8559450e91ad8201f8fe7592a86 Mon Sep 17 00:00:00 2001
From: Yutong Zhu <y25zhu at uwaterloo.ca>
Date: Sun, 16 Mar 2025 11:15:31 -0400
Subject: [PATCH] Implement Wpointer-bool-conversion-strict
---
clang/docs/ReleaseNotes.rst | 2 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++++
clang/lib/Sema/SemaChecking.cpp | 3 +++
.../test/Sema/warn-pointer-bool-conversion-strict.c | 13 +++++++++++++
.../Sema/warn-pointer-bool-conversion-strict.cpp | 12 ++++++++++++
6 files changed, 35 insertions(+)
create mode 100644 clang/test/Sema/warn-pointer-bool-conversion-strict.c
create mode 100644 clang/test/Sema/warn-pointer-bool-conversion-strict.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7859871b0493a..5c9783d051de5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -136,6 +136,8 @@ New Compiler Flags
The feature has `existed <https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program>`_)
for a while and this is just a user facing option.
+- New Option ``-Wpointer-bool-conversion-strict`` has been added to warn about all implicit pointer-to-bool conversions (#GH9500). This option is ignored by default.
+
Deprecated Compiler Flags
-------------------------
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index fac80fb4009aa..4b2baa898a918 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -74,6 +74,7 @@ def LiteralConversion : DiagGroup<"literal-conversion">;
def StringConversion : DiagGroup<"string-conversion">;
def SignConversion : DiagGroup<"sign-conversion">;
def PointerBoolConversion : DiagGroup<"pointer-bool-conversion">;
+def PointerBoolConversionStrict : DiagGroup<"pointer-bool-conversion-strict">;
def UndefinedBoolConversion : DiagGroup<"undefined-bool-conversion">;
def BitwiseInsteadOfLogical : DiagGroup<"bitwise-instead-of-logical">;
def BoolOperation : DiagGroup<"bool-operation", [BitwiseInsteadOfLogical]>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 14b0051709625..7f81b8ece55b5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4337,6 +4337,10 @@ def warn_impcast_pointer_to_bool : Warning<
"address of %select{'%1'|function '%1'|array '%1'|lambda function pointer "
"conversion operator}0 will always evaluate to 'true'">,
InGroup<PointerBoolConversion>;
+def warn_impcast_pointer_to_bool_strict: Warning<
+ "implicit conversion of pointer to bool">,
+ InGroup<PointerBoolConversionStrict>,
+ DefaultIgnore;
def warn_cast_nonnull_to_bool : Warning<
"nonnull %select{function call|parameter}0 '%1' will evaluate to "
"'true' on first encounter">,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 9cac9cf5c4df7..fee5611873232 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11699,6 +11699,9 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC,
DiagnoseAlwaysNonNullPointer(E, Expr::NPCK_NotNull, /*IsEqual*/ false,
SourceRange(CC));
}
+ if (Source->isPointerType()) {
+ Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool_strict);
+ }
}
// If the we're converting a constant to an ObjC BOOL on a platform where BOOL
diff --git a/clang/test/Sema/warn-pointer-bool-conversion-strict.c b/clang/test/Sema/warn-pointer-bool-conversion-strict.c
new file mode 100644
index 0000000000000..5620f054d4354
--- /dev/null
+++ b/clang/test/Sema/warn-pointer-bool-conversion-strict.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -Wpointer-bool-conversion %s
+#include <stddef.h>
+_Bool f() {
+ int *p;
+ if (p) {} // expected-warning {{implicit conversion of pointer to bool}}
+ return (void *)0; // expected-warning {{implicit conversion of pointer to bool}}
+}
+
+_Bool g() {
+ int *p = (void *)0;
+ if (p == NULL) {} // no-warning
+ return (void *)0 == NULL; // no-warning
+}
diff --git a/clang/test/Sema/warn-pointer-bool-conversion-strict.cpp b/clang/test/Sema/warn-pointer-bool-conversion-strict.cpp
new file mode 100644
index 0000000000000..8e612d2459705
--- /dev/null
+++ b/clang/test/Sema/warn-pointer-bool-conversion-strict.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -Wpointer-bool-conversion %s
+bool f() {
+ int *p;
+ if (p) {} // expected-warning {{implicit conversion of pointer to bool}}
+ return (void *)0; // expected-warning {{implicit conversion of pointer to bool}}
+}
+
+bool g() {
+ int *p = nullptr;
+ if (p == nullptr) {} // no-warning
+ return (void *)0 == nullptr; // no-warning
+}
More information about the cfe-commits
mailing list