diff options
author | Jakub Kuderski <kubakuderski@gmail.com> | 2017-05-22 01:56:33 +0000 |
---|---|---|
committer | Jakub Kuderski <kubakuderski@gmail.com> | 2017-05-22 01:56:33 +0000 |
commit | b957708c5fdeebef68d3c26ad7c7d28fef715d66 (patch) | |
tree | 8aeed14d9d6366a161b8a49484bb094fe4538683 | |
parent | d1c23f71840980fabc4ed38625989841afe0fd54 (diff) |
[clang-tidy] Fix PR32896, PR33058: detect initializer lists in modernize-use-empalcerelease_40
Summary:
The patch is backported from: r302281 to fix the 4.0.1 release blocker PR33058.
This patch fixes [[ https://bugs.llvm.org/show_bug.cgi?id=32896 | PR32896 ]].
The problem was that modernize-use-emplace incorrectly removed changed push_back into emplace_back, removing explicit constructor call with initializer list parameter, resulting in compiler error after applying fixits.
modernize-use-emplace used to check if matched constructor had InitListExpr, but didn't check against CXXStdInitializerListExpr.
Eg.
```
std::vector<std::vector<int>> v;
v.push_back(std::vector<int>({1})); // --> v.emplace_back({1});
```
Reviewers: Prazek, alexfh, aaron.ballman
Reviewed By: Prazek, alexfh, aaron.ballman
Subscribers: xazax.hun, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D32767
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/branches/release_40@303524 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | clang-tidy/modernize/UseEmplaceCheck.cpp | 14 | ||||
-rw-r--r-- | test/clang-tidy/modernize-use-emplace.cpp | 23 |
2 files changed, 36 insertions, 1 deletions
diff --git a/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tidy/modernize/UseEmplaceCheck.cpp index 4084454c..214354f9 100644 --- a/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -20,6 +20,14 @@ static const auto DefaultContainersWithPushBack = static const auto DefaultSmartPointers = "::std::shared_ptr; ::std::unique_ptr; ::std::auto_ptr; ::std::weak_ptr"; +namespace { +namespace impl { +// FIXME: This matcher should be replaced by a matcher from ASTMatcher.h +const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, + CXXStdInitializerListExpr> cxxStdInitializerListExpr; +} // namespace impl +} // namespace + UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), ContainersWithPushBack(utils::options::parseStringList(Options.get( @@ -69,7 +77,11 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { // emplace_back can't access private constructor. auto isPrivateCtor = hasDeclaration(cxxConstructorDecl(isPrivate())); - auto hasInitList = has(ignoringImplicit(initListExpr())); + auto hasInitList = anyOf(has(ignoringImplicit(initListExpr())), + has(impl::cxxStdInitializerListExpr())); + // FIXME: Replace internal C++ initializer list matcher with one from + // ASTMatchers.h + // FIXME: Discard 0/NULL (as nullptr), static inline const data members, // overloaded functions and template names. auto soughtConstructExpr = diff --git a/test/clang-tidy/modernize-use-emplace.cpp b/test/clang-tidy/modernize-use-emplace.cpp index a82a3a5b..403022f0 100644 --- a/test/clang-tidy/modernize-use-emplace.cpp +++ b/test/clang-tidy/modernize-use-emplace.cpp @@ -4,9 +4,19 @@ // RUN: value: '::std::vector; ::std::list; ::std::deque; llvm::LikeASmallVector'}]}" -- -std=c++11 namespace std { +template <typename> +class initializer_list +{ +public: + initializer_list() noexcept {} +}; + template <typename T> class vector { public: + vector() = default; + vector(initializer_list<T>) {} + void push_back(const T &) {} void push_back(T &&) {} @@ -422,3 +432,16 @@ void testWithDtor() { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(42); } + +void testInitializerList() { + std::vector<std::vector<int>> v; + v.push_back(std::vector<int>({1})); + // Test against the bug reported in PR32896. + + v.push_back({{2}}); + + using PairIntVector = std::pair<int, std::vector<int>>; + std::vector<PairIntVector> x; + x.push_back(PairIntVector(3, {4})); + x.push_back({5, {6}}); +} |