10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
20 void MisplacedPointerArithmeticInAllocCheck::registerMatchers(
21 MatchFinder *Finder) {
22 const auto AllocFunc =
23 functionDecl(hasAnyName(
"::malloc",
"std::malloc",
"::alloca",
"::calloc",
24 "std::calloc",
"::realloc",
"std::realloc"));
26 const auto AllocFuncPtr =
27 varDecl(hasType(isConstQualified()),
28 hasInitializer(ignoringParenImpCasts(
29 declRefExpr(hasDeclaration(AllocFunc)))));
31 const auto AdditiveOperator = binaryOperator(hasAnyOperatorName(
"+",
"-"));
33 const auto IntExpr = expr(hasType(isInteger()));
35 const auto AllocCall = callExpr(callee(decl(anyOf(AllocFunc, AllocFuncPtr))));
40 hasLHS(anyOf(AllocCall, castExpr(hasSourceExpression(AllocCall)))),
45 const auto New = cxxNewExpr(unless(isArray()));
47 Finder->addMatcher(binaryOperator(AdditiveOperator,
48 hasLHS(anyOf(New, castExpr(New))),
53 const auto ArrayNew = cxxNewExpr(isArray());
55 Finder->addMatcher(binaryOperator(AdditiveOperator,
56 hasLHS(anyOf(ArrayNew, castExpr(ArrayNew))),
62 void MisplacedPointerArithmeticInAllocCheck::check(
63 const MatchFinder::MatchResult &Result) {
64 const auto *PtrArith = Result.Nodes.getNodeAs<BinaryOperator>(
"PtrArith");
65 const Expr *AllocExpr = PtrArith->getLHS()->IgnoreParenCasts();
68 if (
const auto *Call = dyn_cast<CallExpr>(AllocExpr)) {
69 const NamedDecl *Func = Call->getDirectCallee();
71 Func = cast<NamedDecl>(Call->getCalleeDecl());
73 CallName = Func->getName().str();
75 const auto *New = cast<CXXNewExpr>(AllocExpr);
77 CallName =
"operator new[]";
79 const auto *CtrE = New->getConstructExpr();
80 if (!CtrE->getArg(CtrE->getNumArgs() - 1)
82 ->isIntegralOrEnumerationType())
84 CallName =
"operator new";
88 const SourceRange OldRParen = SourceRange(PtrArith->getLHS()->getEndLoc());
89 const StringRef RParen =
90 Lexer::getSourceText(CharSourceRange::getTokenRange(OldRParen),
91 *Result.SourceManager, getLangOpts());
92 const SourceLocation NewRParen = Lexer::getLocForEndOfToken(
93 PtrArith->getEndLoc(), 0, *Result.SourceManager, getLangOpts());
95 diag(PtrArith->getBeginLoc(),
96 "arithmetic operation is applied to the result of %0() instead of its "
98 << CallName << FixItHint::CreateRemoval(OldRParen)
99 << FixItHint::CreateInsertion(NewRParen, RParen);