diff options
author | Thomas Köppe <tkoeppe@google.com> | 2024-09-25 17:25:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-25 09:25:46 -0700 |
commit | cebb7c010854e39a77065cfd681db91a79e7ce15 (patch) | |
tree | cf0642aa99efd1a5cb9db2ddd00f884920b06a53 /clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp | |
parent | d01e336336f2b7fb4137e3dcc7d5c0b06ca1f3d6 (diff) | |
download | llvm-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.cpp | 12 |
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))))); |