11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers;
20 void UseUsingCheck::registerMatchers(MatchFinder *
Finder) {
21 if (!getLangOpts().CPlusPlus11)
23 Finder->addMatcher(typedefDecl().bind(
"typedef"),
this);
29 const SourceLocation &LocEnd, ASTContext &
Context,
30 SourceRange &ResultRange) {
31 FileID FID = SM.getFileID(LocEnd);
32 llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd);
33 Lexer DeclLexer(SM.getLocForStartOfFile(FID), Context.getLangOpts(),
34 Buffer->getBufferStart(), SM.getCharacterData(LocStart),
35 Buffer->getBufferEnd());
38 int parenthesisLevel = 0;
40 while (!DeclLexer.LexFromRawLexer(DeclToken)) {
41 if (DeclToken.getKind() == tok::TokenKind::l_paren)
43 if (DeclToken.getKind() == tok::TokenKind::r_paren)
45 if (DeclToken.getKind() == tok::TokenKind::semi)
49 if (parenthesisLevel == 0 && DeclToken.getKind() == tok::TokenKind::comma)
52 if (DeclToken.isOneOf(tok::TokenKind::identifier,
53 tok::TokenKind::raw_identifier)) {
54 auto TokenStr = DeclToken.getRawIdentifier().str();
56 if (TokenStr ==
"typedef") {
58 SourceRange(DeclToken.getLocation(), DeclToken.getEndLoc());
64 assert(result &&
"No typedef found");
69 void UseUsingCheck::check(
const MatchFinder::MatchResult &
Result) {
70 const auto *MatchedDecl = Result.Nodes.getNodeAs<TypedefDecl>(
"typedef");
71 if (MatchedDecl->getLocation().isInvalid())
74 auto &
Context = *Result.Context;
75 auto &
SM = *Result.SourceManager;
78 diag(MatchedDecl->getLocStart(),
"use 'using' instead of 'typedef'");
79 if (MatchedDecl->getLocStart().isMacroID()) {
82 SourceRange RemovalRange;
83 if (
CheckRemoval(
SM, MatchedDecl->getLocStart(), MatchedDecl->getLocEnd(),
85 Diag << FixItHint::CreateReplacement(
86 MatchedDecl->getSourceRange(),
87 "using " + MatchedDecl->getNameAsString() +
" = " +
88 MatchedDecl->getUnderlyingType().getAsString(getLangOpts()));
std::unique_ptr< ast_matchers::MatchFinder > Finder
ClangTidyContext & Context
static bool CheckRemoval(SourceManager &SM, const SourceLocation &LocStart, const SourceLocation &LocEnd, ASTContext &Context, SourceRange &ResultRange)