aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra')
-rw-r--r--clang-tools-extra/clang-tidy/modernize/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp2
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp93
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h35
-rw-r--r--clang-tools-extra/docs/ReleaseNotes.rst5
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/list.rst1
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst26
-rw-r--r--clang-tools-extra/test/clang-tidy/modernize-use-using.cpp87
8 files changed, 250 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index e42e2a1..57a2b4e 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -20,6 +20,7 @@ add_clang_library(clangTidyModernizeModule
UseEmplaceCheck.cpp
UseNullptrCheck.cpp
UseOverrideCheck.cpp
+ UseUsingCheck.cpp
LINK_LIBS
clangAST
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 5992ade..15c9a57 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -26,6 +26,7 @@
#include "UseEmplaceCheck.h"
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
+#include "UseUsingCheck.h"
using namespace clang::ast_matchers;
@@ -58,6 +59,7 @@ public:
CheckFactories.registerCheck<UseEmplaceCheck>("modernize-use-emplace");
CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
+ CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
}
ClangTidyOptions getModuleOptions() override {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
new file mode 100644
index 0000000..498a95c
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -0,0 +1,93 @@
+//===--- 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 "../utils/LexerUtils.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+ Finder->addMatcher(typedefDecl().bind("typedef"), this);
+}
+
+// Checks if 'typedef' keyword can be removed - we do it only if
+// it is the only declaration in a declaration chain.
+static bool CheckRemoval(SourceManager &SM, const SourceLocation &LocStart,
+ const SourceLocation &LocEnd, ASTContext &Context,
+ SourceRange &ResultRange) {
+ FileID FID = SM.getFileID(LocEnd);
+ llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd);
+ Lexer DeclLexer(SM.getLocForStartOfFile(FID), Context.getLangOpts(),
+ Buffer->getBufferStart(), SM.getCharacterData(LocStart),
+ Buffer->getBufferEnd());
+ Token DeclToken;
+ bool result = false;
+ int parenthesisLevel = 0;
+
+ while (!DeclLexer.LexFromRawLexer(DeclToken)) {
+ if (DeclToken.getKind() == tok::TokenKind::l_paren)
+ parenthesisLevel++;
+ if (DeclToken.getKind() == tok::TokenKind::r_paren)
+ parenthesisLevel--;
+ if (DeclToken.getKind() == tok::TokenKind::semi)
+ break;
+ // if there is comma and we are not between open parenthesis then it is
+ // two or more declatarions in this chain
+ if (parenthesisLevel == 0 && DeclToken.getKind() == tok::TokenKind::comma)
+ return false;
+
+ if (DeclToken.isOneOf(tok::TokenKind::identifier,
+ tok::TokenKind::raw_identifier)) {
+ auto TokenStr = DeclToken.getRawIdentifier().str();
+
+ if (TokenStr == "typedef") {
+ ResultRange =
+ SourceRange(DeclToken.getLocation(), DeclToken.getEndLoc());
+ result = true;
+ }
+ }
+ }
+ // assert if there was keyword 'typedef' in declaration
+ assert(result && "No typedef found");
+
+ return result;
+}
+
+void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedDecl = Result.Nodes.getNodeAs<TypedefDecl>("typedef");
+ if (MatchedDecl->getLocation().isInvalid())
+ return;
+
+ auto &Context = *Result.Context;
+ auto &SM = *Result.SourceManager;
+
+ auto Diag =
+ diag(MatchedDecl->getLocStart(), "use 'using' instead of 'typedef'");
+ if (MatchedDecl->getLocStart().isMacroID()) {
+ return;
+ }
+ SourceRange RemovalRange;
+ if (CheckRemoval(SM, MatchedDecl->getLocStart(), MatchedDecl->getLocEnd(),
+ Context, RemovalRange)) {
+ Diag << FixItHint::CreateReplacement(
+ MatchedDecl->getSourceRange(),
+ "using " + MatchedDecl->getNameAsString() + " = " +
+ MatchedDecl->getUnderlyingType().getAsString(getLangOpts()));
+ }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
new file mode 100644
index 0000000..f1c70de
--- /dev/null
+++ b/clang-tools-extra/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 {
+
+/// Check finds typedefs and replaces it with usings.
+///
+/// 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
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 0aa68b0..9026da9d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -225,6 +225,11 @@ identified. The improvements since the 3.8 release include:
Finds calls that could be changed to emplace.
+- New `modernize-use-using
+ <http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-using.html>`_ check
+
+ Finds typedefs and replaces it with usings.
+
- New `performance-faster-string-find
<http://clang.llvm.org/extra/clang-tidy/checks/performance-faster-string-find.html>`_ check
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 96e59d7..f2cf6a2 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -107,6 +107,7 @@ Clang-Tidy Checks
modernize-use-emplace
modernize-use-nullptr
modernize-use-override
+ modernize-use-using
performance-faster-string-find
performance-for-range-copy
performance-implicit-cast-in-loop
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
new file mode 100644
index 0000000..72d88de
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
@@ -0,0 +1,26 @@
+.. 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 variable = int;
+
+ class Class{};
+ using MyPtrType = void (Class::*)() const;
+
+This check requires using C++11 or higher to run.
diff --git a/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp b/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp
new file mode 100644
index 0000000..b2c6450
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp
@@ -0,0 +1,87 @@
+// 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'
+// CHECK-FIXES: using LL = long;
+
+typedef int Bla;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bla = int;
+
+typedef Bla Bla2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bla2 = Bla;
+
+typedef void (*type)(int, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using type = void (*)(int, int);
+
+typedef void (*type2)();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using type2 = void (*)();
+
+class Class {
+ typedef long long Type;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+ // CHECK-FIXES: using Type = long long;
+};
+
+typedef void (Class::*MyPtrType)(Bla) const;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using MyPtrType = void (Class::*)(Bla) const;
+
+class Iterable {
+public:
+ class Iterator {};
+};
+
+template <typename T>
+class Test {
+ typedef typename T::iterator Iter;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+ // 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'
+// CHECK-FIXES: using PtrType = void (A::*)(int, int) const;
+
+typedef Class some_class;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using some_class = Class;
+
+typedef Class Cclass;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Cclass = Class;
+
+typedef Cclass cclass2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using cclass2 = Cclass;
+
+class cclass {};
+
+typedef void (cclass::*MyPtrType3)(Bla);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using MyPtrType3 = void (cclass::*)(Bla);
+
+using my_class = int;
+
+typedef Test<my_class *> another;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using another = Test<my_class *>;
+
+typedef int bla1, bla2, bla3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+
+#define CODE typedef int INT
+
+CODE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'