diff options
author | Haojian Wu <hokein@google.com> | 2016-05-20 08:34:32 +0000 |
---|---|---|
committer | Haojian Wu <hokein@google.com> | 2016-05-20 08:34:32 +0000 |
commit | 1cea6e553117b25eb1a97e6b95508591af5da63e (patch) | |
tree | aa825c420cea0dad0679dc20687a68ceff7ca509 /clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp | |
parent | 86f1f4ca7724471cc027f31d777b8457c23ecebc (diff) | |
download | bcm5719-llvm-1cea6e553117b25eb1a97e6b95508591af5da63e.tar.gz bcm5719-llvm-1cea6e553117b25eb1a97e6b95508591af5da63e.zip |
[clang-tidy] Handle using-decls with more than one shadow decl.
Reviewers: alexfh
Subscribers: cfe-commits, djasper
Differential Revision: http://reviews.llvm.org/D20429
llvm-svn: 270191
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp')
-rw-r--r-- | clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp index 1fe8f3cdfc0..1785886e291 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -18,6 +18,25 @@ namespace clang { namespace tidy { namespace misc { +// A function that helps to tell whether a TargetDecl will be checked. +// We only check a TargetDecl if : +// * The corresponding UsingDecl is not defined in macros or in class +// definitions. +// * Only variable, function and class types are considered. +static bool ShouldCheckDecl(const Decl *TargetDecl) { + // Ignores using-declarations defined in macros. + if (TargetDecl->getLocation().isMacroID()) + return false; + + // Ignores using-declarations defined in class definition. + if (isa<CXXRecordDecl>(TargetDecl->getDeclContext())) + return false; + + return isa<RecordDecl>(TargetDecl) || isa<ClassTemplateDecl>(TargetDecl) || + isa<FunctionDecl>(TargetDecl) || isa<VarDecl>(TargetDecl) || + isa<FunctionTemplateDecl>(TargetDecl); +} + void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(usingDecl(isExpansionInMainFile()).bind("using"), this); auto DeclMatcher = hasDeclaration(namedDecl().bind("used")); @@ -30,33 +49,20 @@ void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) { void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) { - // FIXME: Implement the correct behavior for using declarations with more - // than one shadow. - if (Using->shadow_size() != 1) - return; - const auto *TargetDecl = - Using->shadow_begin()->getTargetDecl()->getCanonicalDecl(); - - // Ignores using-declarations defined in macros. - if (TargetDecl->getLocation().isMacroID()) - return; - - // Ignores using-declarations defined in class definition. - if (isa<CXXRecordDecl>(TargetDecl->getDeclContext())) - return; - - if (!isa<RecordDecl>(TargetDecl) && !isa<ClassTemplateDecl>(TargetDecl) && - !isa<FunctionDecl>(TargetDecl) && !isa<VarDecl>(TargetDecl) && - !isa<FunctionTemplateDecl>(TargetDecl)) - return; - - FoundDecls[TargetDecl] = Using; - FoundRanges[TargetDecl] = CharSourceRange::getCharRange( + UsingDeclContext Context(Using); + Context.UsingDeclRange = CharSourceRange::getCharRange( Using->getLocStart(), Lexer::findLocationAfterToken( Using->getLocEnd(), tok::semi, *Result.SourceManager, Result.Context->getLangOpts(), /*SkipTrailingWhitespaceAndNewLine=*/true)); + for (const auto *UsingShadow : Using->shadows()) { + const auto *TargetDecl = UsingShadow->getTargetDecl()->getCanonicalDecl(); + if (ShouldCheckDecl(TargetDecl)) + Context.UsingTargetDecls.insert(TargetDecl); + } + if (!Context.UsingTargetDecls.empty()) + Contexts.push_back(Context); return; } @@ -93,20 +99,23 @@ void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { } void UnusedUsingDeclsCheck::removeFromFoundDecls(const Decl *D) { - auto I = FoundDecls.find(D->getCanonicalDecl()); - if (I != FoundDecls.end()) - I->second = nullptr; + for (auto &Context : Contexts) { + if (Context.UsingTargetDecls.count(D->getCanonicalDecl()) > 0) { + Context.IsUsed = true; + break; + } + } } void UnusedUsingDeclsCheck::onEndOfTranslationUnit() { - for (const auto &FoundDecl : FoundDecls) { - if (FoundDecl.second == nullptr) - continue; - diag(FoundDecl.second->getLocation(), "using decl %0 is unused") - << FoundDecl.second - << FixItHint::CreateRemoval(FoundRanges[FoundDecl.first]); + for (const auto &Context : Contexts) { + if (!Context.IsUsed) { + diag(Context.FoundUsingDecl->getLocation(), "using decl %0 is unused") + << Context.FoundUsingDecl + << FixItHint::CreateRemoval(Context.UsingDeclRange); + } } - FoundDecls.clear(); + Contexts.clear(); } } // namespace misc |