clang-tools  11.0.0
DeleteNullPointerCheck.cpp
Go to the documentation of this file.
1 //===--- DeleteNullPointerCheck.cpp - clang-tidy---------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "../utils/LexerUtils.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 = binaryOperator(
39  hasOperands(castExpr(hasCastKind(CK_NullToPointer)), PointerExpr));
40 
41  Finder->addMatcher(
42  traverse(ast_type_traits::TK_AsIs,
43  ifStmt(hasCondition(
44  anyOf(PointerCondition, BinaryPointerCheckCondition)),
45  hasThen(anyOf(DeleteExpr, DeleteMemberExpr,
46  compoundStmt(anyOf(has(DeleteExpr),
47  has(DeleteMemberExpr)),
48  statementCountIs(1))
49  .bind("compound"))))
50  .bind("ifWithDelete")),
51  this);
52 }
53 
54 void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {
55  const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>("ifWithDelete");
56  const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
57 
58  auto Diag = diag(
59  IfWithDelete->getBeginLoc(),
60  "'if' statement is unnecessary; deleting null pointer has no effect");
61  if (IfWithDelete->getElse())
62  return;
63  // FIXME: generate fixit for this case.
64 
65  Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
66  IfWithDelete->getBeginLoc(),
67  utils::lexer::getPreviousToken(IfWithDelete->getThen()->getBeginLoc(),
68  *Result.SourceManager,
69  Result.Context->getLangOpts())
70  .getLocation()));
71 
72  if (Compound) {
73  Diag << FixItHint::CreateRemoval(
74  CharSourceRange::getTokenRange(Compound->getLBracLoc()));
75  Diag << FixItHint::CreateRemoval(
76  CharSourceRange::getTokenRange(Compound->getRBracLoc()));
77  }
78 }
79 
80 } // namespace readability
81 } // namespace tidy
82 } // namespace clang
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::tidy::utils::lexer::getPreviousToken
Token getPreviousToken(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
Returns previous token or tok::unknown if not found.
Definition: LexerUtils.cpp:17
DeleteNullPointerCheck.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27