hokein created this revision. hokein added reviewers: alexfh, djasper. hokein added a subscriber: cfe-commits.
The check doesn't mark the template argument as used when the template argument is a template. https://reviews.llvm.org/D22803 Files: clang-tidy/misc/UnusedUsingDeclsCheck.cpp test/clang-tidy/Inputs/unused-using-decls.h test/clang-tidy/misc-unused-using-decls.cpp
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 @@ -1,4 +1,5 @@ -// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -- -fno-delayed-template-parsing -isystem %S/Inputs/ + // ----- Definitions ----- template <typename T> class vector {}; @@ -54,6 +55,16 @@ } // namespace n +#include "unused-using-decls.h" +namespace ns { +template <typename T> +class AA { + T t; +}; +template <typename T> +T ff() { T t; return t; } +} // namespace ns + // ----- Using declarations ----- // eol-comments aren't removed (yet) using n::A; // A @@ -136,6 +147,9 @@ using n::Color3; using n::Blue; +using ns::AA; +using ns::ff; + // ----- Usages ----- void f(B b); void g() { @@ -151,4 +165,9 @@ Color2 color2; int t1 = Color3::Yellow; int t2 = Blue; + + MyClass a; + int t3 = 0; + a.func1<AA>(&t3); + a.func2<int, ff>(t3); } Index: test/clang-tidy/Inputs/unused-using-decls.h =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/unused-using-decls.h @@ -0,0 +1,11 @@ +class MyClass { +public: + template <template <typename> class S, typename T> + S<T> *func1(T *a) { + return new S<T>(); + } + template <typename T, T (*S)()> + void func2(T a) { + S(); + } +}; Index: clang-tidy/misc/UnusedUsingDeclsCheck.cpp =================================================================== --- clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -37,6 +37,9 @@ Finder->addMatcher(declRefExpr().bind("used"), this); Finder->addMatcher(callExpr(callee(unresolvedLookupExpr().bind("used"))), this); + Finder->addMatcher( + callExpr(hasDeclaration(functionDecl(isInstantiated()).bind("used"))), + this); } void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { @@ -71,16 +74,48 @@ Contexts.push_back(Context); return; } - // Mark using declarations as used by setting FoundDecls' value to zero. As // the AST is walked in order, usages are only marked after a the // 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<NamedDecl>("used")) { - if (const auto *Specialization = - dyn_cast<ClassTemplateSpecializationDecl>(Used)) + if (const auto *FD = dyn_cast<FunctionDecl>(Used)) { + // There is no straightforward way to match template arguments in a + // function call/class member call expression, so we iterate all template + // specializations of a function template to mark all template arguments + // as used. + // + // Find template argument that is provided for a template template + // parameter, e.g: + // + // template<typename T> class A { T t; }; + // B.func<A>(); + // + // Find template class A in B::func template argument. + if (const auto* TemplateArgs = FD->getTemplateSpecializationArgs()) { + for (size_t i = 0; i < TemplateArgs->size(); ++i) { + const auto& TemplateArg = TemplateArgs->get(i); + switch (TemplateArg.getKind()) { + case TemplateArgument::Template: + // Remove class template declaration. + removeFromFoundDecls( + TemplateArg.getAsTemplate().getAsTemplateDecl()); + break; + case TemplateArgument::Declaration: + // Remove function template declaration. + if (auto *FDT = dyn_cast<FunctionDecl>(TemplateArg.getAsDecl())) + removeFromFoundDecls(FDT->getPrimaryTemplate()); + break; + default: + break; + } + } + } + } else if (const auto *Specialization = + dyn_cast<ClassTemplateSpecializationDecl>(Used)) { Used = Specialization->getSpecializedTemplate(); + } removeFromFoundDecls(Used); return; } @@ -109,6 +144,8 @@ } void UnusedUsingDeclsCheck::removeFromFoundDecls(const Decl *D) { + if (!D) + return; // FIXME: Currently, we don't handle the using-decls being used in different // scopes (such as different namespaces, different functions). Instead of // giving an incorrect message, we mark all of them as used.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits