diff --git a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp --- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -37,13 +37,11 @@ Finder->addMatcher(callExpr(callee(unresolvedLookupExpr().bind("used"))), this); Finder->addMatcher( - callExpr(hasDeclaration(functionDecl(hasAnyTemplateArgument( - anyOf(refersToTemplate(templateName().bind("used")), - refersToDeclaration(functionDecl().bind("used"))))))), + callExpr(hasDeclaration(functionDecl(hasAnyTemplateArgument(anything())) + .bind("used_template_args"))), this); - Finder->addMatcher(loc(templateSpecializationType(hasAnyTemplateArgument( - templateArgument().bind("used")))), - this); + Finder->addMatcher( + loc(templateSpecializationType().bind("used_template_args")), this); } void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { @@ -85,47 +83,57 @@ // corresponding using declaration has been found. // FIXME: This currently doesn't look at whether the type reference is // actually found with the help of the using declaration. - if (const auto *Used = Result.Nodes.getNodeAs("used")) { + auto RemoveNamedDecl = [&](const NamedDecl *Used) { + removeFromFoundDecls(Used); if (const auto *FD = dyn_cast(Used)) { removeFromFoundDecls(FD->getPrimaryTemplate()); } else if (const auto *Specialization = dyn_cast(Used)) { - Used = Specialization->getSpecializedTemplate(); + removeFromFoundDecls(Specialization->getSpecializedTemplate()); + } else if (const auto *FD = dyn_cast(Used)) { + if (const auto *FDT = FD->getPrimaryTemplate()) + removeFromFoundDecls(FDT); + } else if (const auto *ECD = dyn_cast(Used)) { + if (const auto *ET = ECD->getType()->getAs()) + removeFromFoundDecls(ET->getDecl()); } - removeFromFoundDecls(Used); + }; + + if (const auto *Used = Result.Nodes.getNodeAs("used")) { + RemoveNamedDecl(Used); return; } - if (const auto *Used = Result.Nodes.getNodeAs("used")) { - // FIXME: Support non-type template parameters. - if (Used->getKind() == TemplateArgument::Template) { - if (const auto *TD = Used->getAsTemplate().getAsTemplateDecl()) - removeFromFoundDecls(TD); - } else if (Used->getKind() == TemplateArgument::Type) { - if (auto *RD = Used->getAsType()->getAsCXXRecordDecl()) - removeFromFoundDecls(RD); - } + if (const auto *DRE = Result.Nodes.getNodeAs("used")) { + RemoveNamedDecl(DRE->getDecl()); return; } - - if (const auto *Used = Result.Nodes.getNodeAs("used")) { - removeFromFoundDecls(Used->getAsTemplateDecl()); + + auto RemoveIfUsedInTemplateArguments = + [&](llvm::ArrayRef TemplateArgs) { + for (const auto &Arg : TemplateArgs) { + if (Arg.getKind() == TemplateArgument::Template) { + if (const auto *TD = Arg.getAsTemplate().getAsTemplateDecl()) + RemoveNamedDecl(TD); + } else if (Arg.getKind() == TemplateArgument::Type) { + if (auto *RD = Arg.getAsType()->getAsCXXRecordDecl()) + RemoveNamedDecl(RD); + } else if (Arg.getKind() == TemplateArgument::Declaration) { + RemoveNamedDecl(Arg.getAsDecl()); + } + } + }; + if (const auto *TFD = + Result.Nodes.getNodeAs("used_template_args")) { + if (const auto *TemplateArgs = TFD->getTemplateSpecializationArgs()) + RemoveIfUsedInTemplateArguments(TemplateArgs->asArray()); return; } - - 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); - } else if (const auto *ECD = dyn_cast(DRE->getDecl())) { - removeFromFoundDecls(ECD); - if (const auto *ET = ECD->getType()->getAs()) - removeFromFoundDecls(ET->getDecl()); - } + if (const auto *U = Result.Nodes.getNodeAs( + "used_template_args")) { + RemoveIfUsedInTemplateArguments( + llvm::makeArrayRef(U->getArgs(), U->getNumArgs())); + return; } // Check the uninstantiated template function usage. if (const auto *ULE = Result.Nodes.getNodeAs("used")) { diff --git a/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp b/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp --- a/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp +++ b/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp @@ -29,6 +29,10 @@ class N {}; template class P {}; + +template +class Q {}; + const int Constant = 0; class Base { @@ -169,6 +173,8 @@ using n::Constant; // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Constant' is unused +using n::Q; + // ----- Usages ----- void f(B b); void g() { @@ -202,3 +208,7 @@ template void i(n::P* t) {} template void i(n::P* t); + +template class U> +class Bar {}; +Bar *bar;