Index: clang-tidy/modernize/CMakeLists.txt =================================================================== --- clang-tidy/modernize/CMakeLists.txt +++ clang-tidy/modernize/CMakeLists.txt @@ -14,6 +14,7 @@ UseDefaultCheck.cpp UseNullptrCheck.cpp UseOverrideCheck.cpp + UseUsingCheck.cpp LINK_LIBS clangAST Index: clang-tidy/modernize/ModernizeTidyModule.cpp =================================================================== --- clang-tidy/modernize/ModernizeTidyModule.cpp +++ clang-tidy/modernize/ModernizeTidyModule.cpp @@ -21,6 +21,7 @@ #include "UseDefaultCheck.h" #include "UseNullptrCheck.h" #include "UseOverrideCheck.h" +#include "UseUsingCheck.h" using namespace clang::ast_matchers; @@ -45,6 +46,8 @@ CheckFactories.registerCheck("modernize-use-default"); CheckFactories.registerCheck("modernize-use-nullptr"); CheckFactories.registerCheck("modernize-use-override"); + CheckFactories.registerCheck( + "modernize-use-using"); } ClangTidyOptions getModuleOptions() override { Index: clang-tidy/modernize/UseUsingCheck.h =================================================================== --- /dev/null +++ clang-tidy/modernize/UseUsingCheck.h @@ -0,0 +1,35 @@ +//===--- UseUsingCheck.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_MODERNIZE_USE_USING_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_USING_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace modernize { + +/// Finds typedefs and replaces it with using +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-using.html +class UseUsingCheck : public ClangTidyCheck { +public: + UseUsingCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace modernize +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_USING_H Index: clang-tidy/modernize/UseUsingCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/modernize/UseUsingCheck.cpp @@ -0,0 +1,61 @@ +//===--- UseUsingCheck.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 "UseUsingCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace modernize { + +void UseUsingCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(typedefDecl().bind("typedef"), this); +} +///Function which replace all substrings "search" with "replace" in string "s" +static void replaceAll(std::string &s, const std::string &search, const std::string replace){ + size_t pos = 0; + while ((pos = s.find(search, pos)) != std::string::npos) { + s.replace(pos, search.length(), replace); + pos += replace.length(); + } +} + +/// Function which removes words "class", "struct", "union" and "void" from +/// AST representation of type. +static std::string removeExtraASTWords(std::string subject) { + const std::pair Subs[] = { + {" class ", ""}, {"(class ", "("}, {"struct ", ""}, {"union ", ""}, {"(void)", "()"}}; + for (auto p : Subs) { + std::string search = p.first; + std::string replace = p.second; + replaceAll(subject, search, replace); + } + return subject; +} + +void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs("typedef"); + if (!MatchedDecl->getLocation().isValid()) + return; + + diag(MatchedDecl->getLocStart(), "use using instead of typedef") + << FixItHint::CreateReplacement( + MatchedDecl->getSourceRange(), + "using " + MatchedDecl->getNameAsString() + " = " + + removeExtraASTWords( + MatchedDecl->getUnderlyingType().getAsString())); +} + +} // namespace modernize +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -85,6 +85,7 @@ modernize-use-default modernize-use-nullptr modernize-use-override + modernize-use-using performance-faster-string-find performance-for-range-copy performance-implicit-cast-in-loop Index: docs/clang-tidy/checks/modernize-use-using.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/modernize-use-using.rst @@ -0,0 +1,24 @@ +.. title:: clang-tidy - modernize-use-using + +modernize-use-using +=================== + +Use C++11's ``using`` instead of ``typedef``. + +Before: + +.. code:: c++ + + typedef int variable; + + class Class{}; + typedef void (Class::* MyPtrType)() const; + +After: + +.. code:: c++ + + using varible = int; + + class Class{}; + using MyPtrType = void (Class::*)() const; Index: test/clang-tidy/modernize-use-using.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-use-using.cpp @@ -0,0 +1,84 @@ +// RUN: %check_clang_tidy %s modernize-use-using %t + + +typedef int Type; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using Type = int; + +typedef long LL; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using LL = long; + +typedef int Bla; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using Bla = int; + +typedef Bla Bla2; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using Bla2 = Bla; + +typedef void (*type)(int); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using type = void (*)(int); + +typedef void (*type2)(); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using type2 = void (*)(); + +class Class { + typedef long long Type; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use using instead of typedef [modernize-use-using] + // CHECK-FIXES: using Type = long long; +}; + +typedef void (Class::* MyPtrType)(Bla) const; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using MyPtrType = void (Class::*)(Bla) const; + +class Iterable { +public: + class Iterator {}; +}; + +template +class Test { + typedef typename T::iterator Iter; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use using instead of typedef [modernize-use-using] + // CHECK-FIXES: using Iter = typename T::iterator; +}; + +using balba = long long; + +union A {}; + +typedef void (A::*PtrType)(int, int) const; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using PtrType = void (A::*)(int, int) const; + +typedef Class some_class; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using some_class = Class; + +typedef Class Cclass; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using Cclass = Class; +typedef Cclass cclass2; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using cclass2 = Cclass; + +class cclass { + +}; + +typedef void (cclass::* MyPtrType3)(Bla); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using MyPtrType3 = void (cclass::*)(Bla); + +using my_class = int; + +//FIXME: below test fails +typedef Test another; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use using instead of typedef [modernize-use-using] +// CHECK-FIXES: using another = Test; + +