1 //===--- UnusedUsingDeclsCheck.cpp - clang-tidy----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "UnusedUsingDeclsCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/Lex/Lexer.h" 14 15 using namespace clang::ast_matchers; 16 17 namespace clang { 18 namespace tidy { 19 namespace misc { 20 21 void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) { 22 Finder->addMatcher(usingDecl(isExpansionInMainFile()).bind("using"), this); 23 auto DeclMatcher = hasDeclaration(namedDecl().bind("used")); 24 Finder->addMatcher(loc(recordType(DeclMatcher)), this); 25 Finder->addMatcher(loc(templateSpecializationType(DeclMatcher)), this); 26 } 27 28 void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { 29 if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) { 30 // FIXME: Implement the correct behavior for using declarations with more 31 // than one shadow. 32 if (Using->shadow_size() != 1) 33 return; 34 const auto *TargetDecl = 35 Using->shadow_begin()->getTargetDecl()->getCanonicalDecl(); 36 37 // FIXME: Handle other target types. 38 if (!isa<RecordDecl>(TargetDecl) && !isa<ClassTemplateDecl>(TargetDecl)) 39 return; 40 41 FoundDecls[TargetDecl] = Using; 42 FoundRanges[TargetDecl] = CharSourceRange::getCharRange( 43 Using->getLocStart(), 44 Lexer::findLocationAfterToken( 45 Using->getLocEnd(), tok::semi, *Result.SourceManager, 46 Result.Context->getLangOpts(), 47 /*SkipTrailingWhitespaceAndNewLine=*/true)); 48 return; 49 } 50 51 // Mark using declarations as used by setting FoundDecls' value to zero. As 52 // the AST is walked in order, usages are only marked after a the 53 // corresponding using declaration has been found. 54 // FIXME: This currently doesn't look at whether the type reference is 55 // actually found with the help of the using declaration. 56 if (const auto *Used = Result.Nodes.getNodeAs<NamedDecl>("used")) { 57 if (const auto *Specialization = 58 dyn_cast<ClassTemplateSpecializationDecl>(Used)) 59 Used = Specialization->getSpecializedTemplate(); 60 auto I = FoundDecls.find(Used->getCanonicalDecl()); 61 if (I != FoundDecls.end()) 62 I->second = nullptr; 63 } 64 } 65 66 void UnusedUsingDeclsCheck::onEndOfTranslationUnit() { 67 for (const auto &FoundDecl : FoundDecls) { 68 if (FoundDecl.second == nullptr) 69 continue; 70 diag(FoundDecl.second->getLocation(), "using decl %0 is unused") 71 << FoundDecl.second 72 << FixItHint::CreateRemoval(FoundRanges[FoundDecl.first]); 73 } 74 FoundDecls.clear(); 75 } 76 77 } // namespace misc 78 } // namespace tidy 79 } // namespace clang 80