clang-tools  14.0.0git
MisplacedPointerArithmeticInAllocCheck.cpp
Go to the documentation of this file.
1 //===--- MisplacedPointerArithmeticInAllocCheck.cpp - clang-tidy-----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace bugprone {
19 
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"));
25 
26  const auto AllocFuncPtr =
27  varDecl(hasType(isConstQualified()),
28  hasInitializer(ignoringParenImpCasts(
29  declRefExpr(hasDeclaration(AllocFunc)))));
30 
31  const auto AdditiveOperator = binaryOperator(hasAnyOperatorName("+", "-"));
32 
33  const auto IntExpr = expr(hasType(isInteger()));
34 
35  const auto AllocCall = callExpr(callee(decl(anyOf(AllocFunc, AllocFuncPtr))));
36 
37  Finder->addMatcher(
38  binaryOperator(
39  AdditiveOperator,
40  hasLHS(anyOf(AllocCall, castExpr(hasSourceExpression(AllocCall)))),
41  hasRHS(IntExpr))
42  .bind("PtrArith"),
43  this);
44 
45  const auto New = cxxNewExpr(unless(isArray()));
46 
47  Finder->addMatcher(binaryOperator(AdditiveOperator,
48  hasLHS(anyOf(New, castExpr(New))),
49  hasRHS(IntExpr))
50  .bind("PtrArith"),
51  this);
52 
53  const auto ArrayNew = cxxNewExpr(isArray());
54 
55  Finder->addMatcher(binaryOperator(AdditiveOperator,
56  hasLHS(anyOf(ArrayNew, castExpr(ArrayNew))),
57  hasRHS(IntExpr))
58  .bind("PtrArith"),
59  this);
60 }
61 
63  const MatchFinder::MatchResult &Result) {
64  const auto *PtrArith = Result.Nodes.getNodeAs<BinaryOperator>("PtrArith");
65  const Expr *AllocExpr = PtrArith->getLHS()->IgnoreParenCasts();
66  std::string CallName;
67 
68  if (const auto *Call = dyn_cast<CallExpr>(AllocExpr)) {
69  const NamedDecl *Func = Call->getDirectCallee();
70  if (!Func) {
71  Func = cast<NamedDecl>(Call->getCalleeDecl());
72  }
73  CallName = Func->getName().str();
74  } else {
75  const auto *New = cast<CXXNewExpr>(AllocExpr);
76  if (New->isArray()) {
77  CallName = "operator new[]";
78  } else {
79  const auto *CtrE = New->getConstructExpr();
80  if (!CtrE || !CtrE->getArg(CtrE->getNumArgs() - 1)
81  ->getType()
82  ->isIntegralOrEnumerationType())
83  return;
84  CallName = "operator new";
85  }
86  }
87 
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());
94 
95  diag(PtrArith->getBeginLoc(),
96  "arithmetic operation is applied to the result of %0() instead of its "
97  "size-like argument")
98  << CallName << FixItHint::CreateRemoval(OldRParen)
99  << FixItHint::CreateInsertion(NewRParen, RParen);
100 }
101 
102 } // namespace bugprone
103 } // namespace tidy
104 } // namespace clang
clang::tidy::cppcoreguidelines::getSourceText
static std::string getSourceText(const CXXDestructorDecl &Destructor)
Definition: VirtualClassDestructorCheck.cpp:112
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::clangd::check
bool check(llvm::StringRef File, llvm::function_ref< bool(const Position &)> ShouldCheckLine, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:259
MisplacedPointerArithmeticInAllocCheck.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27