[clang-tools-extra] [clang-tidy] modernize-use-nullptr matches "NULL" in templates (PR #109169)
Thomas Köppe via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 19 10:56:41 PDT 2024
https://github.com/tkoeppe updated https://github.com/llvm/llvm-project/pull/109169
>From a7ea1466bb42d701f834c984b3225120666ad4df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= <tkoeppe at google.com>
Date: Wed, 18 Sep 2024 17:04:44 +0000
Subject: [PATCH] [clang-tidy] Make modernize-use-nullptr matcher also match
"NULL", but not "0", when it appears on a substituted type of a template
specialization.
Previously, any matches on a substituted type were excluded, but this meant that a situation like the following is not diagnosed:
```c++
template <typename T>
struct X {
T val;
X() { val = NULL; } // should diagnose
};
```
When the user says `NULL`, we expect that the destination type is always meant to be a pointer type, so this should be converted to `nullptr`. By contrast, we do not propose changing a literal `0` in that case, which appears as initializers of both pointer and integer specializations in reasonable real code. (If `NULL` is used erroneously in such a situation, it should be changed to `0` or `{}`.)
---
.../clang-tidy/modernize/UseNullptrCheck.cpp | 4 +++-
clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++
.../checkers/modernize/use-nullptr.cpp | 24 +++++++++++++++++++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 6a003a347badac..b2921690863b84 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -38,7 +38,9 @@ AST_MATCHER(Type, sugaredNullptrType) {
StatementMatcher makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) {
auto ImplicitCastToNull = implicitCastExpr(
anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
- unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
+ anyOf(hasSourceExpression(gnuNullExpr()),
+ unless(hasImplicitDestinationType(
+ qualType(substTemplateTypeParmType())))),
unless(hasSourceExpression(hasType(sugaredNullptrType()))),
unless(hasImplicitDestinationType(
qualType(matchers::matchesAnyListedTypeName(NameList)))));
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index d032cef6b76164..b2bb7549f840cc 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -157,6 +157,10 @@ Changes in existing checks
a false positive when only an implicit conversion happened inside an
initializer list.
+- Improved :doc:`modernize-use-nullptr
+ <clang-tidy/checks/modernize/use-nullptr>` check to also recognize
+ ``NULL``/``__null`` (but not ``0``) when used with a templated type.
+
- Improved :doc:`modernize-use-std-print
<clang-tidy/checks/modernize/use-std-print>` check to support replacing
member function calls too.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp
index 7bc0925136aa86..f9c8f81a04126b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp
@@ -84,6 +84,30 @@ void test_macro_expansion4() {
#undef MY_NULL
}
+template <typename T> struct pear {
+ // If you say __null (or NULL), we assume that T will always be a pointer
+ // type, so we suggest replacing it with nullptr.
+ void f() { x = __null; }
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr [modernize-use-nullptr]
+ // CHECK-FIXES: x = nullptr;
+
+ // But if you say 0, we allow the possibility that T can be used with integral
+ // and pointer types, and "0" is an acceptable initializer (even if "{}" might
+ // be even better).
+ void g() { y = 0; }
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]] warning: use nullptr
+ // CHECK-FIXES-NOT: y = nullptr;
+
+ T x;
+ T y;
+};
+void test_templated() {
+ pear<int*> p;
+ p.f();
+ p.g();
+ dummy(p.x);
+}
+
#define IS_EQ(x, y) if (x != y) return;
void test_macro_args() {
int i = 0;
More information about the cfe-commits
mailing list