Index: clang-tidy/modernize/MakeSmartPtrCheck.cpp =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -29,13 +29,19 @@ 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); Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -85,6 +85,15 @@ Warns about the performance overhead arising from concatenating strings using the ``operator+``, instead of ``operator+=``. + +Fixed bugs: +- `modernize-make-unique + `_ + and `modernize-make-shared + `_ + 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 ----------------------------- Index: test/clang-tidy/modernize-make-shared.cpp =================================================================== --- test/clang-tidy/modernize-make-shared.cpp +++ test/clang-tidy/modernize-make-shared.cpp @@ -100,6 +100,38 @@ std::shared_ptr Placement = std::shared_ptr(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(new Private); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead + // CHECK-FIXES: auto callsPublic = std::make_shared(); + auto ptr = std::shared_ptr(new Private(42)); + } + + virtual ~Private(); +}; + +class Protected { +protected: + Protected() {} + +public: + Protected(int, int) {} + void create() { + auto callsPublic = std::shared_ptr(new Protected(1, 2)); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead + // CHECK-FIXES: auto callsPublic = std::make_shared(1, 2); + auto ptr = std::shared_ptr(new Protected); + } +}; + void initialization(int T, Base b) { // Test different kinds of initialization of the pointee. Index: test/clang-tidy/modernize-make-unique.cpp =================================================================== --- test/clang-tidy/modernize-make-unique.cpp +++ test/clang-tidy/modernize-make-unique.cpp @@ -103,6 +103,38 @@ std::unique_ptr Placement = std::unique_ptr(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(new Private); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead + // CHECK-FIXES: auto callsPublic = std::make_unique(); + auto ptr = std::unique_ptr(new Private(42)); + } + + virtual ~Private(); +}; + +class Protected { +protected: + Protected() {} + +public: + Protected(int, int) {} + void create() { + auto callsPublic = std::unique_ptr(new Protected(1, 2)); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead + // CHECK-FIXES: auto callsPublic = std::make_unique(1, 2); + auto ptr = std::unique_ptr(new Protected); + } +}; + void initialization(int T, Base b) { // Test different kinds of initialization of the pointee.