Index: clang-tidy/misc/UnusedUsingDeclsCheck.h =================================================================== --- clang-tidy/misc/UnusedUsingDeclsCheck.h +++ clang-tidy/misc/UnusedUsingDeclsCheck.h @@ -30,6 +30,7 @@ void onEndOfTranslationUnit() override; private: + void removeFromFoundDecls(const Decl *D); llvm::DenseMap FoundDecls; llvm::DenseMap FoundRanges; }; Index: clang-tidy/misc/UnusedUsingDeclsCheck.cpp =================================================================== --- clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -23,6 +23,7 @@ auto DeclMatcher = hasDeclaration(namedDecl().bind("used")); Finder->addMatcher(loc(recordType(DeclMatcher)), this); Finder->addMatcher(loc(templateSpecializationType(DeclMatcher)), this); + Finder->addMatcher(declRefExpr().bind("used"), this); } void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { @@ -34,8 +35,9 @@ const auto *TargetDecl = Using->shadow_begin()->getTargetDecl()->getCanonicalDecl(); - // FIXME: Handle other target types. - if (!isa(TargetDecl) && !isa(TargetDecl)) + if (!isa(TargetDecl) && !isa(TargetDecl) && + !isa(TargetDecl) && !isa(TargetDecl) && + !isa(TargetDecl)) return; FoundDecls[TargetDecl] = Using; @@ -57,12 +59,26 @@ if (const auto *Specialization = dyn_cast(Used)) Used = Specialization->getSpecializedTemplate(); - auto I = FoundDecls.find(Used->getCanonicalDecl()); - if (I != FoundDecls.end()) - I->second = nullptr; + removeFromFoundDecls(Used->getCanonicalDecl()); + } else if (const auto *DRE = Result.Nodes.getNodeAs("used")) { + if (const auto *FD = dyn_cast(DRE->getDecl())) { + if (const auto *FDT = FD->getPrimaryTemplate()) { + removeFromFoundDecls(FDT); + } else { + removeFromFoundDecls(FD); + } + } else if (const auto *VD = dyn_cast(DRE->getDecl())) { + removeFromFoundDecls(VD); + } } } +void UnusedUsingDeclsCheck::removeFromFoundDecls(const Decl *D) { + auto I = FoundDecls.find(D); + if (I != FoundDecls.end()) + I->second = nullptr; +} + void UnusedUsingDeclsCheck::onEndOfTranslationUnit() { for (const auto &FoundDecl : FoundDecls) { if (FoundDecl.second == nullptr) Index: test/clang-tidy/misc-unused-using-decls.cpp =================================================================== --- test/clang-tidy/misc-unused-using-decls.cpp +++ test/clang-tidy/misc-unused-using-decls.cpp @@ -10,6 +10,21 @@ class D { public: static int i; }; template class E {}; template class F {}; + +D UsedInstance; +D UnusedInstance; + +int UsedFunc() { return 1; } +int UnusedFunc() { return 1; } +template int UsedTemplateFunc() { return 1; } +template int UnusedTemplateFunc() { return 1; } + +class ostream { +public: + ostream &operator<<(ostream &(*PF)(ostream &)); +}; +extern ostream cout; +ostream &endl(ostream &os); } // ----- Using declarations ----- @@ -24,6 +39,15 @@ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'E' is unused // CHECK-FIXES: {{^}}// E using n::F; +using n::UsedInstance; +using n::UsedFunc; +using n::UsedTemplateFunc; +using n::UnusedInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'UnusedInstance' is unused +using n::UnusedFunc; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'UnusedFunc' is unused +using n::cout; +using n::endl; // ----- Usages ----- void f(B b); @@ -31,5 +55,9 @@ vector data; D::i = 1; F f; + UsedInstance.i; + UsedFunc(); + UsedTemplateFunc(); + cout << endl; }