Skip to content

Commit 2f98433

Browse files
committed
[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 `{}`.)
1 parent 698be40 commit 2f98433

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ AST_MATCHER(Type, sugaredNullptrType) {
3838
StatementMatcher makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) {
3939
auto ImplicitCastToNull = implicitCastExpr(
4040
anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
41-
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
41+
anyOf(hasSourceExpression(gnuNullExpr()),
42+
unless(hasImplicitDestinationType(
43+
qualType(substTemplateTypeParmType())))),
4244
unless(hasSourceExpression(hasType(sugaredNullptrType()))),
4345
unless(hasImplicitDestinationType(
4446
qualType(matchers::matchesAnyListedTypeName(NameList)))));

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ Changes in existing checks
183183
<clang-tidy/checks/readability/redundant-smartptr-get>` check to
184184
remove `->`, when redundant `get()` is removed.
185185

186+
- Improved :doc:`modernize-use-nullptr
187+
<clang-tidy/checks/modernize/use-nullptr>` check to also recognize
188+
`NULL`/`__null` (but not `0`) when used with a templated type.
189+
186190
Removed checks
187191
^^^^^^^^^^^^^^
188192

clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,28 @@ void test_macro_expansion4() {
8484
#undef MY_NULL
8585
}
8686

87+
template <typename T> struct pear {
88+
// If you say __null (or NULL), we assume that T will always be a pointer
89+
// type, so we suggest replacing it with nullptr.
90+
void f() { x = __null; }
91+
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr [modernize-use-nullptr]
92+
// CHECK-FIXES: x = nullptr;
93+
94+
// But if you say 0, we allow the possibility that T can be used with integral
95+
// and pointer types, and "0" is an acceptable initializer (even if "{}" might
96+
// be even better).
97+
void g() { y = 0; }
98+
99+
T x;
100+
T y;
101+
};
102+
void test_templated() {
103+
pear<int*> p;
104+
p.f();
105+
p.g();
106+
dummy(p.x);
107+
}
108+
87109
#define IS_EQ(x, y) if (x != y) return;
88110
void test_macro_args() {
89111
int i = 0;

0 commit comments

Comments
 (0)