hokein updated this revision to Diff 109594. hokein marked 3 inline comments as done. hokein added a comment.
Address review comments https://reviews.llvm.org/D36016 Files: clang-tidy/modernize/MakeSmartPtrCheck.cpp test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h test/clang-tidy/modernize-make-unique.cpp
Index: test/clang-tidy/modernize-make-unique.cpp =================================================================== --- test/clang-tidy/modernize-make-unique.cpp +++ 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 <memory> struct Base { @@ -26,6 +27,22 @@ struct Empty {}; +struct E { + E(std::initializer_list<int>); + E(); +}; + +struct F { + F(std::initializer_list<int>); + F(); + int a; +}; + +struct G { + G(std::initializer_list<int>); + 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<Empty> PEmpty = std::make_unique<Empty>(Empty{}); + // Initialization with default constructor. + std::unique_ptr<E> PE1 = std::unique_ptr<E>(new E{}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<E> PE1 = std::make_unique<E>(); + + // Initialization with the initializer-list constructor. + std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<E> PE2 = std::make_unique<E>({1, 2}); + + // Initialization with default constructor. + std::unique_ptr<F> PF1 = std::unique_ptr<F>(new F()); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<F> PF1 = std::make_unique<F>(); + + // Initialization with default constructor. + std::unique_ptr<F> PF2 = std::unique_ptr<F>(new F{}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<F> PF2 = std::make_unique<F>(); + + // Initialization with the initializer-list constructor. + std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<F> PF3 = std::make_unique<F>({1}); + + // Initialization with the initializer-list constructor. + std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<F> PF4 = std::make_unique<F>({1, 2}); + + // Initialization with the initializer-list constructor. + std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2})); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<F> PF5 = std::make_unique<F>({1, 2}); + + // Initialization with the initializer-list constructor as the default + // constructor is not present. + std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<G> PG1 = std::make_unique<G>({}); + + // Initialization with the initializer-list constructor. + std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<G> PG2 = std::make_unique<G>({1}); + + // Initialization with the initializer-list constructor. + std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<G> PG3 = std::make_unique<G>({1, 2}); + std::unique_ptr<Foo> FF = std::unique_ptr<Foo>(new Foo()); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: // CHECK-FIXES: std::unique_ptr<Foo> FF = std::make_unique<Foo>(); Index: test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h @@ -0,0 +1,25 @@ +namespace std { +typedef decltype(sizeof(int)) size_t; + +template <class _E> 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-tidy/modernize/MakeSmartPtrCheck.cpp =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ 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<S>(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<S>(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<T>); }; + // smart_ptr<S>(new S{1, 2, 3}); + // smart_ptr<S>(new S{}); // use initializer-list consturctor + // The brace has to be kept, so this has to be replaced with: + // std::make_smart_ptr<S>({1, 2, 3}); + // std::make_smart_ptr<S>({}); + 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<S>(new S{5}); + // smart_ptr<S>(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<S>(5); + // std::make_smart_ptr<S>(); + InitRange = SourceRange( + NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1), + NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1)); + } } else { // Aggregate initialization. // smart_ptr<Pair>(new Pair{first, second});
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits