diff options
author | Krystyna Gajczyk <krystyna.gajczyk@gmail.com> | 2016-06-25 18:37:53 +0000 |
---|---|---|
committer | Krystyna Gajczyk <krystyna.gajczyk@gmail.com> | 2016-06-25 18:37:53 +0000 |
commit | c37933a12ad181db3f5f40bb99318f8eb7f25903 (patch) | |
tree | 943642627813d91d65d9361e9ac5ff694ba2fc18 /clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp | |
parent | 3bc1af2be470106c961fdae4d08fdbe444a2114d (diff) | |
download | llvm-c37933a12ad181db3f5f40bb99318f8eb7f25903.zip llvm-c37933a12ad181db3f5f40bb99318f8eb7f25903.tar.gz llvm-c37933a12ad181db3f5f40bb99318f8eb7f25903.tar.bz2 |
[clang-tidy] Add modernize-use-using
http://reviews.llvm.org/D18919
llvm-svn: 273786
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp')
-rw-r--r-- | clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
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 |