10 #include "../utils/LexerUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
19 namespace readability {
21 void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {
22 const auto DeleteExpr =
24 has(declRefExpr(to(decl(equalsBoundNode(
"deletedPointer"))))))
27 const auto DeleteMemberExpr =
28 cxxDeleteExpr(has(memberExpr(hasDeclaration(
29 fieldDecl(equalsBoundNode(
"deletedMemberPointer"))))))
30 .bind(
"deleteMemberExpr");
32 const auto PointerExpr = anyOf(
33 declRefExpr(to(decl().bind(
"deletedPointer"))),
34 memberExpr(hasDeclaration(fieldDecl().bind(
"deletedMemberPointer"))));
36 const auto BinaryPointerCheckCondition = binaryOperator(hasOperands(
37 anyOf(cxxNullPtrLiteralExpr(), integerLiteral(equals(0))), PointerExpr));
40 ifStmt(hasCondition(anyOf(PointerExpr, BinaryPointerCheckCondition)),
42 DeleteExpr, DeleteMemberExpr,
43 compoundStmt(anyOf(has(DeleteExpr), has(DeleteMemberExpr)),
46 .bind(
"ifWithDelete"),
51 const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>(
"ifWithDelete");
52 const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>(
"compound");
55 IfWithDelete->getBeginLoc(),
56 "'if' statement is unnecessary; deleting null pointer has no effect");
57 if (IfWithDelete->getElse())
61 Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
62 IfWithDelete->getBeginLoc(),
64 *Result.SourceManager,
65 Result.Context->getLangOpts())
69 Diag << FixItHint::CreateRemoval(
70 CharSourceRange::getTokenRange(Compound->getLBracLoc()));
71 Diag << FixItHint::CreateRemoval(
72 CharSourceRange::getTokenRange(Compound->getRBracLoc()));