Index: clang-tidy/abseil/AbseilTidyModule.cpp =================================================================== --- clang-tidy/abseil/AbseilTidyModule.cpp +++ clang-tidy/abseil/AbseilTidyModule.cpp @@ -9,6 +9,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "../modernize/MakeUniqueCheck.h" #include "DurationAdditionCheck.h" #include "DurationComparisonCheck.h" #include "DurationConversionCastCheck.h" @@ -64,6 +65,17 @@ "abseil-time-subtraction"); CheckFactories.registerCheck( "abseil-upgrade-duration-conversions"); + CheckFactories.registerCheck( + "abseil-make-unique"); + } + + ClangTidyOptions getModuleOptions() override { + ClangTidyOptions Options; + ClangTidyOptions::OptionMap &Opts = Options.CheckOptions; + Opts["abseil-make-unique.MakeSmartPtrFunctionHeader"] = "absl/memory/memory.h"; + Opts["abseil-make-unique.MakeSmartPtrFunction"] = "absl::make_unique"; + Opts["abseil-make-unique.IgnoreListInit"] = "1"; + return Options; } }; Index: clang-tidy/modernize/MakeSmartPtrCheck.h =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.h +++ clang-tidy/modernize/MakeSmartPtrCheck.h @@ -50,6 +50,7 @@ const std::string MakeSmartPtrFunctionHeader; const std::string MakeSmartPtrFunctionName; const bool IgnoreMacros; + const bool IgnoreListInit; void checkConstruct(SourceManager &SM, ASTContext *Ctx, const CXXConstructExpr *Construct, const QualType *Type, Index: clang-tidy/modernize/MakeSmartPtrCheck.cpp =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -51,13 +51,15 @@ Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)), MakeSmartPtrFunctionName( Options.get("MakeSmartPtrFunction", MakeSmartPtrFunctionName)), - IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} + IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)), + IgnoreListInit(Options.get("IgnoreListInit", false)) {} void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader); Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName); Options.store(Opts, "IgnoreMacros", IgnoreMacros); + Options.store(Opts, "IgnoreListInit", IgnoreListInit); } bool MakeSmartPtrCheck::isLanguageVersionSupported( @@ -123,6 +125,9 @@ if (New->getType()->getPointeeType()->getContainedAutoType()) return; + if (IgnoreListInit && New->getInitializationStyle() == CXXNewExpr::ListInit) + return; + // Be conservative for cases where we construct an array without any // initalization. // For example, @@ -342,7 +347,7 @@ Diag << FixItHint::CreateRemoval( SourceRange(NewStart, InitRange.getBegin())); Diag << FixItHint::CreateRemoval(SourceRange(InitRange.getEnd(), NewEnd)); - } + } else { // New array expression with default/value initialization: // smart_ptr(new int[5]()); Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -85,6 +85,11 @@ Finds and fixes cases where ``absl::Duration`` values are being converted to numeric types and back again. +- New alias :doc:`abseil-make-unique + ` to :doc:`modernize-make-unique + ` + added. + - New :doc:`abseil-time-subtraction ` check. @@ -104,6 +109,11 @@ `CommentUserDefiniedLiterals`, `CommentStringLiterals`, `CommentCharacterLiterals` & `CommentNullPtrs` options. +- The :doc:`modernize-make-unique + ` now supports an + `IgnoreListInit` option which disables the check when the constructor + is a list initialization. + - The `Acronyms` and `IncludeDefaultAcronyms` options for the :doc:`objc-property-declaration ` check have been removed. Index: docs/clang-tidy/checks/abseil-make-unique.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/abseil-make-unique.rst @@ -0,0 +1,22 @@ +.. title:: clang-tidy - abseil-make-unique +.. meta:: + :http-equiv=refresh: 5;URL=abseil-make-unique.html + +abseil-make-unique +================== + +This check finds the creation of ``std::unique_ptr`` objects by explicitly +calling the constructor and a ``new`` expression, and replaces it with a call +to ``absl::make_unique``, the Abseil implementation of ``std::make_unique`` +in C++11. + +.. code-block:: c++ + + auto ptr = std::unique_ptr(new int(1)); + + // becomes + + auto ptr = absl::make_unique(1); + +The Abseil Style Guide _ discusses this issue in +more detail. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -13,6 +13,7 @@ abseil-duration-subtraction abseil-duration-unnecessary-conversion abseil-faster-strsplit-delimiter + abseil-make-unique (redirects to modernize-make-unique) abseil-no-internal-dependencies abseil-no-namespace abseil-redundant-strcat-calls Index: docs/clang-tidy/checks/modernize-make-unique.rst =================================================================== --- docs/clang-tidy/checks/modernize-make-unique.rst +++ docs/clang-tidy/checks/modernize-make-unique.rst @@ -48,3 +48,9 @@ If set to non-zero, the check will not give warnings inside macros. Default is `1`. + +.. option:: IgnoreListInit + + If set to non-zero, the check will ignore list initializations of `new` + expressions. Default is `0`. + Index: test/clang-tidy/abseil-make-unique.cpp =================================================================== --- /dev/null +++ test/clang-tidy/abseil-make-unique.cpp @@ -0,0 +1,67 @@ +// RUN: %check_clang_tidy %s abseil-make-unique %t -- -- -std=c++11 \ +// RUN: -I%S/Inputs/modernize-smart-ptr + +#include "unique_ptr.h" +#include "initializer_list.h" +// CHECK-FIXES: #include "absl/memory/memory.h" + +class A { + int x; + int y; + + public: + A(int _x, int _y): x(_x), y(_y) {} +}; + +struct B { + B(std::initializer_list); + B(); +}; + +struct Base { + Base(); +}; + +struct Derived : public Base { + Derived(); +}; + +int* returnPointer(); + +std::unique_ptr makeAndReturnPointer() { + return std::unique_ptr(new int(0)); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use absl::make_unique instead [abseil-make-unique] + // CHECK-FIXES: return absl::make_unique(0); +} + +void Positives() { + std::unique_ptr P1 = std::unique_ptr(new int(1)); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use absl::make_unique instead [abseil-make-unique] + // CHECK-FIXES: std::unique_ptr P1 = absl::make_unique(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(2); + + // Non-primitive paramter + std::unique_ptr P2 = std::unique_ptr(new A(1, 2)); + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use absl::make_unique instead [abseil-make-unique] + // CHECK-FIXES: std::unique_ptr P2 = absl::make_unique(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(3, 4); +} + +void Negatives() { + // Only warn if explicitly allocating a new object + std::unique_ptr R = std::unique_ptr(returnPointer()); + R.reset(returnPointer()); + + // Only replace if the template type is same as new type + auto Pderived = std::unique_ptr(new Derived()); + + // Ignore initializer-list constructors + std::unique_ptr PInit = std::unique_ptr(new B{1, 2}); + PInit.reset(new B{1, 2}); +}