1 //===--- DeleteNullPointerCheck.cpp - clang-tidy---------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "DeleteNullPointerCheck.h"
10 #include "../utils/LexerUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
15 using namespace clang::ast_matchers
;
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"),
50 void DeleteNullPointerCheck::check(const MatchFinder::MatchResult
&Result
) {
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())
59 // FIXME: generate fixit for this case.
61 Diag
<< FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
62 IfWithDelete
->getBeginLoc(),
63 utils::lexer::getPreviousToken(IfWithDelete
->getThen()->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()));
76 } // namespace readability