Author: alexfh Date: Tue Dec 13 10:38:18 2016 New Revision: 289546 URL: http://llvm.org/viewvc/llvm-project?rev=289546&view=rev Log: [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! Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.h clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-no-malloc.cpp Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/trunk/docs/ReleaseNotes.rst clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt?rev=289546&r1=289545&r2=289546&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt Tue Dec 13 10:38:18 2016 @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyCppCoreGuidelinesModule CppCoreGuidelinesTidyModule.cpp InterfacesGlobalInitCheck.cpp + NoMallocCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp ProBoundsConstantArrayIndexCheck.cpp ProBoundsPointerArithmeticCheck.cpp Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=289546&r1=289545&r2=289546&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp Tue Dec 13 10:38:18 2016 @@ -12,6 +12,7 @@ #include "../ClangTidyModuleRegistry.h" #include "../misc/UnconventionalAssignOperatorCheck.h" #include "InterfacesGlobalInitCheck.h" +#include "NoMallocCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" #include "ProBoundsConstantArrayIndexCheck.h" #include "ProBoundsPointerArithmeticCheck.h" @@ -35,6 +36,7 @@ public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck<InterfacesGlobalInitCheck>( "cppcoreguidelines-interfaces-global-init"); + CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc"); CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); CheckFactories.registerCheck<ProBoundsConstantArrayIndexCheck>( Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp?rev=289546&view=auto ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp (added) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp Tue Dec 13 10:38:18 2016 @@ -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 Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.h?rev=289546&view=auto ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.h (added) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/NoMallocCheck.h Tue Dec 13 10:38:18 2016 @@ -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 Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=289546&r1=289545&r2=289546&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original) +++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue Dec 13 10:38:18 2016 @@ -81,6 +81,10 @@ Improvements to clang-tidy Warns if an object is used after it has been moved, without an intervening reinitialization. +- New `cppcoreguidelines-no-malloc + <http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-no-malloc.html>`_ check + warns if C-style memory management is used and suggests the use of RAII. + - `modernize-make-unique <http://clang.llvm.org/extra/clang-tidy/checks/modernize-make-unique.html>`_ and `modernize-make-shared Added: clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst?rev=289546&view=auto ============================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst (added) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst Tue Dec 13 10:38:18 2016 @@ -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)); + Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=289546&r1=289545&r2=289546&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Tue Dec 13 10:38:18 2016 @@ -22,6 +22,7 @@ Clang-Tidy Checks cert-msc50-cpp cert-oop11-cpp (redirects to misc-move-constructor-init) <cert-oop11-cpp> cppcoreguidelines-interfaces-global-init + cppcoreguidelines-no-malloc cppcoreguidelines-pro-bounds-array-to-pointer-decay cppcoreguidelines-pro-bounds-constant-array-index cppcoreguidelines-pro-bounds-pointer-arithmetic Added: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-no-malloc.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-no-malloc.cpp?rev=289546&view=auto ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-no-malloc.cpp (added) +++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-no-malloc.cpp Tue Dec 13 10:38:18 2016 @@ -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) +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits