[clang-tools-extra] b0bab14 - [clang-tidy] Add check bugprone-unique-ptr-array-mismatch.

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Wed May 31 00:55:57 PDT 2023


Author: Balázs Kéri
Date: 2023-05-31T09:55:01+02:00
New Revision: b0bab14b8b5305ddcb4e8b4d8a0e64004fc5425e

URL: https://github.com/llvm/llvm-project/commit/b0bab14b8b5305ddcb4e8b4d8a0e64004fc5425e
DIFF: https://github.com/llvm/llvm-project/commit/b0bab14b8b5305ddcb4e8b4d8a0e64004fc5425e.diff

LOG: [clang-tidy] Add check bugprone-unique-ptr-array-mismatch.

Reviewed By: PiotrZSL

Differential Revision: https://reviews.llvm.org/D151431

Added: 
    clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.cpp
    clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.h
    clang-tools-extra/docs/clang-tidy/checks/bugprone/unique-ptr-array-mismatch.rst
    clang-tools-extra/test/clang-tidy/checkers/bugprone/unique-ptr-array-mismatch.cpp

Modified: 
    clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
    clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 5e9c7d0add4f8..e62e536555c29 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/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 @@ class BugproneModule : public ClangTidyModule {
         "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");

diff  --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e70d1b426a1c6..363d1a85b0ae5 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -69,6 +69,7 @@ add_clang_library(clangTidyBugproneModule
   UndelegatedConstructorCheck.cpp
   UnhandledExceptionAtNewCheck.cpp
   UnhandledSelfAssignmentCheck.cpp
+  UniquePtrArrayMismatchCheck.cpp
   UnsafeFunctionsCheck.cpp
   UnusedRaiiCheck.cpp
   UnusedReturnValueCheck.cpp

diff  --git a/clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.cpp
new file mode 100644
index 0000000000000..8d09b4b320c2c
--- /dev/null
+++ b/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

diff  --git a/clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.h b/clang-tools-extra/clang-tidy/bugprone/UniquePtrArrayMismatchCheck.h
new file mode 100644
index 0000000000000..fb7531ab146c6
--- /dev/null
+++ b/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

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b336cd2fc0e24..5e3c46cadde9f 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -121,6 +121,12 @@ New checks
   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.
 

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unique-ptr-array-mismatch.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unique-ptr-array-mismatch.rst
new file mode 100644
index 0000000000000..c00385954b23c
--- /dev/null
+++ b/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
+  std::unique_ptr<Foo> x1(new Foo), x2(new Foo[10]); // no replacement
+  //                                   ^ warning: unique pointer to non-array is initialized with array
+
+  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
+  };
+
+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.

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 055e6ae661f09..a13f841105f45 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -139,6 +139,7 @@ Clang-Tidy Checks
    `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>`_,

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unique-ptr-array-mismatch.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unique-ptr-array-mismatch.cpp
new file mode 100644
index 0000000000000..494e83dce3720
--- /dev/null
+++ b/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]
+}


        


More information about the cfe-commits mailing list