-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Clang-tidy] check for malloc, realloc and free calls
Summary: This checker flags the use of C-style memory management functionality and notes about modern alternatives. In an earlier revision it tried to autofix some kind of patterns, but that was a bad idea. Since memory management can be so widespread in a program, manual updating is most likely necessary. Maybe for special cases, there could be later additions to this basic checker. This is the first checker I wrote and I never did something with clang (only compiling programs). So whenever I missed conventions or did plain retarded stuff, feel free to point it out! I am willing to fix them and write a better checker. I hope the patch does work, I never did this either. On a testapply in my repository it did, but I am pretty unconfident in my patching skills :) Reviewers: aaron.ballman, hokein, alexfh, malcolm.parsons Subscribers: cfe-commits, JDevlieghere, nemanjai, Eugene.Zelenko, Prazek, mgorny, modocache Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D26167 Patch by Jonas Toth! llvm-svn: 289546
- Loading branch information
Showing
8 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
//===--- NoMallocCheck.cpp - clang-tidy------------------------------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "NoMallocCheck.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/ASTMatchers/ASTMatchFinder.h" | ||
#include <iostream> | ||
#include <string> | ||
|
||
using namespace clang::ast_matchers; | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace cppcoreguidelines { | ||
|
||
void NoMallocCheck::registerMatchers(MatchFinder *Finder) { | ||
// C-style memory management is only problematic in C++. | ||
if (!getLangOpts().CPlusPlus) | ||
return; | ||
|
||
// Registering malloc, will suggest RAII. | ||
Finder->addMatcher( | ||
callExpr(callee(functionDecl(hasAnyName("::malloc", "::calloc")))) | ||
.bind("aquisition"), | ||
this); | ||
|
||
// Registering realloc calls, suggest std::vector or std::string. | ||
Finder->addMatcher( | ||
callExpr(callee(functionDecl(hasName("::realloc")))).bind("realloc"), | ||
this); | ||
|
||
// Registering free calls, will suggest RAII instead. | ||
Finder->addMatcher( | ||
callExpr(callee(functionDecl(hasName("::free")))).bind("free"), this); | ||
} | ||
|
||
void NoMallocCheck::check(const MatchFinder::MatchResult &Result) { | ||
const CallExpr *Call = nullptr; | ||
StringRef Recommendation; | ||
|
||
if ((Call = Result.Nodes.getNodeAs<CallExpr>("aquisition"))) | ||
Recommendation = "consider a container or a smart pointer"; | ||
else if ((Call = Result.Nodes.getNodeAs<CallExpr>("realloc"))) | ||
Recommendation = "consider std::vector or std::string"; | ||
else if ((Call = Result.Nodes.getNodeAs<CallExpr>("free"))) | ||
Recommendation = "use RAII"; | ||
|
||
assert(Call && "Unhandled binding in the Matcher"); | ||
|
||
diag(Call->getLocStart(), "do not manage memory manually; %0") | ||
<< Recommendation << SourceRange(Call->getLocStart(), Call->getLocEnd()); | ||
} | ||
|
||
} // namespace cppcoreguidelines | ||
} // namespace tidy | ||
} // namespace clang |
44 changes: 44 additions & 0 deletions
44
clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
//===--- NoMallocCheck.h - clang-tidy----------------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NO_MALLOC_H | ||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NO_MALLOC_H | ||
|
||
#include "../ClangTidy.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/ASTMatchers/ASTMatchFinder.h" | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace cppcoreguidelines { | ||
|
||
/// This checker is concerned with C-style memory management and suggest modern | ||
/// alternatives to it. | ||
/// The check is only enabled in C++. For analyzing malloc calls see Clang | ||
/// Static Analyzer - unix.Malloc. | ||
/// | ||
/// For the user-facing documentation see: | ||
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-no-malloc.html | ||
class NoMallocCheck : public ClangTidyCheck { | ||
public: | ||
NoMallocCheck(StringRef Name, ClangTidyContext *Context) | ||
: ClangTidyCheck(Name, Context) {} | ||
|
||
/// Registering for malloc, calloc, realloc and free calls. | ||
void registerMatchers(ast_matchers::MatchFinder *Finder) override; | ||
|
||
/// Checks matched function calls and gives suggestion to modernize the code. | ||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override; | ||
}; | ||
|
||
} // namespace cppcoreguidelines | ||
} // namespace tidy | ||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NO_MALLOC_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.. title:: clang-tidy - cppcoreguidelines-no-malloc | ||
|
||
cppcoreguidelines-no-malloc | ||
=========================== | ||
|
||
This check handles C-Style memory management using ``malloc()``, ``realloc()``, | ||
``calloc()`` and ``free()``. It warns about its use and tries to suggest the use | ||
of an appropriate RAII object. | ||
See `C++ Core Guidelines | ||
<https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rr-mallocfree> | ||
|
||
There is no attempt made to provide fixit hints, since manual resource management isn't | ||
easily transformed automatically into RAII. | ||
|
||
.. code-block:: c++ | ||
|
||
// Warns each of the following lines. | ||
// Containers like std::vector or std::string should be used. | ||
char* some_string = (char*) malloc(sizeof(char) * 20); | ||
char* some_string = (char*) realloc(sizeof(char) * 30); | ||
free(some_string); | ||
|
||
int* int_array = (int*) calloc(30, sizeof(int)); | ||
|
||
// Rather use a smartpointer or stack variable. | ||
struct some_struct* s = (struct some_struct*) malloc(sizeof(struct some_struct)); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t | ||
|
||
using size_t = unsigned long; | ||
|
||
void *malloc(size_t size); | ||
void *calloc(size_t num, size_t size); | ||
void *realloc(void *ptr, size_t size); | ||
void free(void *ptr); | ||
|
||
void malloced_array() { | ||
int *array0 = (int *)malloc(sizeof(int) * 20); | ||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc] | ||
|
||
int *zeroed = (int *)calloc(20, sizeof(int)); | ||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc] | ||
|
||
// reallocation memory, std::vector shall be used | ||
char *realloced = (char *)realloc(array0, 50 * sizeof(int)); | ||
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc] | ||
|
||
// freeing memory the bad way | ||
free(realloced); | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc] | ||
|
||
// check if a call to malloc as function argument is found as well | ||
free(malloc(20)); | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc] | ||
// CHECK-MESSAGES: :[[@LINE-2]]:8: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc] | ||
} | ||
|
||
/// newing an array is still not good, but not relevant to this checker | ||
void newed_array() { | ||
int *new_array = new int[10]; // OK(1) | ||
} | ||
|
||
void arbitrary_call() { | ||
// we dont want every function to raise the warning even if malloc is in the name | ||
malloced_array(); // OK(2) | ||
|
||
// completly unrelated function call to malloc | ||
newed_array(); // OK(3) | ||
} |