1 //===--- NoMallocCheck.cpp - clang-tidy------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "NoMallocCheck.h" 11 #include "../utils/Matchers.h" 12 #include "../utils/OptionsUtils.h" 13 #include "clang/AST/ASTContext.h" 14 #include "clang/ASTMatchers/ASTMatchFinder.h" 15 #include <algorithm> 16 #include <string> 17 #include <vector> 18 19 using namespace clang::ast_matchers; 20 using namespace clang::ast_matchers::internal; 21 22 namespace clang { 23 namespace tidy { 24 namespace cppcoreguidelines { 25 26 namespace { 27 Matcher<FunctionDecl> hasAnyListedName(const std::string &FunctionNames) { 28 const std::vector<std::string> NameList = 29 utils::options::parseStringList(FunctionNames); 30 return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end())); 31 } 32 } // namespace 33 34 void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { 35 Options.store(Opts, "Allocations", AllocList); 36 Options.store(Opts, "Reallocations", ReallocList); 37 Options.store(Opts, "Deallocations", DeallocList); 38 } 39 40 void NoMallocCheck::registerMatchers(MatchFinder *Finder) { 41 // C-style memory management is only problematic in C++. 42 if (!getLangOpts().CPlusPlus) 43 return; 44 45 // Registering malloc, will suggest RAII. 46 Finder->addMatcher(callExpr(callee(functionDecl(hasAnyListedName(AllocList)))) 47 .bind("allocation"), 48 this); 49 50 // Registering realloc calls, suggest std::vector or std::string. 51 Finder->addMatcher( 52 callExpr(callee(functionDecl(hasAnyListedName(ReallocList)))) 53 .bind("realloc"), 54 this); 55 56 // Registering free calls, will suggest RAII instead. 57 Finder->addMatcher( 58 callExpr(callee(functionDecl(hasAnyListedName(DeallocList)))) 59 .bind("free"), 60 this); 61 } 62 63 void NoMallocCheck::check(const MatchFinder::MatchResult &Result) { 64 const CallExpr *Call = nullptr; 65 StringRef Recommendation; 66 67 if ((Call = Result.Nodes.getNodeAs<CallExpr>("allocation"))) 68 Recommendation = "consider a container or a smart pointer"; 69 else if ((Call = Result.Nodes.getNodeAs<CallExpr>("realloc"))) 70 Recommendation = "consider std::vector or std::string"; 71 else if ((Call = Result.Nodes.getNodeAs<CallExpr>("free"))) 72 Recommendation = "use RAII"; 73 74 assert(Call && "Unhandled binding in the Matcher"); 75 76 diag(Call->getLocStart(), "do not manage memory manually; %0") 77 << Recommendation << SourceRange(Call->getLocStart(), Call->getLocEnd()); 78 } 79 80 } // namespace cppcoreguidelines 81 } // namespace tidy 82 } // namespace clang 83