20 const auto DeleteExpr =
22 has(declRefExpr(to(decl(equalsBoundNode(
"deletedPointer"))))))
25 const auto DeleteMemberExpr =
26 cxxDeleteExpr(has(memberExpr(hasDeclaration(
27 fieldDecl(equalsBoundNode(
"deletedMemberPointer"))))))
28 .bind(
"deleteMemberExpr");
30 const auto PointerExpr = anyOf(
31 declRefExpr(to(decl().bind(
"deletedPointer"))),
32 memberExpr(hasDeclaration(fieldDecl().bind(
"deletedMemberPointer"))));
34 const auto BinaryPointerCheckCondition = binaryOperator(hasOperands(
35 anyOf(cxxNullPtrLiteralExpr(), integerLiteral(equals(0))), PointerExpr));
37 const auto IfWithScopedCondition =
38 ifStmt(anyOf(hasInitStatement(stmt()),
39 hasConditionVariableStatement(declStmt())))
40 .bind(
"ifWithScopedCondition");
43 ifStmt(hasCondition(anyOf(PointerExpr, BinaryPointerCheckCondition)),
44 optionally(IfWithScopedCondition),
46 DeleteExpr, DeleteMemberExpr,
47 compoundStmt(anyOf(has(DeleteExpr), has(DeleteMemberExpr)),
50 .bind(
"ifWithDelete"),
55 const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>(
"ifWithDelete");
56 const bool HasScopedCondition =
57 Result.Nodes.getNodeAs<IfStmt>(
"ifWithScopedCondition") !=
nullptr;
58 const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>(
"compound");
61 IfWithDelete->getBeginLoc(),
62 "'if' statement is unnecessary; deleting null pointer has no effect");
63 if (HasScopedCondition || IfWithDelete->hasElseStorage())
68 IfWithDelete->getThen()->getBeginLoc(), *Result.SourceManager,
69 Result.Context->getLangOpts());
73 Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
74 IfWithDelete->getBeginLoc(), PrevTok->getLocation()));
77 Diag << FixItHint::CreateRemoval(
78 CharSourceRange::getTokenRange(Compound->getLBracLoc()));
79 Diag << FixItHint::CreateRemoval(
80 CharSourceRange::getTokenRange(Compound->getRBracLoc()));
std::optional< Token > getPreviousToken(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
Returns previous token or std::nullopt if not found.