SilverGeri updated this revision to Diff 77784.
SilverGeri added a comment.
Herald added a subscriber: modocache.

move checker to readability module
add missing description to header file


https://reviews.llvm.org/D21298

Files:
  clang-tidy/readability/CMakeLists.txt
  clang-tidy/readability/DeleteNullPointerCheck.cpp
  clang-tidy/readability/DeleteNullPointerCheck.h
  clang-tidy/readability/ReadabilityTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/readability-delete-null-pointer.rst
  test/clang-tidy/readability-delete-null-pointer.cpp

Index: test/clang-tidy/readability-delete-null-pointer.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/readability-delete-null-pointer.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s readability-delete-null-pointer %t
+
+#include <cstdlib>
+
+void f() {
+  int *p = 0;
+  if (p) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+    delete p;
+  }
+  // CHECK-FIXES: delete p;
+  int *p3 = new int[3];
+  if (p3)
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+    delete[] p3;
+  // CHECK-FIXES: delete[] p3;
+
+  if (NULL != p) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+    delete p;
+  }
+  // CHECK-FIXES: delete p;
+
+  if (p != nullptr) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+    delete p;
+  }
+  // CHECK-FIXES: delete p;
+
+  if (p != 0) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+    delete p;
+  }
+  // CHECK-FIXES: delete p;
+}
+
+void g() {
+  int *p, *p2;
+  if (p)
+    delete p2;
+
+  if (p && p2)
+    delete p;
+
+  if (p2) {
+    int x = 5;
+    delete p2;
+  }
+}
\ No newline at end of file
Index: docs/clang-tidy/checks/readability-delete-null-pointer.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/readability-delete-null-pointer.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - readability-delete-null-pointer
+
+readability-delete-null-pointer
+===============================
+
+Checks the 'if' statements where a pointer's existence is checked and then deletes the pointer.
+The check is unnecessary as deleting a nullpointer has no effect.
+
+.. code:: c++
+  int *p;
+  if (p)
+    delete p;
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -123,6 +123,7 @@
    readability-avoid-const-params-in-decls
    readability-braces-around-statements
    readability-container-size-empty
+   readability-delete-null-pointer
    readability-deleted-default
    readability-else-after-return
    readability-function-size
Index: clang-tidy/readability/ReadabilityTidyModule.cpp
===================================================================
--- clang-tidy/readability/ReadabilityTidyModule.cpp
+++ clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -13,6 +13,7 @@
 #include "AvoidConstParamsInDecls.h"
 #include "BracesAroundStatementsCheck.h"
 #include "ContainerSizeEmptyCheck.h"
+#include "DeleteNullPointerCheck.h"
 #include "DeletedDefaultCheck.h"
 #include "ElseAfterReturnCheck.h"
 #include "FunctionSizeCheck.h"
@@ -44,6 +45,8 @@
         "readability-braces-around-statements");
     CheckFactories.registerCheck<ContainerSizeEmptyCheck>(
         "readability-container-size-empty");
+    CheckFactories.registerCheck<DeleteNullPointerCheck>(
+        "readability-delete-null-pointer");
     CheckFactories.registerCheck<DeletedDefaultCheck>(
         "readability-deleted-default");
     CheckFactories.registerCheck<ElseAfterReturnCheck>(
Index: clang-tidy/readability/DeleteNullPointerCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/readability/DeleteNullPointerCheck.h
@@ -0,0 +1,35 @@
+//===--- DeleteNullPointerCheck.h - clang-tidy-------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETE_NULL_POINTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETE_NULL_POINTER_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Check whether the 'if' statement is unnecessary before calling 'delete' on a pointer.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-delete-null-pointer.html
+class DeleteNullPointerCheck : public ClangTidyCheck {
+public:
+  DeleteNullPointerCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETE_NULL_POINTER_H
Index: clang-tidy/readability/DeleteNullPointerCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/readability/DeleteNullPointerCheck.cpp
@@ -0,0 +1,66 @@
+//===--- DeleteNullPointerCheck.cpp - clang-tidy---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DeleteNullPointerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {
+  const auto DeleteExpr =
+          cxxDeleteExpr(has(castExpr(has(declRefExpr(
+                  to(decl(equalsBoundNode("deletedPointer"))))))))
+                  .bind("deleteExpr");
+
+  const auto PointerCondition = castExpr(hasCastKind(CK_PointerToBoolean));
+  const auto BinaryPointerCheckCondition = binaryOperator(
+          allOf(hasEitherOperand(castExpr(hasCastKind(CK_NullToPointer))),
+                hasEitherOperand(ignoringImpCasts(declRefExpr()))));
+
+  Finder->addMatcher(
+          ifStmt(allOf(hasCondition(
+                  anyOf(PointerCondition, BinaryPointerCheckCondition)),
+                       hasCondition(anyOf(
+                               ignoringImpCasts(
+                                       declRefExpr(to(decl().bind("deletedPointer")))),
+                               binaryOperator(hasEitherOperand(ignoringImpCasts(
+                                       declRefExpr(to(decl().bind("deletedPointer")))))))),
+                       hasThen(anyOf(
+                               DeleteExpr,
+                               compoundStmt(allOf(has(DeleteExpr), statementCountIs(1)))
+                                       .bind("compound")))))
+                  .bind("ifWithDelete"),
+          this);
+}
+
+void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>("ifWithDelete");
+  const auto *Delete = Result.Nodes.getNodeAs<CXXDeleteExpr>("deleteExpr");
+
+  auto D =
+          diag(IfWithDelete->getLocStart(),
+               "'if' statement is unnecessary; deleting null pointer has no effect");
+  std::string ReplacementText = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(Delete->getSourceRange()),
+          *Result.SourceManager, Result.Context->getLangOpts());
+  ReplacementText += ';';
+
+  D << FixItHint::CreateReplacement(IfWithDelete->getSourceRange(),
+                                    ReplacementText);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tidy/readability/CMakeLists.txt
+++ clang-tidy/readability/CMakeLists.txt
@@ -4,6 +4,7 @@
   AvoidConstParamsInDecls.cpp
   BracesAroundStatementsCheck.cpp
   ContainerSizeEmptyCheck.cpp
+  DeleteNullPointerCheck.cpp
   DeletedDefaultCheck.cpp
   ElseAfterReturnCheck.cpp
   FunctionSizeCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to