kuhar created this revision.
kuhar added a project: clang-tools-extra.

This patch prevents modernize-use-emplace from changing push_backs of brace 
initialized pairs (`.push_back({1, 2})`) to `.emplace_back(1, 2)`.
Pair's constructor doesn't have any interesting logic and basically performs 
aggregate initialization. There also doesn't seem to be much win
in terms of making code more concise, thus is makes little sense to turn such 
push_back calls into emplace_backs.

The change is inspired by the recent discussion on changing and enforcing 
coding guidelines:
[llvm-dev] [cfe-dev] Modernizing LLVM Coding Style Guide and    enforcing 
Clang-tidy
http://lists.llvm.org/pipermail/llvm-dev/2016-December/108559.html


https://reviews.llvm.org/D32313

Files:
  clang-tidy/modernize/UseEmplaceCheck.cpp
  clang-tidy/modernize/UseEmplaceCheck.h
  test/clang-tidy/modernize-use-emplace.cpp


Index: test/clang-tidy/modernize-use-emplace.cpp
===================================================================
--- test/clang-tidy/modernize-use-emplace.cpp
+++ test/clang-tidy/modernize-use-emplace.cpp
@@ -186,6 +186,11 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
   // CHECK-FIXES: v.emplace_back(1, 2);
 
+  v.push_back({1, 2});
+  v.push_back(std::pair<int, int>{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
   GetPair g;
   v.push_back(g.getPair());
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
Index: clang-tidy/modernize/UseEmplaceCheck.h
===================================================================
--- clang-tidy/modernize/UseEmplaceCheck.h
+++ clang-tidy/modernize/UseEmplaceCheck.h
@@ -35,6 +35,7 @@
 private:
   std::vector<std::string> ContainersWithPushBack;
   std::vector<std::string> SmartPointers;
+  std::vector<std::string> PairTypes;
 };
 
 } // namespace modernize
Index: clang-tidy/modernize/UseEmplaceCheck.cpp
===================================================================
--- clang-tidy/modernize/UseEmplaceCheck.cpp
+++ clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -19,13 +19,16 @@
     "::std::vector; ::std::list; ::std::deque";
 static const auto DefaultSmartPointers =
     "::std::shared_ptr; ::std::unique_ptr; ::std::auto_ptr; ::std::weak_ptr";
+static const auto DefaultPairTypes = "::std::pair";
 
 UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       ContainersWithPushBack(utils::options::parseStringList(Options.get(
           "ContainersWithPushBack", DefaultContainersWithPushBack))),
       SmartPointers(utils::options::parseStringList(
-          Options.get("SmartPointers", DefaultSmartPointers))) {}
+          Options.get("SmartPointers", DefaultSmartPointers))),
+      PairTypes(utils::options::parseStringList(
+          Options.get("PairTypes", DefaultPairTypes))) {}
 
 void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus11)
@@ -72,11 +75,19 @@
   auto hasInitList = has(ignoringImplicit(initListExpr()));
   // FIXME: Discard 0/NULL (as nullptr), static inline const data members,
   // overloaded functions and template names.
+
+  // Ignore push_back({first, second}) for pair types (eg. std::pair).
+  auto isPairBraceInit = expr(allOf(cxxConstructExpr(hasDeclaration(
+      cxxConstructorDecl(ofClass(hasAnyName(SmallVector<StringRef, 2>(
+          PairTypes.begin(), PairTypes.end())))))),
+                                    unless(cxxTemporaryObjectExpr())),
+                              unless(hasParent(implicitCastExpr())));
+
   auto soughtConstructExpr =
       cxxConstructExpr(
           unless(anyOf(isCtorOfSmartPtr, hasInitList, bitFieldAsArgument,
                        initializerListAsArgument, newExprAsArgument,
-                       constructingDerived, isPrivateCtor)))
+                       constructingDerived, isPrivateCtor, isPairBraceInit)))
           .bind("ctor");
   auto hasConstructExpr = has(ignoringImplicit(soughtConstructExpr));
 


Index: test/clang-tidy/modernize-use-emplace.cpp
===================================================================
--- test/clang-tidy/modernize-use-emplace.cpp
+++ test/clang-tidy/modernize-use-emplace.cpp
@@ -186,6 +186,11 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
   // CHECK-FIXES: v.emplace_back(1, 2);
 
+  v.push_back({1, 2});
+  v.push_back(std::pair<int, int>{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
   GetPair g;
   v.push_back(g.getPair());
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
Index: clang-tidy/modernize/UseEmplaceCheck.h
===================================================================
--- clang-tidy/modernize/UseEmplaceCheck.h
+++ clang-tidy/modernize/UseEmplaceCheck.h
@@ -35,6 +35,7 @@
 private:
   std::vector<std::string> ContainersWithPushBack;
   std::vector<std::string> SmartPointers;
+  std::vector<std::string> PairTypes;
 };
 
 } // namespace modernize
Index: clang-tidy/modernize/UseEmplaceCheck.cpp
===================================================================
--- clang-tidy/modernize/UseEmplaceCheck.cpp
+++ clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -19,13 +19,16 @@
     "::std::vector; ::std::list; ::std::deque";
 static const auto DefaultSmartPointers =
     "::std::shared_ptr; ::std::unique_ptr; ::std::auto_ptr; ::std::weak_ptr";
+static const auto DefaultPairTypes = "::std::pair";
 
 UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       ContainersWithPushBack(utils::options::parseStringList(Options.get(
           "ContainersWithPushBack", DefaultContainersWithPushBack))),
       SmartPointers(utils::options::parseStringList(
-          Options.get("SmartPointers", DefaultSmartPointers))) {}
+          Options.get("SmartPointers", DefaultSmartPointers))),
+      PairTypes(utils::options::parseStringList(
+          Options.get("PairTypes", DefaultPairTypes))) {}
 
 void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus11)
@@ -72,11 +75,19 @@
   auto hasInitList = has(ignoringImplicit(initListExpr()));
   // FIXME: Discard 0/NULL (as nullptr), static inline const data members,
   // overloaded functions and template names.
+
+  // Ignore push_back({first, second}) for pair types (eg. std::pair).
+  auto isPairBraceInit = expr(allOf(cxxConstructExpr(hasDeclaration(
+      cxxConstructorDecl(ofClass(hasAnyName(SmallVector<StringRef, 2>(
+          PairTypes.begin(), PairTypes.end())))))),
+                                    unless(cxxTemporaryObjectExpr())),
+                              unless(hasParent(implicitCastExpr())));
+
   auto soughtConstructExpr =
       cxxConstructExpr(
           unless(anyOf(isCtorOfSmartPtr, hasInitList, bitFieldAsArgument,
                        initializerListAsArgument, newExprAsArgument,
-                       constructingDerived, isPrivateCtor)))
+                       constructingDerived, isPrivateCtor, isPairBraceInit)))
           .bind("ctor");
   auto hasConstructExpr = has(ignoringImplicit(soughtConstructExpr));
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to