[clang-tidy] Ignore function context in misc-unused-using-decls.

Summary: Make the check's behavior more correct when handling using-decls in multiple scopes.

Reviewers: alexfh

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D20909

llvm-svn: 271632
This commit is contained in:
Haojian Wu 2016-06-03 08:05:11 +00:00
parent 5e3d314488
commit d80c7c4808
3 changed files with 40 additions and 6 deletions

View File

@ -41,11 +41,17 @@ void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) {
if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) {
// Ignores using-declarations defined in macros.
if (Using->getLocation().isMacroID())
return ;
return;
// Ignores using-declarations defined in class definition.
if (isa<CXXRecordDecl>(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<FunctionDecl>(Using->getDeclContext()))
return;
UsingDeclContext Context(Using);
Context.UsingDeclRange = CharSourceRange::getCharRange(
@ -97,11 +103,14 @@ void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) {
}
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;
}
}
}

View File

@ -36,9 +36,15 @@ private:
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<const Decl *, 4> UsingTargetDecls;
// The original UsingDecl.
const UsingDecl *FoundUsingDecl;
// The source range of the UsingDecl.
CharSourceRange UsingDeclRange;
// Whether the UsingDecl is used.
bool IsUsed;
};

View File

@ -17,6 +17,8 @@ class I {
static int ii;
};
template <typename T> class J {};
class G;
class H;
class Base {
public:
@ -99,6 +101,24 @@ DEFINE_INT(test);
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 @@ void g() {
UsedTemplateFunc<int>();
cout << endl;
}