Index: clang-tidy/modernize/MakeSmartPtrCheck.h =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.h +++ clang-tidy/modernize/MakeSmartPtrCheck.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_SMART_PTR_H #include "../ClangTidy.h" +#include "../utils/IncludeInserter.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" #include "llvm/ADT/StringRef.h" @@ -24,9 +25,11 @@ class MakeSmartPtrCheck : public ClangTidyCheck { public: MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context, - std::string makeSmartPtrFunctionName); + StringRef makeSmartPtrFunctionName); void registerMatchers(ast_matchers::MatchFinder *Finder) final; + void registerPPCallbacks(clang::CompilerInstance &Compiler) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) final; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; protected: using SmartPtrTypeMatcher = ast_matchers::internal::BindableMatcher; @@ -43,13 +46,18 @@ static const char NewExpression[]; private: - std::string makeSmartPtrFunctionName; + std::unique_ptr Inserter; + const utils::IncludeSorter::IncludeStyle IncludeStyle; + const std::string makeSmartPtrFunctionHeader; + const std::string makeSmartPtrFunctionName; void checkConstruct(SourceManager &SM, const CXXConstructExpr *Construct, const QualType *Type, const CXXNewExpr *New); void checkReset(SourceManager &SM, const CXXMemberCallExpr *Member, const CXXNewExpr *New); void replaceNew(DiagnosticBuilder &Diag, const CXXNewExpr *New); + + void insertHeader(DiagnosticBuilder &Diag, FileID FD); }; } // namespace modernize Index: clang-tidy/modernize/MakeSmartPtrCheck.cpp =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "MakeSharedCheck.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" using namespace clang::ast_matchers; @@ -16,15 +18,36 @@ namespace tidy { namespace modernize { +static constexpr char StdMemoryHeader[] = "memory"; + const char MakeSmartPtrCheck::PointerType[] = "pointerType"; const char MakeSmartPtrCheck::ConstructorCall[] = "constructorCall"; const char MakeSmartPtrCheck::ResetCall[] = "resetCall"; const char MakeSmartPtrCheck::NewExpression[] = "newExpression"; MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context, - std::string makeSmartPtrFunctionName) + StringRef makeSmartPtrFunctionName) : ClangTidyCheck(Name, Context), - makeSmartPtrFunctionName(std::move(makeSmartPtrFunctionName)) {} + IncludeStyle(utils::IncludeSorter::parseIncludeStyle( + Options.get("IncludeStyle", "llvm"))), + makeSmartPtrFunctionHeader( + Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)), + makeSmartPtrFunctionName( + Options.get("MakeSmartPtrFunction", makeSmartPtrFunctionName)) {} + +void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IncludeStyle", IncludeStyle); + Options.store(Opts, "MakeSmartPtrFunctionHeader", makeSmartPtrFunctionHeader); + Options.store(Opts, "MakeSmartPtrFunction", makeSmartPtrFunctionName); +} + +void MakeSmartPtrCheck::registerPPCallbacks(CompilerInstance &Compiler) { + if (getLangOpts().CPlusPlus11) { + Inserter.reset(new utils::IncludeInserter( + Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle)); + Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks()); + } +} void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) { if (!getLangOpts().CPlusPlus11) @@ -126,6 +149,7 @@ } replaceNew(Diag, New); + insertHeader(Diag, SM.getFileID(ConstructCallStart)); } void MakeSmartPtrCheck::checkReset(SourceManager &SM, @@ -151,6 +175,7 @@ Diag << FixItHint::CreateInsertion(ExprStart, "*"); replaceNew(Diag, New); + insertHeader(Diag, SM.getFileID(OperatorLoc)); } void MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag, @@ -201,6 +226,17 @@ } } +void MakeSmartPtrCheck::insertHeader(DiagnosticBuilder &Diag, FileID FD) { + if (makeSmartPtrFunctionHeader.empty()) { + return; + } + if (auto IncludeFixit = Inserter->CreateIncludeInsertion( + FD, makeSmartPtrFunctionHeader, + /*IsAngled=*/makeSmartPtrFunctionHeader == StdMemoryHeader)) { + Diag << *IncludeFixit; + } +} + } // namespace modernize } // namespace tidy } // namespace clang Index: docs/clang-tidy/checks/modernize-make-shared.rst =================================================================== --- docs/clang-tidy/checks/modernize-make-shared.rst +++ docs/clang-tidy/checks/modernize-make-shared.rst @@ -25,3 +25,21 @@ // becomes my_ptr = std::make_shared(1, 2); + +Options +------- + +.. option:: MakeSmartPtrFunction + + A string specifying the name of make-shared-ptr function. Default is + `std::make_shared`. + +.. option:: MakeSmartPtrFunctionHeader + + A string specifying the corresponding header of make-shared-ptr function. + Default is `memory`. + +.. option:: IncludeStyle + + A string specifying which include-style is used, `llvm` or `google`. Default + is `llvm`. 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 @@ -25,3 +25,21 @@ // becomes my_ptr = std::make_unique(1, 2); + +Options +------- + +.. option:: MakeSmartPtrFunction + + A string specifying the name of make-unique-ptr function. Default is + `std::make_unique`. + +.. option:: MakeSmartPtrFunctionHeader + + A string specifying the corresponding header of make-unique-ptr function. + Default is `memory`. + +.. option:: IncludeStyle + + A string specifying which include-style is used, `llvm` or `google`. Default + is `llvm`. Index: test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h @@ -0,0 +1,24 @@ +namespace std { + +template +class shared_ptr { +public: + shared_ptr(); + shared_ptr(type *ptr); + shared_ptr(const shared_ptr &t) {} + shared_ptr(shared_ptr &&t) {} + ~shared_ptr(); + type &operator*() { return *ptr; } + type *operator->() { return ptr; } + type *release(); + void reset(); + void reset(type *pt); + shared_ptr &operator=(shared_ptr &&); + template + shared_ptr &operator=(shared_ptr &&); + +private: + type *ptr; +}; + +} // namespace std Index: test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h @@ -0,0 +1,27 @@ +namespace std { + +template +class default_delete {}; + +template > +class unique_ptr { +public: + unique_ptr(); + unique_ptr(type *ptr); + unique_ptr(const unique_ptr &t) = delete; + unique_ptr(unique_ptr &&t); + ~unique_ptr(); + type &operator*() { return *ptr; } + type *operator->() { return ptr; } + type *release(); + void reset(); + void reset(type *pt); + unique_ptr &operator=(unique_ptr &&); + template + unique_ptr &operator=(unique_ptr &&); + +private: + type *ptr; +}; + +} // namespace std Index: test/clang-tidy/modernize-make-shared-header.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-make-shared-header.cpp @@ -0,0 +1,18 @@ +// RUN: cp %S/Inputs/modernize-smart-ptr/shared_ptr.h %T/shared_ptr.h +// RUN: %check_clang_tidy %s modernize-make-shared %t -- \ +// RUN: -config="{CheckOptions: \ +// RUN: [{key: modernize-make-shared.MakeSmartPtrFunction, \ +// RUN: value: 'my::MakeShared'}, \ +// RUN: {key: modernize-make-shared.MakeSmartPtrFunctionHeader, \ +// RUN: value: 'make_shared_util.h'} \ +// RUN: ]}" \ +// RUN: -- -std=c++11 + +#include "shared_ptr.h" +// CHECK-FIXES: #include "make_shared_util.h" + +void f() { + std::shared_ptr P1 = std::shared_ptr(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeShared instead + // CHECK-FIXES: std::shared_ptr P1 = my::MakeShared(); +} Index: test/clang-tidy/modernize-make-shared.cpp =================================================================== --- test/clang-tidy/modernize-make-shared.cpp +++ test/clang-tidy/modernize-make-shared.cpp @@ -1,28 +1,8 @@ +// RUN: cp %S/Inputs/modernize-smart-ptr/shared_ptr.h %T/shared_ptr.h // RUN: %check_clang_tidy %s modernize-make-shared %t -namespace std { - -template -class shared_ptr { -public: - shared_ptr(); - shared_ptr(type *ptr); - shared_ptr(const shared_ptr &t) {} - shared_ptr(shared_ptr &&t) {} - ~shared_ptr(); - type &operator*() { return *ptr; } - type *operator->() { return ptr; } - type *release(); - void reset(); - void reset(type *pt); - shared_ptr &operator=(shared_ptr &&); - template - shared_ptr &operator=(shared_ptr &&); - -private: - type *ptr; -}; -} +#include "shared_ptr.h" +// CHECK-FIXES: #include struct Base { Base(); Index: test/clang-tidy/modernize-make-unique-header.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-make-unique-header.cpp @@ -0,0 +1,18 @@ +// RUN: cp %S/Inputs/modernize-smart-ptr/unique_ptr.h %T/unique_ptr.h +// RUN: %check_clang_tidy %s modernize-make-unique %t -- \ +// RUN: -config="{CheckOptions: \ +// RUN: [{key: modernize-make-unique.MakeSmartPtrFunction, \ +// RUN: value: 'my::MakeUnique'}, \ +// RUN: {key: modernize-make-unique.MakeSmartPtrFunctionHeader, \ +// RUN: value: 'make_unique_util.h'} \ +// RUN: ]}" \ +// RUN: -- -std=c++11 + +#include "unique_ptr.h" +// CHECK-FIXES: #include "make_unique_util.h" + +void f() { + std::unique_ptr P1 = std::unique_ptr(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeUnique instead + // CHECK-FIXES: std::unique_ptr P1 = my::MakeUnique(); +} Index: test/clang-tidy/modernize-make-unique.cpp =================================================================== --- test/clang-tidy/modernize-make-unique.cpp +++ test/clang-tidy/modernize-make-unique.cpp @@ -1,31 +1,8 @@ +// RUN: cp %S/Inputs/modernize-smart-ptr/unique_ptr.h %T/unique_ptr.h // RUN: %check_clang_tidy %s modernize-make-unique %t -namespace std { - -template -class default_delete {}; - -template > -class unique_ptr { -public: - unique_ptr(); - unique_ptr(type *ptr); - unique_ptr(const unique_ptr &t) = delete; - unique_ptr(unique_ptr &&t); - ~unique_ptr(); - type &operator*() { return *ptr; } - type *operator->() { return ptr; } - type *release(); - void reset(); - void reset(type *pt); - unique_ptr &operator=(unique_ptr &&); - template - unique_ptr &operator=(unique_ptr &&); - -private: - type *ptr; -}; -} +#include "unique_ptr.h" +// CHECK-FIXES: #include struct Base { Base();