This revision was automatically updated to reflect the committed changes. Closed by commit rL347315: [clang-tidy] Don't generate incorrect fixes for class constructed from list… (authored by hokein, committed by ). Herald added a subscriber: llvm-commits.
Repository: rL LLVM https://reviews.llvm.org/D54704 Files: clang-tools-extra/trunk/clang-tidy/modernize/MakeSmartPtrCheck.cpp clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp
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 @@ -280,7 +280,27 @@ SM, getLangOpts()) .str(); } - + // Returns true if the given constructor expression has any braced-init-list + // argument, e.g. + // Foo({1, 2}, 1) => true + // Foo(Bar{1, 2}) => true + // Foo(1) => false + // Foo{1} => false + auto HasListIntializedArgument = [](const CXXConstructExpr *CE) { + for (const auto *Arg : CE->arguments()) { + if (isa<CXXStdInitializerListExpr>(Arg) || isa<InitListExpr>(Arg)) + return true; + // Check whether we implicitly construct a class from a + // std::initializer_list. + if (const auto *ImplicitCE = + dyn_cast<CXXConstructExpr>(Arg->IgnoreImplicit())) { + if (ImplicitCE->isStdInitListInitialization()) + return true; + } + return false; + } + return false; + }; switch (New->getInitializationStyle()) { case CXXNewExpr::NoInit: { if (ArraySizeExpr.empty()) { @@ -300,32 +320,20 @@ // std::make_smart_ptr, we need to specify the type explicitly in the fixes: // struct S { S(std::initializer_list<int>, int); }; // struct S2 { S2(std::vector<int>); }; + // struct S3 { S3(S2, int); }; // smart_ptr<S>(new S({1, 2, 3}, 1)); // C++98 call-style initialization // smart_ptr<S>(new S({}, 1)); // smart_ptr<S2>(new S2({1})); // implicit conversion: // // std::initializer_list => std::vector + // smart_ptr<S3>(new S3({1, 2}, 3)); // The above samples have to be replaced with: // std::make_smart_ptr<S>(std::initializer_list<int>({1, 2, 3}), 1); // std::make_smart_ptr<S>(std::initializer_list<int>({}), 1); // std::make_smart_ptr<S2>(std::vector<int>({1})); + // std::make_smart_ptr<S3>(S2{1, 2}, 3); if (const auto *CE = New->getConstructExpr()) { - for (const auto *Arg : CE->arguments()) { - if (isa<CXXStdInitializerListExpr>(Arg)) { - return false; - } - // Check whether we construct a class from a std::initializer_list. - // If so, we won't generate the fixes. - auto IsStdInitListInitConstructExpr = [](const Expr* E) { - assert(E); - if (const auto *ImplicitCE = dyn_cast<CXXConstructExpr>(E)) { - if (ImplicitCE->isStdInitListInitialization()) - return true; - } - return false; - }; - if (IsStdInitListInitConstructExpr(Arg->IgnoreImplicit())) - return false; - } + if (HasListIntializedArgument(CE)) + return false; } if (ArraySizeExpr.empty()) { SourceRange InitRange = New->getDirectInitRange(); @@ -346,16 +354,20 @@ // Range of the substring that we do not want to remove. SourceRange InitRange; if (const auto *NewConstruct = New->getConstructExpr()) { - if (NewConstruct->isStdInitListInitialization()) { + if (NewConstruct->isStdInitListInitialization() || + HasListIntializedArgument(NewConstruct)) { // FIXME: Add fixes for direct initialization with the initializer-list // constructor. Similar to the above CallInit case, the type has to be // specified explicitly in the fixes. // struct S { S(std::initializer_list<int>); }; + // struct S2 { S2(S, int); }; // smart_ptr<S>(new S{1, 2, 3}); // C++11 direct list-initialization // smart_ptr<S>(new S{}); // use initializer-list consturctor + // smart_ptr<S2>()new S2{ {1,2}, 3 }; // have a list-initialized arg // The above cases have to be replaced with: // std::make_smart_ptr<S>(std::initializer_list<int>({1, 2, 3})); // std::make_smart_ptr<S>(std::initializer_list<int>({})); + // std::make_smart_ptr<S2>(S{1, 2}, 3); return false; } else { // Direct initialization with ordinary constructors. 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 @@ -58,6 +58,10 @@ I(G); }; +struct J { + J(E e, int); +}; + namespace { class Foo {}; } // namespace @@ -372,6 +376,34 @@ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead // CHECK-FIXES: PI1 = std::make_unique<I>(G({1, 2, 3})); + std::unique_ptr<J> PJ1 = std::unique_ptr<J>(new J({1, 2}, 1)); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<J> PJ1 = std::unique_ptr<J>(new J({1, 2}, 1)); + PJ1.reset(new J({1, 2}, 1)); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead + // CHECK-FIXES: PJ1.reset(new J({1, 2}, 1)); + + std::unique_ptr<J> PJ2 = std::unique_ptr<J>(new J(E{1, 2}, 1)); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<J> PJ2 = std::make_unique<J>(E{1, 2}, 1); + PJ2.reset(new J(E{1, 2}, 1)); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead + // CHECK-FIXES: PJ2 = std::make_unique<J>(E{1, 2}, 1); + + std::unique_ptr<J> PJ3 = std::unique_ptr<J>(new J{ {1, 2}, 1 }); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<J> PJ3 = std::unique_ptr<J>(new J{ {1, 2}, 1 }); + PJ3.reset(new J{ {1, 2}, 1 }); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead + // CHECK-FIXES: PJ3.reset(new J{ {1, 2}, 1 }); + + std::unique_ptr<J> PJ4 = std::unique_ptr<J>(new J{E{1, 2}, 1}); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr<J> PJ4 = std::make_unique<J>(E{1, 2}, 1); + PJ4.reset(new J{E{1, 2}, 1}); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead + // CHECK-FIXES: PJ4 = std::make_unique<J>(E{1, 2}, 1); + 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>();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits