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