clang-tools  4.0.0
DeleteNullPointerCheck.cpp
Go to the documentation of this file.
1 //===--- DeleteNullPointerCheck.cpp - clang-tidy---------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "DeleteNullPointerCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace readability {
20 
21 void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {
22  const auto DeleteExpr =
23  cxxDeleteExpr(has(castExpr(has(declRefExpr(
24  to(decl(equalsBoundNode("deletedPointer"))))))))
25  .bind("deleteExpr");
26 
27  const auto PointerExpr =
28  ignoringImpCasts(declRefExpr(to(decl().bind("deletedPointer"))));
29  const auto PointerCondition = castExpr(hasCastKind(CK_PointerToBoolean),
30  hasSourceExpression(PointerExpr));
31  const auto BinaryPointerCheckCondition =
32  binaryOperator(hasEitherOperand(castExpr(hasCastKind(CK_NullToPointer))),
33  hasEitherOperand(PointerExpr));
34 
35  Finder->addMatcher(
36  ifStmt(hasCondition(anyOf(PointerCondition, BinaryPointerCheckCondition)),
37  hasThen(anyOf(DeleteExpr,
38  compoundStmt(has(DeleteExpr), statementCountIs(1))
39  .bind("compound"))))
40  .bind("ifWithDelete"),
41  this);
42 }
43 
44 void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {
45  const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>("ifWithDelete");
46  const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
47 
48  auto Diag = diag(
49  IfWithDelete->getLocStart(),
50  "'if' statement is unnecessary; deleting null pointer has no effect");
51  if (IfWithDelete->getElse())
52  return;
53  // FIXME: generate fixit for this case.
54 
55  Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
56  IfWithDelete->getLocStart(),
57  Lexer::getLocForEndOfToken(IfWithDelete->getCond()->getLocEnd(), 0,
58  *Result.SourceManager,
59  Result.Context->getLangOpts())));
60  if (Compound) {
61  Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
62  Compound->getLBracLoc(),
63  Lexer::getLocForEndOfToken(Compound->getLBracLoc(), 0,
64  *Result.SourceManager,
65  Result.Context->getLangOpts())));
66  Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
67  Compound->getRBracLoc(),
68  Lexer::getLocForEndOfToken(Compound->getRBracLoc(), 0,
69  *Result.SourceManager,
70  Result.Context->getLangOpts())));
71  }
72 }
73 
74 } // namespace readability
75 } // namespace tidy
76 } // namespace clang
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:262
const NamedDecl * Result
Definition: USRFinder.cpp:162