75 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 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"14 15using namespace clang::ast_matchers;16 17namespace clang::tidy::readability {18 19void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {20 const auto DeleteExpr =21 cxxDeleteExpr(22 has(declRefExpr(to(decl(equalsBoundNode("deletedPointer"))))))23 .bind("deleteExpr");24 25 const auto DeleteMemberExpr =26 cxxDeleteExpr(has(memberExpr(hasDeclaration(27 fieldDecl(equalsBoundNode("deletedMemberPointer"))))))28 .bind("deleteMemberExpr");29 30 const auto PointerExpr = anyOf(31 declRefExpr(to(decl().bind("deletedPointer"))),32 memberExpr(hasDeclaration(fieldDecl().bind("deletedMemberPointer"))));33 34 const auto BinaryPointerCheckCondition = binaryOperator(hasOperands(35 anyOf(cxxNullPtrLiteralExpr(), integerLiteral(equals(0))), PointerExpr));36 37 Finder->addMatcher(38 ifStmt(hasCondition(anyOf(PointerExpr, BinaryPointerCheckCondition)),39 hasThen(anyOf(40 DeleteExpr, DeleteMemberExpr,41 compoundStmt(anyOf(has(DeleteExpr), has(DeleteMemberExpr)),42 statementCountIs(1))43 .bind("compound"))))44 .bind("ifWithDelete"),45 this);46}47 48void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {49 const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>("ifWithDelete");50 const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");51 52 auto Diag = diag(53 IfWithDelete->getBeginLoc(),54 "'if' statement is unnecessary; deleting null pointer has no effect");55 if (IfWithDelete->getElse())56 return;57 // FIXME: generate fixit for this case.58 59 Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(60 IfWithDelete->getBeginLoc(),61 utils::lexer::getPreviousToken(IfWithDelete->getThen()->getBeginLoc(),62 *Result.SourceManager,63 Result.Context->getLangOpts())64 .getLocation()));65 66 if (Compound) {67 Diag << FixItHint::CreateRemoval(68 CharSourceRange::getTokenRange(Compound->getLBracLoc()));69 Diag << FixItHint::CreateRemoval(70 CharSourceRange::getTokenRange(Compound->getRBracLoc()));71 }72}73 74} // namespace clang::tidy::readability75