[clang-tidy] modernize-make-{smart_ptr} private ctor bugfix

Summary:
Bugfix for 27321. When the constructor of stored pointer
type is private then it is invalid to change it to
make_shared or make_unique.

Reviewers: alexfh, aaron.ballman, hokein

Subscribers: cfe-commits

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

llvm-svn: 280180
This commit is contained in:
Piotr Padlewski 2016-08-31 00:06:55 +00:00
parent 3f8f7840bf
commit d57be707b8
4 changed files with 79 additions and 1 deletions

View File

@ -29,13 +29,19 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus11)
return;
// Calling make_smart_ptr from within a member function of a type with a
// private or protected constructor would be ill-formed.
auto CanCallCtor = unless(has(ignoringImpCasts(cxxConstructExpr(
hasDeclaration(decl(unless(isPublic())))))));
Finder->addMatcher(
cxxBindTemporaryExpr(has(ignoringParenImpCasts(
cxxConstructExpr(
hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
hasArgument(0,
cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
equalsBoundNode(PointerType))))))
equalsBoundNode(PointerType))))),
CanCallCtor)
.bind(NewExpression)))
.bind(ConstructorCall)))),
this);

View File

@ -97,6 +97,14 @@ Improvements to clang-tidy
Flags function parameters of a pointer type that could be changed to point to
a constant type instead.
Fixed bugs:
- `modernize-make-unique
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-make-unique.html>`_
and `modernize-make-shared
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-make-shared.html>`_
Calling ``make_{unique|shared}`` from within a member function of a type
with a private or protected constructor would be ill-formed.
Improvements to include-fixer
-----------------------------

View File

@ -100,6 +100,38 @@ void basic() {
std::shared_ptr<int> Placement = std::shared_ptr<int>(new (PInt) int{3});
}
// Calling make_smart_ptr from within a member function of a type with a
// private or protected constructor would be ill-formed.
class Private {
private:
Private(int z) {}
public:
Private() {}
void create() {
auto callsPublic = std::shared_ptr<Private>(new Private);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
// CHECK-FIXES: auto callsPublic = std::make_shared<Private>();
auto ptr = std::shared_ptr<Private>(new Private(42));
}
virtual ~Private();
};
class Protected {
protected:
Protected() {}
public:
Protected(int, int) {}
void create() {
auto callsPublic = std::shared_ptr<Protected>(new Protected(1, 2));
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
// CHECK-FIXES: auto callsPublic = std::make_shared<Protected>(1, 2);
auto ptr = std::shared_ptr<Protected>(new Protected);
}
};
void initialization(int T, Base b) {
// Test different kinds of initialization of the pointee.

View File

@ -103,6 +103,38 @@ void basic() {
std::unique_ptr<int> Placement = std::unique_ptr<int>(new (PInt) int{3});
}
// Calling make_smart_ptr from within a member function of a type with a
// private or protected constructor would be ill-formed.
class Private {
private:
Private(int z) {}
public:
Private() {}
void create() {
auto callsPublic = std::unique_ptr<Private>(new Private);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
// CHECK-FIXES: auto callsPublic = std::make_unique<Private>();
auto ptr = std::unique_ptr<Private>(new Private(42));
}
virtual ~Private();
};
class Protected {
protected:
Protected() {}
public:
Protected(int, int) {}
void create() {
auto callsPublic = std::unique_ptr<Protected>(new Protected(1, 2));
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
// CHECK-FIXES: auto callsPublic = std::make_unique<Protected>(1, 2);
auto ptr = std::unique_ptr<Protected>(new Protected);
}
};
void initialization(int T, Base b) {
// Test different kinds of initialization of the pointee.