[clang-tidy] Fix for bug 31838: readability-delete-null-pointer does not work for class members

I have made a small fix for readability-delete-null-pointer check so it also checks for class members.

Example of case that it fixes
```
  struct A {
    void foo() {
      if(mp)
        delete mp;
    }
    int *mp;
  };
```

Reviewers: JDevlieghere, aaron.ballman, alexfh, malcolm.parsons

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D29726

llvm-svn: 294912
This commit is contained in:
Mads Ravn 2017-02-12 20:09:59 +00:00
parent e826cbf4f3
commit 6ff978fd54
3 changed files with 26 additions and 6 deletions

View File

@ -24,8 +24,15 @@ void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {
to(decl(equalsBoundNode("deletedPointer")))))))) to(decl(equalsBoundNode("deletedPointer"))))))))
.bind("deleteExpr"); .bind("deleteExpr");
const auto PointerExpr = const auto DeleteMemberExpr =
ignoringImpCasts(declRefExpr(to(decl().bind("deletedPointer")))); cxxDeleteExpr(has(castExpr(has(memberExpr(hasDeclaration(
fieldDecl(equalsBoundNode("deletedMemberPointer"))))))))
.bind("deleteMemberExpr");
const auto PointerExpr = ignoringImpCasts(anyOf(
declRefExpr(to(decl().bind("deletedPointer"))),
memberExpr(hasDeclaration(fieldDecl().bind("deletedMemberPointer")))));
const auto PointerCondition = castExpr(hasCastKind(CK_PointerToBoolean), const auto PointerCondition = castExpr(hasCastKind(CK_PointerToBoolean),
hasSourceExpression(PointerExpr)); hasSourceExpression(PointerExpr));
const auto BinaryPointerCheckCondition = const auto BinaryPointerCheckCondition =
@ -34,9 +41,11 @@ void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher( Finder->addMatcher(
ifStmt(hasCondition(anyOf(PointerCondition, BinaryPointerCheckCondition)), ifStmt(hasCondition(anyOf(PointerCondition, BinaryPointerCheckCondition)),
hasThen(anyOf(DeleteExpr, hasThen(anyOf(
compoundStmt(has(DeleteExpr), statementCountIs(1)) DeleteExpr, DeleteMemberExpr,
.bind("compound")))) compoundStmt(has(anyOf(DeleteExpr, DeleteMemberExpr)),
statementCountIs(1))
.bind("compound"))))
.bind("ifWithDelete"), .bind("ifWithDelete"),
this); this);
} }

View File

@ -16,7 +16,8 @@ namespace clang {
namespace tidy { namespace tidy {
namespace readability { namespace readability {
/// Check whether the 'if' statement is unnecessary before calling 'delete' on a pointer. /// Check whether the 'if' statement is unnecessary before calling 'delete' on a
/// pointer.
/// ///
/// For the user-facing documentation see: /// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-delete-null-pointer.html /// http://clang.llvm.org/extra/clang-tidy/checks/readability-delete-null-pointer.html

View File

@ -59,6 +59,16 @@ void f() {
} else { } else {
c2 = c; c2 = c;
} }
struct A {
void foo() {
if (mp) // #6
delete mp;
// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
// CHECK-FIXES: {{^ }}// #6
// CHECK-FIXES-NEXT: delete mp;
}
int *mp;
};
} }
void g() { void g() {