balazske updated this revision to Diff 526063. balazske marked an inline comment as done. balazske added a comment.
Fixed the documentation issue. Added tests. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D151431/new/ https://reviews.llvm.org/D151431 Files: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.cpp clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.h clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/bugprone/unique-ptr-array-mismatch.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/bugprone/unique-ptr-array-mismatch.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/unique-ptr-array-mismatch.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/unique-ptr-array-mismatch.cpp @@ -0,0 +1,127 @@ +// RUN: %check_clang_tidy %s bugprone-unique-ptr-array-mismatch %t + +namespace std { + +template<class T> struct default_delete {}; +template<class T> struct default_delete<T[]> {}; + +template<class T, class Deleter = std::default_delete<T>> +class unique_ptr { +public: + explicit unique_ptr(T* p) noexcept; + unique_ptr(T* p, Deleter d1 ) noexcept; +}; + +template <class T, class Deleter> +class unique_ptr<T[], Deleter> { +public: + template<class U> + explicit unique_ptr(U p) noexcept; + template<class U> + unique_ptr(U p, Deleter d1) noexcept; +}; + +} // namespace std + +struct A {}; + +using PtrT = std::unique_ptr<A>; +using PtrTArr = std::unique_ptr<A[]>; + +void f1() { + std::unique_ptr<int> P1{new int}; + std::unique_ptr<int> P2{new int[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-FIXES: std::unique_ptr<int[]> P2{new int[10]}; + // clang-format off + std::unique_ptr< int > P3{new int[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-FIXES: std::unique_ptr< int[] > P3{new int[10]}; + // clang-format on + std::unique_ptr<int> P4(new int[10]); + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-FIXES: std::unique_ptr<int[]> P4(new int[10]); + new std::unique_ptr<int>(new int[10]); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + std::unique_ptr<int[]> P5(new int[10]); + + A deleter; + std::unique_ptr<int, A> P6(new int[10], deleter); + std::unique_ptr<int, A> P7(new int[10]); + std::default_delete<int[]> def_del; + std::unique_ptr<int, std::default_delete<int[]>> P8(new int[10], def_del); + + new PtrT(new A[10]); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + new PtrTArr(new A[10]); +} + +void f2() { + std::unique_ptr<A> P1(new A); + std::unique_ptr<A> P2(new A[10]); + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-FIXES: std::unique_ptr<A[]> P2(new A[10]); + std::unique_ptr<A[]> P3(new A[10]); +} + +void f3() { + std::unique_ptr<int> P1{new int}, P2{new int[10]}, P3{new int[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-MESSAGES: :[[@LINE-2]]:57: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] +} + +struct S { + std::unique_ptr<int> P1; + std::unique_ptr<int> P2{new int[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + std::unique_ptr<int> P3{new int}, P4{new int[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + S() : P1{new int[10]} {} + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] +}; + +void f_parm(std::unique_ptr<int>); + +void f4() { + f_parm(std::unique_ptr<int>{new int[10]}); + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] +} + +std::unique_ptr<int> f_ret() { + return std::unique_ptr<int>(new int[10]); + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] +} + +template <class T> +void f_tmpl() { + std::unique_ptr<T> P1{new T[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-FIXES: std::unique_ptr<T[]> P1{new T[10]}; +} + +void f5() { + f_tmpl<char>(); +} + +template <class T> +void f_tmpl_1() { + std::unique_ptr<T> P1{new T[10]}; + // FIXME_CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // FIXME_CHECK-FIXES: std::unique_ptr<T[]> P1{new T[10]}; +} + +#define CHAR_PTR_TYPE std::unique_ptr<char> +#define CHAR_PTR_VAR(X) \ + X { new char[10] } +#define CHAR_PTR_INIT(X, Y) \ + std::unique_ptr<char> X { Y } + +void f6() { + CHAR_PTR_TYPE P1{new char[10]}; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + std::unique_ptr<char> CHAR_PTR_VAR(P2); + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + // CHECK-FIXES: std::unique_ptr<char[]> CHAR_PTR_VAR(P2); + CHAR_PTR_INIT(P3, new char[10]); + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] +} Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -139,6 +139,7 @@ `bugprone-undelegated-constructor <bugprone/undelegated-constructor.html>`_, `bugprone-unhandled-exception-at-new <bugprone/unhandled-exception-at-new.html>`_, `bugprone-unhandled-self-assignment <bugprone/unhandled-self-assignment.html>`_, + `bugprone-unique-ptr-array-mismatch <bugprone/unique-ptr-array-mismatch.html>`_, "Yes" `bugprone-unsafe-functions <bugprone/unsafe-functions.html>`_, `bugprone-unused-raii <bugprone/unused-raii.html>`_, "Yes" `bugprone-unused-return-value <bugprone/unused-return-value.html>`_, Index: clang-tools-extra/docs/clang-tidy/checks/bugprone/unique-ptr-array-mismatch.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/bugprone/unique-ptr-array-mismatch.rst @@ -0,0 +1,39 @@ +.. title:: clang-tidy - bugprone-unique-ptr-array-mismatch + +bugprone-unique-ptr-array-mismatch +================================== + +Finds initializations of C++ unique pointers to non-array type that are +initialized with an array. + +If a pointer ``std::unique_ptr<T>`` is initialized with a new-expression +``new T[]`` the memory is not deallocated correctly. A plain ``delete`` is used +in this case to deallocate the target memory. Instead a ``delete[]`` call is +needed. A ``std::unique_ptr<T[]>`` uses the correct delete operator. The check +does not emit warning if an ``unique_ptr`` with user-specified deleter type is +used. + +The check offers replacement of ``unique_ptr<T>`` to ``unique_ptr<T[]>`` if it +is used at a single variable declaration (one variable in one statement). + +Example: + +.. code-block:: c++ + + std::unique_ptr<Foo> x(new Foo[10]); // -> std::unique_ptr<Foo[]> x(new Foo[10]); + // ^ warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + std::unique_ptr<Foo> x1(new Foo), x2(new Foo[10]); // no replacement + // ^ warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + + D d; + std::unique_ptr<Foo, D> x3(new Foo[10], d); // no warning (custom deleter used) + + struct S { + std::unique_ptr<Foo> x(new Foo[10]); // no replacement in this case + // ^ warning: unique pointer to non-array is initialized with array [bugprone-unique-ptr-array-mismatch] + }; + +This check partially covers the CERT C++ Coding Standard rule +`MEM51-CPP. Properly deallocate dynamically allocated resources +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM51-CPP.+Properly+deallocate+dynamically+allocated+resources>`_ +However, only the ``std::unique_ptr`` case is detected by this check. Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -121,6 +121,12 @@ Detect implicit and explicit casts of ``enum`` type into ``bool`` where ``enum`` type doesn't have a zero-value enumerator. +- New :doc:`bugprone-unique-ptr-array-mismatch + <clang-tidy/checks/bugprone/unique-ptr-array-mismatch>` check. + + Finds initializations of C++ unique pointers to non-array type that are + initialized with an array. + - New :doc:`bugprone-unsafe-functions <clang-tidy/checks/bugprone/unsafe-functions>` check. Index: clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.h @@ -0,0 +1,34 @@ +//===--- UniquePtrArrayMismatchCheck.h - clang-tidy -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNIQUEPTRARRAYMISMATCHCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNIQUEPTRARRAYMISMATCHCHECK_H + +#include "SmartPtrArrayMismatchCheck.h" + +namespace clang::tidy::bugprone { + +/// Finds initializations of C++ unique pointers to non-array type that are +/// initialized with an array. +/// +/// Example: +/// +/// \code +/// std::unique_ptr<int> PtrArr{new int[10]}; +/// \endcode +class UniquePtrArrayMismatchCheck : public SmartPtrArrayMismatchCheck { +public: + UniquePtrArrayMismatchCheck(StringRef Name, ClangTidyContext *Context); + +protected: + SmartPtrClassMatcher getSmartPointerClassMatcher() const override; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNIQUEPTRARRAYMISMATCHCHECK_H Index: clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.cpp @@ -0,0 +1,33 @@ +//===--- UniquePtrArrayMismatchCheck.cpp - clang-tidy ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "UniquePtrArrayMismatchCheck.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +UniquePtrArrayMismatchCheck::UniquePtrArrayMismatchCheck( + StringRef Name, ClangTidyContext *Context) + : SmartPtrArrayMismatchCheck(Name, Context, "unique") {} + +UniquePtrArrayMismatchCheck::SmartPtrClassMatcher +UniquePtrArrayMismatchCheck::getSmartPointerClassMatcher() const { + auto DeleterDecl = classTemplateSpecializationDecl( + hasName("::std::default_delete"), templateArgumentCountIs(1), + hasTemplateArgument(0, templateArgument(refersToType( + qualType(equalsBoundNode(PointerTypeN)))))); + return classTemplateSpecializationDecl( + hasName("::std::unique_ptr"), templateArgumentCountIs(2), + hasTemplateArgument( + 0, templateArgument(refersToType(qualType().bind(PointerTypeN)))), + hasTemplateArgument(1, templateArgument(refersToType( + qualType(hasDeclaration(DeleterDecl)))))); +} + +} // namespace clang::tidy::bugprone Index: clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -69,6 +69,7 @@ UndelegatedConstructorCheck.cpp UnhandledExceptionAtNewCheck.cpp UnhandledSelfAssignmentCheck.cpp + UniquePtrArrayMismatchCheck.cpp UnsafeFunctionsCheck.cpp UnusedRaiiCheck.cpp UnusedReturnValueCheck.cpp Index: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -73,6 +73,7 @@ #include "UndelegatedConstructorCheck.h" #include "UnhandledExceptionAtNewCheck.h" #include "UnhandledSelfAssignmentCheck.h" +#include "UniquePtrArrayMismatchCheck.h" #include "UnsafeFunctionsCheck.h" #include "UnusedRaiiCheck.h" #include "UnusedReturnValueCheck.h" @@ -207,6 +208,8 @@ "bugprone-unhandled-self-assignment"); CheckFactories.registerCheck<UnhandledExceptionAtNewCheck>( "bugprone-unhandled-exception-at-new"); + CheckFactories.registerCheck<UniquePtrArrayMismatchCheck>( + "bugprone-unique-ptr-array-mismatch"); CheckFactories.registerCheck<UnsafeFunctionsCheck>( "bugprone-unsafe-functions"); CheckFactories.registerCheck<UnusedRaiiCheck>("bugprone-unused-raii");
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits