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