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 void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { 26 Options.store(Opts, "Allocations", AllocList); 27 Options.store(Opts, "Reallocations", ReallocList); 28 Options.store(Opts, "Deallocations", DeallocList); 29 } 30 31 void NoMallocCheck::registerMatchers(MatchFinder *Finder) { 32 // Registering malloc, will suggest RAII. 33 Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName( 34 utils::options::parseStringList(AllocList))))) 35 .bind("allocation"), 36 this); 37 38 // Registering realloc calls, suggest std::vector or std::string. 39 Finder->addMatcher( 40 callExpr(callee(functionDecl( 41 hasAnyName(utils::options::parseStringList((ReallocList)))))) 42 .bind("realloc"), 43 this); 44 45 // Registering free calls, will suggest RAII instead. 46 Finder->addMatcher( 47 callExpr(callee(functionDecl( 48 hasAnyName(utils::options::parseStringList((DeallocList)))))) 49 .bind("free"), 50 this); 51 } 52 53 void NoMallocCheck::check(const MatchFinder::MatchResult &Result) { 54 const CallExpr *Call = nullptr; 55 StringRef Recommendation; 56 57 if ((Call = Result.Nodes.getNodeAs<CallExpr>("allocation"))) 58 Recommendation = "consider a container or a smart pointer"; 59 else if ((Call = Result.Nodes.getNodeAs<CallExpr>("realloc"))) 60 Recommendation = "consider std::vector or std::string"; 61 else if ((Call = Result.Nodes.getNodeAs<CallExpr>("free"))) 62 Recommendation = "use RAII"; 63 64 assert(Call && "Unhandled binding in the Matcher"); 65 66 diag(Call->getBeginLoc(), "do not manage memory manually; %0") 67 << Recommendation << SourceRange(Call->getBeginLoc(), Call->getEndLoc()); 68 } 69 70 } // namespace cppcoreguidelines 71 } // namespace tidy 72 } // namespace clang 73