10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "clang/Lex/Lexer.h" 24 return isa<RecordDecl>(TargetDecl) || isa<ClassTemplateDecl>(TargetDecl) ||
25 isa<FunctionDecl>(TargetDecl) || isa<VarDecl>(TargetDecl) ||
26 isa<FunctionTemplateDecl>(TargetDecl) || isa<EnumDecl>(TargetDecl) ||
27 isa<EnumConstantDecl>(TargetDecl);
30 void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) {
31 Finder->addMatcher(usingDecl(isExpansionInMainFile()).bind(
"using"),
this);
32 auto DeclMatcher = hasDeclaration(namedDecl().bind(
"used"));
33 Finder->addMatcher(loc(enumType(DeclMatcher)),
this);
34 Finder->addMatcher(loc(recordType(DeclMatcher)),
this);
35 Finder->addMatcher(loc(templateSpecializationType(DeclMatcher)),
this);
36 Finder->addMatcher(declRefExpr().bind(
"used"),
this);
37 Finder->addMatcher(callExpr(callee(unresolvedLookupExpr().bind(
"used"))),
40 callExpr(hasDeclaration(functionDecl(hasAnyTemplateArgument(
41 anyOf(refersToTemplate(templateName().bind(
"used")),
42 refersToDeclaration(functionDecl().bind(
"used"))))))),
44 Finder->addMatcher(loc(templateSpecializationType(hasAnyTemplateArgument(
45 templateArgument().bind(
"used")))),
49 void UnusedUsingDeclsCheck::check(
const MatchFinder::MatchResult &
Result) {
50 if (Result.Context->getDiagnostics().hasUncompilableErrorOccurred())
53 if (
const auto *Using = Result.Nodes.getNodeAs<UsingDecl>(
"using")) {
55 if (Using->getLocation().isMacroID())
59 if (isa<CXXRecordDecl>(Using->getDeclContext()))
65 if (isa<FunctionDecl>(Using->getDeclContext()))
68 UsingDeclContext Context(Using);
69 Context.UsingDeclRange = CharSourceRange::getCharRange(
71 Lexer::findLocationAfterToken(
72 Using->getEndLoc(), tok::semi, *Result.SourceManager, getLangOpts(),
74 for (
const auto *UsingShadow : Using->shadows()) {
75 const auto *TargetDecl = UsingShadow->getTargetDecl()->getCanonicalDecl();
77 Context.UsingTargetDecls.insert(TargetDecl);
79 if (!Context.UsingTargetDecls.empty())
80 Contexts.push_back(Context);
88 if (
const auto *Used = Result.Nodes.getNodeAs<NamedDecl>(
"used")) {
89 if (
const auto *FD = dyn_cast<FunctionDecl>(Used)) {
90 removeFromFoundDecls(FD->getPrimaryTemplate());
91 }
else if (
const auto *Specialization =
92 dyn_cast<ClassTemplateSpecializationDecl>(Used)) {
93 Used = Specialization->getSpecializedTemplate();
95 removeFromFoundDecls(Used);
99 if (
const auto *Used = Result.Nodes.getNodeAs<TemplateArgument>(
"used")) {
101 if (Used->getKind() == TemplateArgument::Template) {
102 if (
const auto *TD = Used->getAsTemplate().getAsTemplateDecl())
103 removeFromFoundDecls(TD);
105 if (
auto *RD = Used->getAsType()->getAsCXXRecordDecl())
106 removeFromFoundDecls(RD);
111 if (
const auto *Used = Result.Nodes.getNodeAs<TemplateName>(
"used")) {
112 removeFromFoundDecls(Used->getAsTemplateDecl());
116 if (
const auto *DRE = Result.Nodes.getNodeAs<DeclRefExpr>(
"used")) {
117 if (
const auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
118 if (
const auto *FDT = FD->getPrimaryTemplate())
119 removeFromFoundDecls(FDT);
121 removeFromFoundDecls(FD);
122 }
else if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
123 removeFromFoundDecls(VD);
124 }
else if (
const auto *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
125 removeFromFoundDecls(ECD);
126 if (
const auto *ET = ECD->getType()->getAs<EnumType>())
127 removeFromFoundDecls(ET->getDecl());
131 if (
const auto *ULE = Result.Nodes.getNodeAs<UnresolvedLookupExpr>(
"used")) {
132 for (
const NamedDecl *ND : ULE->decls()) {
133 if (
const auto *USD = dyn_cast<UsingShadowDecl>(ND))
134 removeFromFoundDecls(USD->getTargetDecl()->getCanonicalDecl());
139 void UnusedUsingDeclsCheck::removeFromFoundDecls(
const Decl *
D) {
147 for (
auto &Context : Contexts) {
148 if (Context.UsingTargetDecls.count(D->getCanonicalDecl()) > 0)
149 Context.IsUsed =
true;
153 void UnusedUsingDeclsCheck::onEndOfTranslationUnit() {
154 for (
const auto &Context : Contexts) {
155 if (!Context.IsUsed) {
156 diag(Context.FoundUsingDecl->getLocation(),
"using decl %0 is unused")
157 << Context.FoundUsingDecl;
159 diag(Context.FoundUsingDecl->getLocation(),
160 "remove the using", DiagnosticIDs::Note)
161 << FixItHint::CreateRemoval(Context.UsingDeclRange);
static bool ShouldCheckDecl(const Decl *TargetDecl)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result