clang-tools 6.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 DeleteMemberExpr =
28 cxxDeleteExpr(has(castExpr(has(memberExpr(hasDeclaration(
29 fieldDecl(equalsBoundNode("deletedMemberPointer"))))))))
30 .bind("deleteMemberExpr");
31
32 const auto PointerExpr = ignoringImpCasts(anyOf(
33 declRefExpr(to(decl().bind("deletedPointer"))),
34 memberExpr(hasDeclaration(fieldDecl().bind("deletedMemberPointer")))));
35
36 const auto PointerCondition = castExpr(hasCastKind(CK_PointerToBoolean),
37 hasSourceExpression(PointerExpr));
38 const auto BinaryPointerCheckCondition =
39 binaryOperator(hasEitherOperand(castExpr(hasCastKind(CK_NullToPointer))),
40 hasEitherOperand(PointerExpr));
41
42 Finder->addMatcher(
43 ifStmt(hasCondition(anyOf(PointerCondition, BinaryPointerCheckCondition)),
44 hasThen(anyOf(
45 DeleteExpr, DeleteMemberExpr,
46 compoundStmt(anyOf(has(DeleteExpr), has(DeleteMemberExpr)),
47 statementCountIs(1))
48 .bind("compound"))))
49 .bind("ifWithDelete"),
50 this);
51 }
52
53 void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {
54 const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>("ifWithDelete");
55 const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
56
57 auto Diag = diag(
58 IfWithDelete->getLocStart(),
59 "'if' statement is unnecessary; deleting null pointer has no effect");
60 if (IfWithDelete->getElse())
61 return;
62 // FIXME: generate fixit for this case.
63
64 Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
65 IfWithDelete->getLocStart(),
66 Lexer::getLocForEndOfToken(IfWithDelete->getCond()->getLocEnd(), 0,
67 *Result.SourceManager,
68 Result.Context->getLangOpts())));
69 if (Compound) {
70 Diag << FixItHint::CreateRemoval(
71 CharSourceRange::getTokenRange(Compound->getLBracLoc()));
72 Diag << FixItHint::CreateRemoval(
73 CharSourceRange::getTokenRange(Compound->getRBracLoc()));
74 }
75 }
76
77 } // namespace readability
78 } // namespace tidy
79 } // namespace clang
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
clang
Definition: AndroidTidyModule.cpp:28
DeleteNullPointerCheck.h