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;
24 MemsetZeroLengthCheck::registerMatchers(ast_matchers::MatchFinder *
Finder) {
29 callExpr(callee(functionDecl(hasName(
"::memset"))), argumentCountIs(3),
30 unless(isInTemplateInstantiation())).bind(
"decl"),
37 const SourceManager &
SM = *Result.SourceManager;
40 if (R.getBegin().isMacroID() ||
41 !SM.isWrittenInSameFile(R.getBegin(), R.getEnd()))
44 const char *Begin = SM.getCharacterData(R.getBegin());
45 const char *End = SM.getCharacterData(Lexer::getLocForEndOfToken(
46 R.getEnd(), 0,
SM, Result.Context->getLangOpts()));
48 return StringRef(Begin, End - Begin);
51 void MemsetZeroLengthCheck::check(
const MatchFinder::MatchResult &
Result) {
52 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"decl");
57 const Expr *Arg1 = Call->getArg(1);
58 const Expr *Arg2 = Call->getArg(2);
61 llvm::APSInt Value1, Value2;
62 if (Arg2->isValueDependent() ||
63 !Arg2->EvaluateAsInt(Value2, *Result.Context) || Value2 != 0)
69 if (!Arg1->isValueDependent() &&
70 Arg1->EvaluateAsInt(Value1, *Result.Context) &&
71 (Value1 == 0 || Value1.isNegative()))
77 auto D = diag(Call->getLocStart(),
78 "memset of size zero, potentially swapped arguments");
79 SourceRange LHSRange = Arg1->getSourceRange();
80 SourceRange RHSRange = Arg2->getSourceRange();
81 StringRef RHSString =
getAsString(Result, RHSRange);
82 StringRef LHSString =
getAsString(Result, LHSRange);
83 if (LHSString.empty() || RHSString.empty())
86 D << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(LHSRange),
88 << 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.