axzhang updated this revision to Diff 177972.
axzhang added a comment.

Per the suggestions of reviewers, change the check so that it uses 
modernize-make-smart-pointer instead.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55044/new/

https://reviews.llvm.org/D55044

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/MakeUniqueCheck.cpp
  clang-tidy/abseil/MakeUniqueCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-make-unique.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-make-unique.cpp

Index: test/clang-tidy/abseil-make-unique.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/abseil-make-unique.cpp
@@ -0,0 +1,130 @@
+// RUN: %check_clang_tidy %s abseil-make-unique %t -- -- -std=c++11 \
+
+// CHECK-FIXES: #include <memory>
+
+namespace std {
+
+template <typename T>
+class default_delete {};
+
+template <typename type, typename Deleter = std::default_delete<type>>
+class unique_ptr {
+public:
+  unique_ptr() {}
+  unique_ptr(type *ptr) {}
+  unique_ptr(const unique_ptr<type> &t) = delete;
+  unique_ptr(unique_ptr<type> &&t) {}
+  ~unique_ptr() {}
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release() { return ptr; }
+  void reset() {}
+  void reset(type *pt) {}
+  void reset(type pt) {}
+  unique_ptr &operator=(unique_ptr &&) { return *this; }
+  template <typename T>
+  unique_ptr &operator=(unique_ptr<T> &&) { return *this; }
+
+private:
+  type *ptr;
+};
+
+}  // namespace std
+
+class A {
+ int x;
+ int y;
+
+ public:
+   A(int _x, int _y): x(_x), y(_y) {}
+};
+
+struct Base {
+  Base();
+};
+
+struct Derived : public Base {
+  Derived();
+};
+
+int* returnPointer();
+void expectPointer(std::unique_ptr<int> p);
+
+std::unique_ptr<int> makeAndReturnPointer() {
+  // Make smart pointer in return statement
+  return std::unique_ptr<int>(new int(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: return absl::make_unique<int>(0);
+}
+
+void Positives() {
+  std::unique_ptr<int> P1 = std::unique_ptr<int>(new int(1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: std::unique_ptr<int> P1 = absl::make_unique<int>(1);
+
+  P1.reset(new int(2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: P1 = absl::make_unique<int>(2);
+
+  // Non-primitive paramter
+  std::unique_ptr<A> P2 = std::unique_ptr<A>(new A(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: std::unique_ptr<A> P2 = absl::make_unique<A>(1, 2);
+
+  P2.reset(new A(3, 4));
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: P2 = absl::make_unique<A>(3, 4);
+
+  // No arguments to new expression
+  std::unique_ptr<int> P3 = std::unique_ptr<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: std::unique_ptr<int> P3 = absl::make_unique<int>();
+
+  P3.reset(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: P3 = absl::make_unique<int>();
+
+  // Nested parentheses
+  std::unique_ptr<int> P4 = std::unique_ptr<int>((new int(3)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: std::unique_ptr<int> P4 = absl::make_unique<int>(3);
+
+  P4 = std::unique_ptr<int>(((new int(4))));
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: P4 = absl::make_unique<int>(4);
+
+  P4.reset((new int(5)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: P4 = absl::make_unique<int>(5);
+
+  // With auto
+  auto P5 = std::unique_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: auto P5 = absl::make_unique<int>();
+
+  {
+    // No std
+    using namespace std;
+    unique_ptr<int> Q = unique_ptr<int>(new int());
+    // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use absl::make_unique instead [abseil-make-unique]
+    // CHECK-FIXES: unique_ptr<int> Q = absl::make_unique<int>();
+
+    Q = unique_ptr<int>(new int());
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use absl::make_unique instead [abseil-make-unique]
+    // CHECK-FIXES: Q = absl::make_unique<int>();
+  }
+
+  // Create the unique_ptr as a parameter to a function
+  expectPointer(std::unique_ptr<int>(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use absl::make_unique instead [abseil-make-unique]
+  // CHECK-FIXES: expectPointer(absl::make_unique<int>());
+}
+
+void Negatives() {
+  // Only warn if explicitly allocating a new object
+  std::unique_ptr<int> R = std::unique_ptr<int>(returnPointer());
+  R.reset(returnPointer());
+
+  // Only replace if the template type is same as new type
+  auto Pderived = std::unique_ptr<Base>(new Derived());
+}
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -7,11 +7,12 @@
    abseil-duration-division
    abseil-duration-factory-float
    abseil-faster-strsplit-delimiter
+   abseil-make-unique
    abseil-no-internal-dependencies
    abseil-no-namespace
    abseil-redundant-strcat-calls
-   abseil-string-find-startswith
    abseil-str-cat-append
+   abseil-string-find-startswith
    android-cloexec-accept
    android-cloexec-accept4
    android-cloexec-creat
@@ -151,6 +152,7 @@
    hicpp-special-member-functions (redirects to cppcoreguidelines-special-member-functions) <hicpp-special-member-functions>
    hicpp-static-assert (redirects to misc-static-assert) <hicpp-static-assert>
    hicpp-undelegated-constructor (redirects to bugprone-undelegated-constructor) <hicpp-undelegated-constructor>
+   hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) <hicpp-uppercase-literal-suffix>
    hicpp-use-auto (redirects to modernize-use-auto) <hicpp-use-auto>
    hicpp-use-emplace (redirects to modernize-use-emplace) <hicpp-use-emplace>
    hicpp-use-equals-default (redirects to modernize-use-equals-default) <hicpp-use-equals-default>
@@ -159,7 +161,6 @@
    hicpp-use-nullptr (redirects to modernize-use-nullptr) <hicpp-use-nullptr>
    hicpp-use-override (redirects to modernize-use-override) <hicpp-use-override>
    hicpp-vararg (redirects to cppcoreguidelines-pro-type-vararg) <hicpp-vararg>
-   hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) <hicpp-uppercase-literal-suffix>
    llvm-header-guard
    llvm-include-order
    llvm-namespace-comment
Index: docs/clang-tidy/checks/abseil-make-unique.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/abseil-make-unique.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - abseil-make-unique
+
+abseil-make-unique
+==================
+
+Checks for instances of initializing a `unique_ptr` with a direct call to
+`new` and suggests using `absl::make_unique` instead.
+
+Replaces initialization of smart pointers:
+\code
+  std::unique_ptr<int> ptr = std::unique_ptr<int>(new int(1));
+\endcode
+
+with the preferred usage:
+\code
+  std::unique_ptr<int> ptr = absl::make_unique<int>(1);
+\endcode
+
+per the Abseil tips and guidelines at https://abseil.io/tips/126.
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -87,6 +87,12 @@
   Finds instances of ``absl::StrSplit()`` or ``absl::MaxSplits()`` where the
   delimiter is a single character string literal and replaces with a character.
 
+- New :doc:`abseil-make-unique
+  <clang-tidy/checks/abseil-make-unique>` check.
+
+  Checks for instances of initializing a `unique_ptr` with a direct call to
+  `new` and suggests using `absl::make_unique` instead.
+
 - New :doc:`abseil-no-internal-dependencies
   <clang-tidy/checks/abseil-no-internal-dependencies>` check.
 
Index: clang-tidy/abseil/MakeUniqueCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/abseil/MakeUniqueCheck.h
@@ -0,0 +1,42 @@
+//===--- MakeUniqueCheck.h - clang-tidy -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_MAKEUNIQUECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_MAKEUNIQUECHECK_H
+
+#include "../ClangTidy.h"
+#include "../modernize/MakeSmartPtrCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Replace the pattern:
+/// \code
+///   std::unique_ptr<type>(new type(args...))
+/// \endcode
+///
+/// With the Abseil version:
+/// \code
+///   absl::make_unique<type>(args...)
+/// \endcode
+class MakeUniqueCheck : public modernize::MakeSmartPtrCheck {
+public:
+  MakeUniqueCheck(StringRef Name, ClangTidyContext *Context);
+
+protected:
+  SmartPtrTypeMatcher getSmartPointerTypeMatcher() const override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_MAKEUNIQUECHECK_H
Index: clang-tidy/abseil/MakeUniqueCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/abseil/MakeUniqueCheck.cpp
@@ -0,0 +1,48 @@
+//===--- MakeUniqueCheck.cpp - clang-tidy ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MakeUniqueCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+MakeUniqueCheck::MakeUniqueCheck(StringRef Name,
+                                 clang::tidy::ClangTidyContext *Context)
+    : MakeSmartPtrCheck(Name, Context, "absl::make_unique") {}
+
+MakeUniqueCheck::SmartPtrTypeMatcher
+MakeUniqueCheck::getSmartPointerTypeMatcher() const {
+  return qualType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(classTemplateSpecializationDecl(
+          hasName("::std::unique_ptr"), templateArgumentCountIs(2),
+          hasTemplateArgument(
+              0, templateArgument(refersToType(qualType().bind(PointerType)))),
+          hasTemplateArgument(
+              1, templateArgument(refersToType(
+                     qualType(hasDeclaration(classTemplateSpecializationDecl(
+                         hasName("::std::default_delete"),
+                         templateArgumentCountIs(1),
+                         hasTemplateArgument(
+                             0, templateArgument(refersToType(qualType(
+                                    equalsBoundNode(PointerType))))))))))))))));
+}
+
+bool MakeUniqueCheck::isLanguageVersionSupported(
+    const LangOptions &LangOpts) const {
+  return LangOpts.CPlusPlus11;
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/CMakeLists.txt
===================================================================
--- clang-tidy/abseil/CMakeLists.txt
+++ clang-tidy/abseil/CMakeLists.txt
@@ -5,6 +5,7 @@
   DurationDivisionCheck.cpp
   DurationFactoryFloatCheck.cpp
   FasterStrsplitDelimiterCheck.cpp
+  MakeUniqueCheck.cpp
   NoInternalDependenciesCheck.cpp
   NoNamespaceCheck.cpp
   RedundantStrcatCallsCheck.cpp
Index: clang-tidy/abseil/AbseilTidyModule.cpp
===================================================================
--- clang-tidy/abseil/AbseilTidyModule.cpp
+++ clang-tidy/abseil/AbseilTidyModule.cpp
@@ -13,6 +13,7 @@
 #include "DurationDivisionCheck.h"
 #include "DurationFactoryFloatCheck.h"
 #include "FasterStrsplitDelimiterCheck.h"
+#include "MakeUniqueCheck.h"
 #include "NoInternalDependenciesCheck.h"
 #include "NoNamespaceCheck.h"
 #include "RedundantStrcatCallsCheck.h"
@@ -32,6 +33,8 @@
         "abseil-duration-factory-float");
     CheckFactories.registerCheck<FasterStrsplitDelimiterCheck>(
         "abseil-faster-strsplit-delimiter");
+    CheckFactories.registerCheck<MakeUniqueCheck>(
+        "abseil-make-unique");
     CheckFactories.registerCheck<NoInternalDependenciesCheck>(
         "abseil-no-internal-dependencies");
     CheckFactories.registerCheck<NoNamespaceCheck>("abseil-no-namespace");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to