10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 19 void MisplacedOperatorInStrlenInAllocCheck::registerMatchers(
20 MatchFinder *Finder) {
21 const auto StrLenFunc = functionDecl(anyOf(
22 hasName(
"::strlen"), hasName(
"::std::strlen"), hasName(
"::strnlen"),
23 hasName(
"::std::strnlen"), hasName(
"::strnlen_s"),
24 hasName(
"::std::strnlen_s"), hasName(
"::wcslen"),
25 hasName(
"::std::wcslen"), hasName(
"::wcsnlen"), hasName(
"::std::wcsnlen"),
26 hasName(
"::wcsnlen_s"), hasName(
"std::wcsnlen_s")));
29 callExpr(callee(StrLenFunc),
30 hasAnyArgument(ignoringImpCasts(
33 hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))
37 const auto BadArg = anyOf(
38 allOf(unless(binaryOperator(
39 hasOperatorName(
"+"), hasLHS(BadUse),
40 hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))),
41 hasDescendant(BadUse)),
44 const auto Alloc0Func =
45 functionDecl(anyOf(hasName(
"::malloc"), hasName(
"std::malloc"),
46 hasName(
"::alloca"), hasName(
"std::alloca")));
47 const auto Alloc1Func =
48 functionDecl(anyOf(hasName(
"::calloc"), hasName(
"std::calloc"),
49 hasName(
"::realloc"), hasName(
"std::realloc")));
51 const auto Alloc0FuncPtr =
52 varDecl(hasType(isConstQualified()),
53 hasInitializer(ignoringParenImpCasts(
54 declRefExpr(hasDeclaration(Alloc0Func)))));
55 const auto Alloc1FuncPtr =
56 varDecl(hasType(isConstQualified()),
57 hasInitializer(ignoringParenImpCasts(
58 declRefExpr(hasDeclaration(Alloc1Func)))));
60 Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))),
61 hasArgument(0, BadArg))
64 Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))),
65 hasArgument(1, BadArg))
69 cxxNewExpr(isArray(), hasArraySize(BadArg)).bind(
"Alloc"),
this);
72 void MisplacedOperatorInStrlenInAllocCheck::check(
73 const MatchFinder::MatchResult &Result) {
74 const Expr *Alloc = Result.Nodes.getNodeAs<CallExpr>(
"Alloc");
76 Alloc = Result.Nodes.getNodeAs<CXXNewExpr>(
"Alloc");
77 assert(Alloc &&
"Matched node bound by 'Alloc' shoud be either 'CallExpr'" 80 const auto *StrLen = Result.Nodes.getNodeAs<CallExpr>(
"StrLen");
81 const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"BinOp");
83 const StringRef StrLenText = Lexer::getSourceText(
85 *Result.SourceManager, getLangOpts());
86 const StringRef Arg0Text = Lexer::getSourceText(
88 *Result.SourceManager, getLangOpts());
89 const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find(Arg0Text));
90 const StringRef StrLenEnd = StrLenText.substr(
91 StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size());
93 const StringRef LHSText = Lexer::getSourceText(
95 *Result.SourceManager, getLangOpts());
96 const StringRef RHSText = Lexer::getSourceText(
98 *Result.SourceManager, getLangOpts());
100 auto Hint = FixItHint::CreateReplacement(
101 StrLen->getSourceRange(),
102 (StrLenBegin + LHSText + StrLenEnd +
" + " + RHSText).str());
104 diag(Alloc->getBeginLoc(),
105 "addition operator is applied to the argument of %0 instead of its " 107 << StrLen->getDirectCallee()->getName() << Hint;
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//