aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
diff options
context:
space:
mode:
authorThomas Köppe <tkoeppe@google.com>2024-09-25 17:25:46 +0100
committerGitHub <noreply@github.com>2024-09-25 09:25:46 -0700
commitcebb7c010854e39a77065cfd681db91a79e7ce15 (patch)
treecf0642aa99efd1a5cb9db2ddd00f884920b06a53 /clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
parentd01e336336f2b7fb4137e3dcc7d5c0b06ca1f3d6 (diff)
downloadllvm-cebb7c010854e39a77065cfd681db91a79e7ce15.zip
llvm-cebb7c010854e39a77065cfd681db91a79e7ce15.tar.gz
llvm-cebb7c010854e39a77065cfd681db91a79e7ce15.tar.bz2
[clang-tidy] modernize-use-nullptr matches "NULL" in templates (#109169)
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 `{}`.)
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp12
1 files changed, 11 insertions, 1 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 6a003a3..108717e 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -35,10 +35,20 @@ AST_MATCHER(Type, sugaredNullptrType) {
/// to null within.
/// Finding sequences of explicit casts is necessary so that an entire sequence
/// can be replaced instead of just the inner-most implicit cast.
+///
+/// TODO/NOTE: The second "anyOf" below discards matches on a substituted type,
+/// since we don't know if that would _always_ be a pointer type for all other
+/// specializations, unless the expression was "__null", in which case we assume
+/// that all specializations are expected to be for pointer types. Ideally this
+/// would check for the "NULL" macro instead, but that'd be harder to express.
+/// In practice, "NULL" is often defined as "__null", and this is a useful
+/// condition.
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)))));