11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchers.h"
14 #include "clang/Lex/Lexer.h"
16 using namespace clang::ast_matchers;
23 void MemsetZeroLengthCheck::registerMatchers(
24 ast_matchers::MatchFinder *
Finder) {
28 Finder->addMatcher(callExpr(callee(functionDecl(hasName(
"::memset"))),
30 unless(isInTemplateInstantiation()))
38 const SourceManager &
SM = *Result.SourceManager;
41 if (R.getBegin().isMacroID() ||
42 !SM.isWrittenInSameFile(R.getBegin(), R.getEnd()))
45 const char *Begin = SM.getCharacterData(R.getBegin());
46 const char *End = SM.getCharacterData(Lexer::getLocForEndOfToken(
47 R.getEnd(), 0,
SM, Result.Context->getLangOpts()));
49 return StringRef(Begin, End - Begin);
52 void MemsetZeroLengthCheck::check(
const MatchFinder::MatchResult &
Result) {
53 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"decl");
58 const Expr *Arg1 = Call->getArg(1);
59 const Expr *Arg2 = Call->getArg(2);
62 llvm::APSInt Value1, Value2;
63 if (Arg2->isValueDependent() ||
64 !Arg2->EvaluateAsInt(Value2, *Result.Context) || Value2 != 0)
70 if (!Arg1->isValueDependent() &&
71 Arg1->EvaluateAsInt(Value1, *Result.Context) &&
72 (Value1 == 0 || Value1.isNegative()))
78 auto D = diag(Call->getLocStart(),
79 "memset of size zero, potentially swapped arguments");
80 SourceRange LHSRange = Arg1->getSourceRange();
81 SourceRange RHSRange = Arg2->getSourceRange();
82 StringRef RHSString =
getAsString(Result, RHSRange);
83 StringRef LHSString =
getAsString(Result, LHSRange);
84 if (LHSString.empty() || RHSString.empty())
87 D << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(LHSRange),
89 << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(RHSRange),
std::unique_ptr< ast_matchers::MatchFinder > Finder
static StringRef getAsString(const MatchFinder::MatchResult &Result, SourceRange R)
Get a StringRef representing a SourceRange.