10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
20 void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
23 callee(functionDecl(hasAnyName(
"remove",
"remove_if",
"unique"))),
26 anyOf(cxxConstructExpr(has(ignoringImplicit(
27 cxxMemberCallExpr(callee(cxxMethodDecl(hasName(
"end"))))
32 const auto DeclInStd = type(hasUnqualifiedDesugaredType(
33 tagType(hasDeclaration(decl(isInStdNamespace())))));
36 ast_type_traits::TK_AsIs,
38 on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
39 callee(cxxMethodDecl(hasName(
"erase"))), argumentCountIs(1),
40 hasArgument(0, has(ignoringImplicit(anyOf(
41 EndCall, has(ignoringImplicit(EndCall)))))),
42 unless(isInTemplateInstantiation()))
47 void InaccurateEraseCheck::check(
const MatchFinder::MatchResult &Result) {
48 const auto *MemberCall =
49 Result.Nodes.getNodeAs<CXXMemberCallExpr>(
"erase");
51 Result.Nodes.getNodeAs<CXXMemberCallExpr>(
"end");
52 const SourceLocation
Loc = MemberCall->getBeginLoc();
56 if (!
Loc.isMacroID() && EndExpr) {
57 const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>(
"alg");
58 std::string ReplacementText = std::string(Lexer::getSourceText(
59 CharSourceRange::getTokenRange(EndExpr->getSourceRange()),
60 *Result.SourceManager, getLangOpts()));
61 const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
62 AlgCall->getEndLoc(), 0, *Result.SourceManager, getLangOpts());
63 Hint = FixItHint::CreateInsertion(EndLoc,
", " + ReplacementText);
66 diag(
Loc,
"this call will remove at most one item even when multiple items "