xref: /llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp (revision 7d2ea6c422d3f5712b7253407005e1a465a76946)
1ffbc2380SAlexander Kornienko //===--- NoMallocCheck.cpp - clang-tidy------------------------------------===//
2ebdfb9cfSAlexander Kornienko //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ebdfb9cfSAlexander Kornienko //
7ebdfb9cfSAlexander Kornienko //===----------------------------------------------------------------------===//
8ebdfb9cfSAlexander Kornienko 
9ebdfb9cfSAlexander Kornienko #include "NoMallocCheck.h"
10d993e76aSAlexander Kornienko #include "../utils/Matchers.h"
11d993e76aSAlexander Kornienko #include "../utils/OptionsUtils.h"
12ebdfb9cfSAlexander Kornienko #include "clang/AST/ASTContext.h"
13ebdfb9cfSAlexander Kornienko #include "clang/ASTMatchers/ASTMatchFinder.h"
14d993e76aSAlexander Kornienko #include <algorithm>
15ebdfb9cfSAlexander Kornienko #include <string>
16d993e76aSAlexander Kornienko #include <vector>
17ebdfb9cfSAlexander Kornienko 
18ebdfb9cfSAlexander Kornienko using namespace clang::ast_matchers;
19d993e76aSAlexander Kornienko using namespace clang::ast_matchers::internal;
20ebdfb9cfSAlexander Kornienko 
21*7d2ea6c4SCarlos Galvez namespace clang::tidy::cppcoreguidelines {
22ebdfb9cfSAlexander Kornienko 
storeOptions(ClangTidyOptions::OptionMap & Opts)23d993e76aSAlexander Kornienko void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
24d993e76aSAlexander Kornienko   Options.store(Opts, "Allocations", AllocList);
25d993e76aSAlexander Kornienko   Options.store(Opts, "Reallocations", ReallocList);
26d993e76aSAlexander Kornienko   Options.store(Opts, "Deallocations", DeallocList);
27d993e76aSAlexander Kornienko }
28d993e76aSAlexander Kornienko 
registerMatchers(MatchFinder * Finder)29ebdfb9cfSAlexander Kornienko void NoMallocCheck::registerMatchers(MatchFinder *Finder) {
30ebdfb9cfSAlexander Kornienko   // Registering malloc, will suggest RAII.
3112cb5405SNathan James   Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
3212cb5405SNathan James                                   utils::options::parseStringList(AllocList)))))
33d993e76aSAlexander Kornienko                          .bind("allocation"),
34ebdfb9cfSAlexander Kornienko                      this);
35ebdfb9cfSAlexander Kornienko 
36ebdfb9cfSAlexander Kornienko   // Registering realloc calls, suggest std::vector or std::string.
37ebdfb9cfSAlexander Kornienko   Finder->addMatcher(
3812cb5405SNathan James       callExpr(callee(functionDecl(
3912cb5405SNathan James                    hasAnyName(utils::options::parseStringList((ReallocList))))))
40d993e76aSAlexander Kornienko           .bind("realloc"),
41ebdfb9cfSAlexander Kornienko       this);
42ebdfb9cfSAlexander Kornienko 
43ebdfb9cfSAlexander Kornienko   // Registering free calls, will suggest RAII instead.
44ebdfb9cfSAlexander Kornienko   Finder->addMatcher(
4512cb5405SNathan James       callExpr(callee(functionDecl(
4612cb5405SNathan James                    hasAnyName(utils::options::parseStringList((DeallocList))))))
47d993e76aSAlexander Kornienko           .bind("free"),
48d993e76aSAlexander Kornienko       this);
49ebdfb9cfSAlexander Kornienko }
50ebdfb9cfSAlexander Kornienko 
check(const MatchFinder::MatchResult & Result)51ebdfb9cfSAlexander Kornienko void NoMallocCheck::check(const MatchFinder::MatchResult &Result) {
52ebdfb9cfSAlexander Kornienko   const CallExpr *Call = nullptr;
53ebdfb9cfSAlexander Kornienko   StringRef Recommendation;
54ebdfb9cfSAlexander Kornienko 
55d993e76aSAlexander Kornienko   if ((Call = Result.Nodes.getNodeAs<CallExpr>("allocation")))
56ebdfb9cfSAlexander Kornienko     Recommendation = "consider a container or a smart pointer";
57ebdfb9cfSAlexander Kornienko   else if ((Call = Result.Nodes.getNodeAs<CallExpr>("realloc")))
58ebdfb9cfSAlexander Kornienko     Recommendation = "consider std::vector or std::string";
59ebdfb9cfSAlexander Kornienko   else if ((Call = Result.Nodes.getNodeAs<CallExpr>("free")))
60ebdfb9cfSAlexander Kornienko     Recommendation = "use RAII";
61ebdfb9cfSAlexander Kornienko 
62ebdfb9cfSAlexander Kornienko   assert(Call && "Unhandled binding in the Matcher");
63ebdfb9cfSAlexander Kornienko 
6443465bf3SStephen Kelly   diag(Call->getBeginLoc(), "do not manage memory manually; %0")
65c09197e0SStephen Kelly       << Recommendation << SourceRange(Call->getBeginLoc(), Call->getEndLoc());
66ebdfb9cfSAlexander Kornienko }
67ebdfb9cfSAlexander Kornienko 
68*7d2ea6c4SCarlos Galvez } // namespace clang::tidy::cppcoreguidelines
69