// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++11 \ // RUN: -I%S/Inputs/modernize-smart-ptr #include "unique_ptr.h" #include "initializer_list.h" // CHECK-FIXES: #include struct Base { Base(); Base(int, int); }; struct Derived : public Base { Derived(); Derived(int, int); }; struct APair { int a, b; }; struct DPair { DPair() : a(0), b(0) {} DPair(int x, int y) : a(y), b(x) {} int a, b; }; struct Empty {}; struct E { E(std::initializer_list); E(); }; struct F { F(std::initializer_list); F(); int a; }; struct G { G(std::initializer_list); G(int); }; struct H { H(std::vector); }; struct I { I(G); }; namespace { class Foo {}; } // namespace namespace bar { class Bar {}; } // namespace bar template using unique_ptr_ = std::unique_ptr; void *operator new(__SIZE_TYPE__ Count, void *Ptr); int g(std::unique_ptr P); std::unique_ptr getPointer() { return std::unique_ptr(new Base); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead // CHECK-FIXES: return std::make_unique(); } void basic() { std::unique_ptr P1 = std::unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: std::unique_ptr P1 = std::make_unique(); P1.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P1 = std::make_unique(); P1 = std::unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P1 = std::make_unique(); // Without parenthesis. std::unique_ptr P2 = std::unique_ptr(new int); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: std::unique_ptr P2 = std::make_unique(); P2.reset(new int); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P2 = std::make_unique(); P2 = std::unique_ptr(new int); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P2 = std::make_unique(); // With auto. auto P3 = std::unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead // CHECK-FIXES: auto P3 = std::make_unique(); { // No std. using namespace std; unique_ptr Q = unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead // CHECK-FIXES: unique_ptr Q = std::make_unique(); Q = unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: Q = std::make_unique(); } std::unique_ptr R(new int()); // Create the unique_ptr as a parameter to a function. int T = g(std::unique_ptr(new int())); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead // CHECK-FIXES: int T = g(std::make_unique()); // Only replace if the type in the template is the same as the type returned // by the new operator. auto Pderived = std::unique_ptr(new Derived()); // OK to replace for reset and assign Pderived.reset(new Derived()); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead // CHECK-FIXES: Pderived = std::make_unique(); Pderived = std::unique_ptr(new Derived()); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_unique instead // CHECK-FIXES: Pderived = std::make_unique(); // FIXME: OK to replace if assigned to unique_ptr Pderived = std::unique_ptr(new Derived()); // FIXME: OK to replace when auto is not used std::unique_ptr PBase = std::unique_ptr(new Derived()); // The pointer is returned by the function, nothing to do. std::unique_ptr RetPtr = getPointer(); // This emulates std::move. std::unique_ptr Move = static_cast &&>(P1); // Placement arguments should not be removed. int *PInt = new int; std::unique_ptr Placement = std::unique_ptr(new (PInt) int{3}); Placement.reset(new (PInt) int{3}); 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)); ptr.reset(new Private(42)); 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); ptr.reset(new Protected); ptr = std::unique_ptr(new Protected); } }; void initialization(int T, Base b) { // Test different kinds of initialization of the pointee. // Direct initialization with parenthesis. std::unique_ptr PDir1 = std::unique_ptr(new DPair(1, T)); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PDir1 = std::make_unique(1, T); PDir1.reset(new DPair(1, T)); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: PDir1 = std::make_unique(1, T); // Direct initialization with braces. std::unique_ptr PDir2 = std::unique_ptr(new DPair{2, T}); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PDir2 = std::make_unique(2, T); PDir2.reset(new DPair{2, T}); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: PDir2 = std::make_unique(2, T); // Aggregate initialization. std::unique_ptr PAggr = std::unique_ptr(new APair{T, 1}); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PAggr = std::make_unique(APair{T, 1}); PAggr.reset(new APair{T, 1}); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: std::make_unique(APair{T, 1}); // Test different kinds of initialization of the pointee, when the unique_ptr // is initialized with braces. // Direct initialization with parenthesis. std::unique_ptr PDir3 = std::unique_ptr{new DPair(3, T)}; // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PDir3 = std::make_unique(3, T); // Direct initialization with braces. std::unique_ptr PDir4 = std::unique_ptr{new DPair{4, T}}; // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PDir4 = std::make_unique(4, T); // Aggregate initialization. std::unique_ptr PAggr2 = std::unique_ptr{new APair{T, 2}}; // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PAggr2 = std::make_unique(APair{T, 2}); // Direct initialization with parenthesis, without arguments. std::unique_ptr PDir5 = std::unique_ptr(new DPair()); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PDir5 = std::make_unique(); // Direct initialization with braces, without arguments. std::unique_ptr PDir6 = std::unique_ptr(new DPair{}); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PDir6 = std::make_unique(); // Aggregate initialization without arguments. std::unique_ptr PEmpty = std::unique_ptr(new Empty{}); // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PEmpty = std::make_unique(Empty{}); // Initialization with default constructor. std::unique_ptr PE1 = std::unique_ptr(new E{}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PE1 = std::make_unique(); PE1.reset(new E{}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PE1 = std::make_unique(); //============================================================================ // NOTE: For initlializer-list constructors, the check only gives warnings, // and no fixes are generated. //============================================================================ // Initialization with the initializer-list constructor. std::unique_ptr PE2 = std::unique_ptr(new E{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PE2 = std::unique_ptr(new E{1, 2}); PE2.reset(new E{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PE2.reset(new E{1, 2}); // Initialization with default constructor. std::unique_ptr PF1 = std::unique_ptr(new F()); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PF1 = std::make_unique(); PF1.reset(new F()); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PF1 = std::make_unique(); // Initialization with default constructor. std::unique_ptr PF2 = std::unique_ptr(new F{}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PF2 = std::make_unique(); PF2.reset(new F()); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PF2 = std::make_unique(); // Initialization with the initializer-list constructor. std::unique_ptr PF3 = std::unique_ptr(new F{1}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PF3 = std::unique_ptr(new F{1}); PF3.reset(new F{1}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PF3.reset(new F{1}); // Initialization with the initializer-list constructor. std::unique_ptr PF4 = std::unique_ptr(new F{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PF4 = std::unique_ptr(new F{1, 2}); // Initialization with the initializer-list constructor. std::unique_ptr PF5 = std::unique_ptr(new F({1, 2})); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PF5 = std::unique_ptr(new F({1, 2})); // Initialization with the initializer-list constructor as the default // constructor is not present. std::unique_ptr PG1 = std::unique_ptr(new G{}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PG1 = std::unique_ptr(new G{}); PG1.reset(new G{}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PG1.reset(new G{}); // Initialization with the initializer-list constructor. std::unique_ptr PG2 = std::unique_ptr(new G{1}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PG2 = std::unique_ptr(new G{1}); // Initialization with the initializer-list constructor. std::unique_ptr PG3 = std::unique_ptr(new G{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PG3 = std::unique_ptr(new G{1, 2}); std::unique_ptr PH1 = std::unique_ptr(new H({1, 2, 3})); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PH1 = std::unique_ptr(new H({1, 2, 3})); PH1.reset(new H({1, 2, 3})); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PH1.reset(new H({1, 2, 3})); std::unique_ptr PI1 = std::unique_ptr(new I(G({1, 2, 3}))); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr PI1 = std::make_unique(G({1, 2, 3})); PI1.reset(new I(G({1, 2, 3}))); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PI1 = std::make_unique(G({1, 2, 3})); std::unique_ptr FF = std::unique_ptr(new Foo()); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: // CHECK-FIXES: std::unique_ptr FF = std::make_unique(); FF.reset(new Foo()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: FF = std::make_unique(); std::unique_ptr BB = std::unique_ptr(new bar::Bar()); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: // CHECK-FIXES: std::unique_ptr BB = std::make_unique(); BB.reset(new bar::Bar()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: BB = std::make_unique(); std::unique_ptr FFs; FFs.reset(new Foo[5]); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: // CHECK-FIXES: FFs = std::make_unique(5); FFs.reset(new Foo[5]()); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: // CHECK-FIXES: FFs = std::make_unique(5); const int Num = 1; FFs.reset(new Foo[Num]); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: // CHECK-FIXES: FFs = std::make_unique(Num); int Num2 = 1; FFs.reset(new Foo[Num2]); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: // CHECK-FIXES: FFs = std::make_unique(Num2); std::unique_ptr FI; FI.reset(new int[5]); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: FI = std::make_unique(5); FI.reset(new int[5]()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: FI = std::make_unique(5); FI.reset(new int[Num]); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: FI = std::make_unique(Num); FI.reset(new int[Num2]); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: FI = std::make_unique(Num2); } void aliases() { typedef std::unique_ptr IntPtr; IntPtr Typedef = IntPtr(new int); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead // CHECK-FIXES: IntPtr Typedef = std::make_unique(); // We use 'bool' instead of '_Bool'. typedef std::unique_ptr BoolPtr; BoolPtr BoolType = BoolPtr(new bool); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_unique instead // CHECK-FIXES: BoolPtr BoolType = std::make_unique(); // We use 'Base' instead of 'struct Base'. typedef std::unique_ptr BasePtr; BasePtr StructType = BasePtr(new Base); // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead // CHECK-FIXES: BasePtr StructType = std::make_unique(); #define PTR unique_ptr std::unique_ptr Macro = std::PTR(new int); // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr Macro = std::make_unique(); #undef PTR std::unique_ptr Using = unique_ptr_(new int); // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr Using = std::make_unique(); } void whitespaces() { // clang-format off auto Space = std::unique_ptr (new int()); // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead // CHECK-FIXES: auto Space = std::make_unique(); auto Spaces = std :: unique_ptr (new int()); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead // CHECK-FIXES: auto Spaces = std::make_unique(); // clang-format on } void nesting() { auto Nest = std::unique_ptr>(new std::unique_ptr(new int)); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use std::make_unique instead // CHECK-FIXES: auto Nest = std::make_unique>(new int); Nest.reset(new std::unique_ptr(new int)); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead // CHECK-FIXES: Nest = std::make_unique>(new int); Nest->reset(new int); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: *Nest = std::make_unique(); } void reset() { std::unique_ptr P; P.reset(); P.reset(nullptr); P.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_unique instead // CHECK-FIXES: P = std::make_unique(); auto Q = &P; Q->reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead // CHECK-FIXES: *Q = std::make_unique(); } #define DEFINE(...) __VA_ARGS__ template void g2(std::unique_ptr *t) { DEFINE(auto p = std::unique_ptr(new Foo); t->reset(new Foo);); } void macro() { std::unique_ptr *t; g2(t); } #undef DEFINE class UniqueFoo : public std::unique_ptr { public: void foo() { reset(new Foo); this->reset(new Foo); // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::make_unique instead // CHECK-FIXES: *this = std::make_unique(); (*this).reset(new Foo); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead // CHECK-FIXES: (*this) = std::make_unique(); } }; // Ignore statements inside a template instantiation. template void template_fun(T* t) { std::unique_ptr t2 = std::unique_ptr(new T); t2.reset(new T); } void invoke_template() { Foo* foo; template_fun(foo); }