11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
15 using namespace clang::ast_matchers;
21 void InaccurateEraseCheck::registerMatchers(MatchFinder *
Finder) {
24 if (!getLangOpts().CPlusPlus)
27 const auto CheckForEndCall = hasArgument(
28 1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts(
29 cxxMemberCallExpr(callee(cxxMethodDecl(hasName(
"end"))))
30 .bind(
"InaccEndCall")))),
35 on(hasType(namedDecl(matchesName(
"^::std::")))),
36 callee(cxxMethodDecl(hasName(
"erase"))), argumentCountIs(1),
37 hasArgument(0, has(ignoringParenImpCasts(
38 callExpr(callee(functionDecl(matchesName(
39 "^::std::(remove(_if)?|unique)$"))),
41 .bind(
"InaccAlgCall")))),
42 unless(isInTemplateInstantiation()))
47 void InaccurateEraseCheck::check(
const MatchFinder::MatchResult &
Result) {
48 const auto *MemberCall =
49 Result.Nodes.getNodeAs<CXXMemberCallExpr>(
"InaccErase");
51 Result.Nodes.getNodeAs<CXXMemberCallExpr>(
"InaccEndCall");
52 const SourceLocation
Loc = MemberCall->getLocStart();
56 if (!Loc.isMacroID() && EndExpr) {
57 const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>(
"InaccAlgCall");
58 std::string ReplacementText = Lexer::getSourceText(
59 CharSourceRange::getTokenRange(EndExpr->getSourceRange()),
60 *Result.SourceManager, getLangOpts());
61 const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
62 AlgCall->getLocEnd(), 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 "
SourceLocation Loc
'#' location in the include directive
std::unique_ptr< ast_matchers::MatchFinder > Finder