Index: clang-tools-extra/trunk/clang-tidy/misc/UnusedUsingDeclsCheck.h =================================================================== --- clang-tools-extra/trunk/clang-tidy/misc/UnusedUsingDeclsCheck.h +++ clang-tools-extra/trunk/clang-tidy/misc/UnusedUsingDeclsCheck.h @@ -36,9 +36,15 @@ struct UsingDeclContext { explicit UsingDeclContext(const UsingDecl *FoundUsingDecl) : FoundUsingDecl(FoundUsingDecl), IsUsed(false) {} + // A set saves all UsingShadowDecls introduced by a UsingDecl. A UsingDecl + // can introduce multiple UsingShadowDecls in some cases (such as + // overloaded functions). llvm::SmallPtrSet UsingTargetDecls; + // The original UsingDecl. const UsingDecl *FoundUsingDecl; + // The source range of the UsingDecl. CharSourceRange UsingDeclRange; + // Whether the UsingDecl is used. bool IsUsed; }; Index: clang-tools-extra/trunk/clang-tidy/misc/UnusedUsingDeclsCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -41,11 +41,17 @@ if (const auto *Using = Result.Nodes.getNodeAs("using")) { // Ignores using-declarations defined in macros. if (Using->getLocation().isMacroID()) - return ; + return; // Ignores using-declarations defined in class definition. if (isa(Using->getDeclContext())) - return ; + return; + + // FIXME: We ignore using-decls defined in function definitions at the + // moment because of false positives caused by ADL and different function + // scopes. + if (isa(Using->getDeclContext())) + return; UsingDeclContext Context(Using); Context.UsingDeclRange = CharSourceRange::getCharRange( @@ -97,11 +103,14 @@ } void UnusedUsingDeclsCheck::removeFromFoundDecls(const Decl *D) { + // 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. + // + // FIXME: Use a more efficient way to find a matching context. for (auto &Context : Contexts) { - if (Context.UsingTargetDecls.count(D->getCanonicalDecl()) > 0) { + if (Context.UsingTargetDecls.count(D->getCanonicalDecl()) > 0) Context.IsUsed = true; - break; - } } } Index: clang-tools-extra/trunk/test/clang-tidy/misc-unused-using-decls.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/misc-unused-using-decls.cpp +++ clang-tools-extra/trunk/test/clang-tidy/misc-unused-using-decls.cpp @@ -17,6 +17,8 @@ static int ii; }; template class J {}; +class G; +class H; class Base { public: @@ -99,6 +101,24 @@ USING_FUNC #undef USING_FUNC +namespace N1 { +// n::G is used in namespace N2. +// Currently, the check doesn't support multiple scopes. All the relevant +// using-decls will be marked as used once we see an usage even the usage is in +// other scope. +using n::G; +} + +namespace N2 { +using n::G; +void f(G g); +} + +void IgnoreFunctionScope() { +// Using-decls defined in function scope will be ignored. +using n::H; +} + // ----- Usages ----- void f(B b); void g() { @@ -112,4 +132,3 @@ UsedTemplateFunc(); cout << endl; } -