diff options
| author | Samuel Benzaquen <sbenza@google.com> | 2014-03-27 17:42:26 +0000 |
|---|---|---|
| committer | Samuel Benzaquen <sbenza@google.com> | 2014-03-27 17:42:26 +0000 |
| commit | 3a571019c8b17e6f5896c5b2a80e3a854011eb32 (patch) | |
| tree | 6a7f609f79d924e428298252097304d9167f26d3 /clang-tools-extra/clang-tidy/misc | |
| parent | b517c8128e8255a205d2e2da65a26f38e2474fcb (diff) | |
| download | bcm5719-llvm-3a571019c8b17e6f5896c5b2a80e3a854011eb32.tar.gz bcm5719-llvm-3a571019c8b17e6f5896c5b2a80e3a854011eb32.zip | |
Add clang-tidy check to remove redundant .get() calls on smart pointers.
Summary:
This check finds and removes redundant .get() calls on smart pointers.
Example:
ptr.get()->Foo() ==> ptr->Foo()
Reviewers: alexfh
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D3186
llvm-svn: 204947
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc')
4 files changed, 130 insertions, 3 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 8c9b5dd3c0b..3dd97bf0b4f 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyMiscModule ArgumentCommentCheck.cpp MiscTidyModule.cpp + RedundantSmartptrGet.cpp LINK_LIBS clangAST diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp index f7f657addfa..b89e2dcad48 100644 --- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" #include "ArgumentCommentCheck.h" +#include "RedundantSmartptrGet.h" namespace clang { namespace tidy { @@ -18,9 +19,12 @@ namespace tidy { class MiscModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { - CheckFactories.addCheckFactory( - "misc-argument-comment", - new ClangTidyCheckFactory<ArgumentCommentCheck>()); + CheckFactories.addCheckFactory( + "misc-argument-comment", + new ClangTidyCheckFactory<ArgumentCommentCheck>()); + CheckFactories.addCheckFactory( + "misc-redundant-smartptr-get", + new ClangTidyCheckFactory<RedundantSmartptrGet>()); } }; diff --git a/clang-tools-extra/clang-tidy/misc/RedundantSmartptrGet.cpp b/clang-tools-extra/clang-tidy/misc/RedundantSmartptrGet.cpp new file mode 100644 index 00000000000..ec08c142c18 --- /dev/null +++ b/clang-tools-extra/clang-tidy/misc/RedundantSmartptrGet.cpp @@ -0,0 +1,88 @@ +//===--- RedundantSmartptrGet.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 "RedundantSmartptrGet.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void RedundantSmartptrGet::registerMatchers(MatchFinder *Finder) { + const auto QuacksLikeASmartptr = recordDecl( + has(methodDecl(hasName("operator->"), + returns(qualType(pointsTo(type().bind("op->Type")))))), + has(methodDecl(hasName("operator*"), + returns(qualType(references(type().bind("op*Type")))))), + has(methodDecl(hasName("get"), + returns(qualType(pointsTo(type().bind("getType"))))))); + + const auto CallToGet = + memberCallExpr(on(expr(hasType(recordDecl(QuacksLikeASmartptr))) + .bind("smart_pointer")), + callee(methodDecl(hasName("get")))).bind("redundant_get"); + + const auto ArrowCallToGet = + memberCallExpr( + on(expr(hasType(qualType(pointsTo(recordDecl(QuacksLikeASmartptr))))) + .bind("smart_pointer")), + callee(methodDecl(hasName("get")))).bind("redundant_get"); + + // Catch 'ptr.get()->Foo()' + Finder->addMatcher( + memberExpr(isArrow(), hasObjectExpression(ignoringImpCasts(CallToGet))), + this); + + // Catch '*ptr.get()' + Finder->addMatcher( + unaryOperator(hasOperatorName("*"), hasUnaryOperand(CallToGet)), this); + + // Catch '*ptr->get()' + Finder->addMatcher( + unaryOperator(hasOperatorName("*"), hasUnaryOperand(ArrowCallToGet)) + .bind("ptr_to_ptr"), + this); +} + +namespace { +bool allReturnTypesMatch(const MatchFinder::MatchResult &Result) { + // Verify that the types match. + // We can't do this on the matcher because the type nodes can be different, + // even though they represent the same type. This difference comes from how + // the type is referenced (eg. through a typedef, a type trait, etc). + const Type *OpArrowType = + Result.Nodes.getNodeAs<Type>("op->Type")->getUnqualifiedDesugaredType(); + const Type *OpStarType = + Result.Nodes.getNodeAs<Type>("op*Type")->getUnqualifiedDesugaredType(); + const Type *GetType = + Result.Nodes.getNodeAs<Type>("getType")->getUnqualifiedDesugaredType(); + return OpArrowType == OpStarType && OpArrowType == GetType; +} +} // namespace + +void RedundantSmartptrGet::check(const MatchFinder::MatchResult &Result) { + if (!allReturnTypesMatch(Result)) return; + + bool IsPtrToPtr = Result.Nodes.getNodeAs<Expr>("ptr_to_ptr") != nullptr; + const Expr *GetCall = Result.Nodes.getNodeAs<Expr>("redundant_get"); + const Expr *Smartptr = Result.Nodes.getNodeAs<Expr>("smart_pointer"); + + StringRef SmartptrText = Lexer::getSourceText( + CharSourceRange::getTokenRange(Smartptr->getSourceRange()), + *Result.SourceManager, LangOptions()); + // Replace *foo->get() with **foo, and foo.get() with foo. + std::string Replacement = Twine(IsPtrToPtr ? "*" : "", SmartptrText).str(); + diag(GetCall->getLocStart(), "Redundant get() call on smart pointer.") + << FixItHint::CreateReplacement(GetCall->getSourceRange(), Replacement); +} + +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/misc/RedundantSmartptrGet.h b/clang-tools-extra/clang-tidy/misc/RedundantSmartptrGet.h new file mode 100644 index 00000000000..32268c2dab1 --- /dev/null +++ b/clang-tools-extra/clang-tidy/misc/RedundantSmartptrGet.h @@ -0,0 +1,34 @@ +//===--- RedundantSmartptrGet.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_MISC_REDUNDANT_SMARTPTR_GET_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +/// \brief Find and remove redundant calls to smart pointer's .get() method. +/// +/// Examples: +/// ptr.get()->Foo() ==> ptr->Foo() +/// *ptr.get() ==> *ptr +/// *ptr->get() ==> **ptr +class RedundantSmartptrGet : public ClangTidyCheck { +public: + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H + |

