Skip to content

Commit

Permalink
[clang-tidy] Add "MakeSmartPtrFunction" option to modernize-make-shar…
Browse files Browse the repository at this point in the history
…ed/unique checks.

Reviewers: alexfh, aaron.ballman

Reviewed By: alexfh

Subscribers: JDevlieghere, Eugene.Zelenko, xazax.hun, cfe-commits

Differential Revision: https://reviews.llvm.org/D34206

llvm-svn: 307130
  • Loading branch information
hokein committed Jul 5, 2017
1 parent d19389a commit 040c0f9
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 60 deletions.
50 changes: 44 additions & 6 deletions clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -17,6 +19,9 @@ namespace tidy {
namespace modernize {

namespace {

constexpr char StdMemoryHeader[] = "memory";

std::string GetNewExprName(const CXXNewExpr *NewExpr,
const SourceManager &SM,
const LangOptions &Lang) {
Expand All @@ -29,6 +34,7 @@ std::string GetNewExprName(const CXXNewExpr *NewExpr,
}
return WrittenName.str();
}

} // namespace

const char MakeSmartPtrCheck::PointerType[] = "pointerType";
Expand All @@ -37,9 +43,28 @@ 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)
Expand Down Expand Up @@ -107,7 +132,7 @@ void MakeSmartPtrCheck::checkConstruct(SourceManager &SM,
return;

auto Diag = diag(ConstructCallStart, "use %0 instead")
<< makeSmartPtrFunctionName;
<< MakeSmartPtrFunctionName;

// Find the location of the template's left angle.
size_t LAngle = ExprStr.find("<");
Expand All @@ -125,7 +150,7 @@ void MakeSmartPtrCheck::checkConstruct(SourceManager &SM,

Diag << FixItHint::CreateReplacement(
CharSourceRange::getCharRange(ConstructCallStart, ConstructCallEnd),
makeSmartPtrFunctionName);
MakeSmartPtrFunctionName);

// If the smart_ptr is built with brace enclosed direct initialization, use
// parenthesis instead.
Expand All @@ -142,6 +167,7 @@ void MakeSmartPtrCheck::checkConstruct(SourceManager &SM,
}

replaceNew(Diag, New, SM);
insertHeader(Diag, SM.getFileID(ConstructCallStart));
}

void MakeSmartPtrCheck::checkReset(SourceManager &SM,
Expand All @@ -155,18 +181,19 @@ void MakeSmartPtrCheck::checkReset(SourceManager &SM,
Lexer::getLocForEndOfToken(Expr->getLocEnd(), 0, SM, getLangOpts());

auto Diag = diag(ResetCallStart, "use %0 instead")
<< makeSmartPtrFunctionName;
<< MakeSmartPtrFunctionName;

Diag << FixItHint::CreateReplacement(
CharSourceRange::getCharRange(OperatorLoc, ExprEnd),
(llvm::Twine(" = ") + makeSmartPtrFunctionName + "<" +
(llvm::Twine(" = ") + MakeSmartPtrFunctionName + "<" +
GetNewExprName(New, SM, getLangOpts()) + ">")
.str());

if (Expr->isArrow())
Diag << FixItHint::CreateInsertion(ExprStart, "*");

replaceNew(Diag, New, SM);
insertHeader(Diag, SM.getFileID(OperatorLoc));
}

void MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
Expand Down Expand Up @@ -243,6 +270,17 @@ void MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
}
}

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
12 changes: 10 additions & 2 deletions clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -24,9 +25,11 @@ namespace modernize {
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<QualType>;
Expand All @@ -43,14 +46,19 @@ class MakeSmartPtrCheck : public ClangTidyCheck {
static const char NewExpression[];

private:
std::string makeSmartPtrFunctionName;
std::unique_ptr<utils::IncludeInserter> 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,
SourceManager &SM);
void insertHeader(DiagnosticBuilder &Diag, FileID FD);
};

} // namespace modernize
Expand Down
18 changes: 18 additions & 0 deletions clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,21 @@ expression, and replaces it with a call to ``std::make_shared``.
// becomes

my_ptr = std::make_shared<MyPair>(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`.
18 changes: 18 additions & 0 deletions clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,21 @@ expression, and replaces it with a call to ``std::make_unique``.
// becomes

my_ptr = std::make_unique<MyPair>(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`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace std {

template <typename type>
class shared_ptr {
public:
shared_ptr();
shared_ptr(type *ptr);
shared_ptr(const shared_ptr<type> &t) {}
shared_ptr(shared_ptr<type> &&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 <typename T>
shared_ptr &operator=(shared_ptr<T> &&);

private:
type *ptr;
};

} // namespace std
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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();
void reset();
void reset(type *pt);
void reset(type pt);
unique_ptr &operator=(unique_ptr &&);
template <typename T>
unique_ptr &operator=(unique_ptr<T> &&);

private:
type *ptr;
};

} // namespace std
17 changes: 17 additions & 0 deletions clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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 -I%S/Inputs/modernize-smart-ptr

#include "shared_ptr.h"
// CHECK-FIXES: #include "make_shared_util.h"

void f() {
std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeShared instead
// CHECK-FIXES: std::shared_ptr<int> P1 = my::MakeShared<int>();
}
28 changes: 4 additions & 24 deletions clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
// RUN: %check_clang_tidy %s modernize-make-shared %t
// RUN: %check_clang_tidy %s modernize-make-shared %t -- -- -std=c++11 \
// RUN: -I%S/Inputs/modernize-smart-ptr

namespace std {

template <typename type>
class shared_ptr {
public:
shared_ptr();
shared_ptr(type *ptr);
shared_ptr(const shared_ptr<type> &t) {}
shared_ptr(shared_ptr<type> &&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 <typename T>
shared_ptr &operator=(shared_ptr<T> &&);

private:
type *ptr;
};
}
#include "shared_ptr.h"
// CHECK-FIXES: #include <memory>

struct Base {
Base();
Expand Down
17 changes: 17 additions & 0 deletions clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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 -I%S/Inputs/modernize-smart-ptr

#include "unique_ptr.h"
// CHECK-FIXES: #include "make_unique_util.h"

void f() {
std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeUnique instead
// CHECK-FIXES: std::unique_ptr<int> P1 = my::MakeUnique<int>();
}
32 changes: 4 additions & 28 deletions clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp
Original file line number Diff line number Diff line change
@@ -1,32 +1,8 @@
// RUN: %check_clang_tidy %s modernize-make-unique %t
// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++11 \
// RUN: -I%S/Inputs/modernize-smart-ptr

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();
void reset();
void reset(type *pt);
void reset(type pt);
unique_ptr &operator=(unique_ptr &&);
template <typename T>
unique_ptr &operator=(unique_ptr<T> &&);

private:
type *ptr;
};
}
#include "unique_ptr.h"
// CHECK-FIXES: #include <memory>

struct Base {
Base();
Expand Down

0 comments on commit 040c0f9

Please sign in to comment.