[clang-tidy] Add check bugprone-unique-ptr-array-mismatch.
Reviewed By: PiotrZSL Differential Revision: https://reviews.llvm.org/D151431
This commit is contained in:
@@ -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 @@ public:
|
||||
"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");
|
||||
|
||||
@@ -69,6 +69,7 @@ add_clang_library(clangTidyBugproneModule
|
||||
UndelegatedConstructorCheck.cpp
|
||||
UnhandledExceptionAtNewCheck.cpp
|
||||
UnhandledSelfAssignmentCheck.cpp
|
||||
UniquePtrArrayMismatchCheck.cpp
|
||||
UnsafeFunctionsCheck.cpp
|
||||
UnusedRaiiCheck.cpp
|
||||
UnusedReturnValueCheck.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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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>`_,
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
Reference in New Issue
Block a user