Index: clang-tools-extra/trunk/clang-tidy/modernize/MakeSmartPtrCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -242,16 +242,33 @@ // Range of the substring that we do not want to remove. SourceRange InitRange; if (const auto *NewConstruct = New->getConstructExpr()) { - // Direct initialization with initialization list. - // struct S { S(int x) {} }; - // smart_ptr(new S{5}); - // The arguments in the initialization list are going to be forwarded to - // the constructor, so this has to be replaced with: - // struct S { S(int x) {} }; - // std::make_smart_ptr(5); - InitRange = SourceRange( - NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1), - NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1)); + if (NewConstruct->isStdInitListInitialization()) { + // Direct Initialization with the initializer-list constructor. + // struct S { S(std::initializer_list); }; + // smart_ptr(new S{1, 2, 3}); + // smart_ptr(new S{}); // use initializer-list consturctor + // The brace has to be kept, so this has to be replaced with: + // std::make_smart_ptr({1, 2, 3}); + // std::make_smart_ptr({}); + unsigned NumArgs = NewConstruct->getNumArgs(); + if (NumArgs == 0) { + return; + } + InitRange = SourceRange(NewConstruct->getArg(0)->getLocStart(), + NewConstruct->getArg(NumArgs - 1)->getLocEnd()); + } else { + // Direct initialization with ordinary constructors. + // struct S { S(int x); S(); }; + // smart_ptr(new S{5}); + // smart_ptr(new S{}); // use default constructor + // The arguments in the initialization list are going to be forwarded to + // the constructor, so this has to be replaced with: + // std::make_smart_ptr(5); + // std::make_smart_ptr(); + InitRange = SourceRange( + NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1), + NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1)); + } } else { // Aggregate initialization. // smart_ptr(new Pair{first, second}); Index: clang-tools-extra/trunk/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h +++ clang-tools-extra/trunk/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h @@ -0,0 +1,25 @@ +namespace std { +typedef decltype(sizeof(int)) size_t; + +template class initializer_list { + const _E *__begin_; + size_t __size_; + + initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {} + +public: + typedef _E value_type; + typedef const _E &reference; + typedef const _E &const_reference; + typedef size_t size_type; + + typedef const _E *iterator; + typedef const _E *const_iterator; + + initializer_list() : __begin_(nullptr), __size_(0) {} + + size_t size() const { return __size_; } + const _E *begin() const { return __begin_; } + const _E *end() const { return __begin_ + __size_; } +}; +} // namespace std Index: clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp +++ clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp @@ -2,6 +2,7 @@ // RUN: -I%S/Inputs/modernize-smart-ptr #include "unique_ptr.h" +#include "initializer_list.h" // CHECK-FIXES: #include struct Base { @@ -26,6 +27,22 @@ 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); +}; + namespace { class Foo {}; } // namespace @@ -225,6 +242,57 @@ // 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(); + + // 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::make_unique({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(); + + // 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(); + + // 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::make_unique({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::make_unique({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::make_unique({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::make_unique({}); + + // 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::make_unique({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::make_unique({1, 2}); + std::unique_ptr FF = std::unique_ptr(new Foo()); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: // CHECK-FIXES: std::unique_ptr FF = std::make_unique();