1 | //===--- NoMallocCheck.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 | |
9 | #include "NoMallocCheck.h" |
10 | #include "../utils/OptionsUtils.h" |
11 | #include "clang/ASTMatchers/ASTMatchFinder.h" |
12 | |
13 | using namespace clang::ast_matchers; |
14 | using namespace clang::ast_matchers::internal; |
15 | |
16 | namespace clang::tidy::cppcoreguidelines { |
17 | |
18 | void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { |
19 | Options.store(Options&: Opts, LocalName: "Allocations" , Value: AllocList); |
20 | Options.store(Options&: Opts, LocalName: "Reallocations" , Value: ReallocList); |
21 | Options.store(Options&: Opts, LocalName: "Deallocations" , Value: DeallocList); |
22 | } |
23 | |
24 | void NoMallocCheck::registerMatchers(MatchFinder *Finder) { |
25 | // Registering malloc, will suggest RAII. |
26 | Finder->addMatcher(NodeMatch: callExpr(callee(InnerMatcher: functionDecl(hasAnyName( |
27 | utils::options::parseStringList(Option: AllocList))))) |
28 | .bind(ID: "allocation" ), |
29 | Action: this); |
30 | |
31 | // Registering realloc calls, suggest std::vector or std::string. |
32 | Finder->addMatcher( |
33 | NodeMatch: callExpr(callee(InnerMatcher: functionDecl( |
34 | hasAnyName(utils::options::parseStringList(Option: (ReallocList)))))) |
35 | .bind(ID: "realloc" ), |
36 | Action: this); |
37 | |
38 | // Registering free calls, will suggest RAII instead. |
39 | Finder->addMatcher( |
40 | NodeMatch: callExpr(callee(InnerMatcher: functionDecl( |
41 | hasAnyName(utils::options::parseStringList(Option: (DeallocList)))))) |
42 | .bind(ID: "free" ), |
43 | Action: this); |
44 | } |
45 | |
46 | void NoMallocCheck::check(const MatchFinder::MatchResult &Result) { |
47 | const CallExpr *Call = nullptr; |
48 | StringRef Recommendation; |
49 | |
50 | if ((Call = Result.Nodes.getNodeAs<CallExpr>(ID: "allocation" ))) |
51 | Recommendation = "consider a container or a smart pointer" ; |
52 | else if ((Call = Result.Nodes.getNodeAs<CallExpr>(ID: "realloc" ))) |
53 | Recommendation = "consider std::vector or std::string" ; |
54 | else if ((Call = Result.Nodes.getNodeAs<CallExpr>(ID: "free" ))) |
55 | Recommendation = "use RAII" ; |
56 | |
57 | assert(Call && "Unhandled binding in the Matcher" ); |
58 | |
59 | diag(Loc: Call->getBeginLoc(), Description: "do not manage memory manually; %0" ) |
60 | << Recommendation << SourceRange(Call->getBeginLoc(), Call->getEndLoc()); |
61 | } |
62 | |
63 | } // namespace clang::tidy::cppcoreguidelines |
64 | |