11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
15 using namespace clang::ast_matchers;
20 void UnusedParametersCheck::registerMatchers(MatchFinder *
Finder) {
21 Finder->addMatcher(functionDecl().bind(
"function"),
this);
26 const T *PrevNode,
const T *Node,
29 return CharSourceRange::getCharRange(Node->getLocStart(),
30 NextNode->getLocStart());
33 return CharSourceRange::getTokenRange(
34 Lexer::getLocForEndOfToken(PrevNode->getLocEnd(), 0,
35 *Result.SourceManager,
36 Result.Context->getLangOpts()),
39 return CharSourceRange::getTokenRange(Node->getSourceRange());
43 const FunctionDecl *Function,
unsigned Index) {
45 Result, Index > 0 ? Function->getParamDecl(Index - 1) :
nullptr,
46 Function->getParamDecl(Index),
47 Index + 1 < Function->getNumParams() ? Function->getParamDecl(Index + 1)
52 const CallExpr *Call,
unsigned Index) {
54 Result, Index > 0 ? Call->getArg(Index - 1) :
nullptr,
56 Index + 1 < Call->getNumArgs() ? Call->getArg(Index + 1) :
nullptr));
59 void UnusedParametersCheck::warnOnUnusedParameter(
60 const MatchFinder::MatchResult &
Result,
const FunctionDecl *Function,
61 unsigned ParamIndex) {
62 const auto *Param = Function->getParamDecl(ParamIndex);
63 auto MyDiag = diag(Param->getLocation(),
"parameter '%0' is unused")
66 auto UsedByRef = [&] {
67 return !ast_matchers::match(
69 declRefExpr(to(equalsNode(Function)),
71 callExpr(callee(equalsNode(Function)))))))),
72 *Result.Context->getTranslationUnitDecl(), *Result.Context)
77 if (Function->isExternallyVisible() ||
78 !Result.SourceManager->isInMainFile(Function->getLocation()) ||
80 SourceRange RemovalRange(Param->getLocation(), Param->getLocEnd());
84 MyDiag << FixItHint::CreateReplacement(
85 RemovalRange, (Twine(
" /*") + Param->getName() +
"*/").str());
90 for (
const FunctionDecl *FD : Function->redecls())
95 auto CallMatches = ast_matchers::match(
96 decl(forEachDescendant(
97 callExpr(callee(functionDecl(equalsNode(Function)))).bind(
"x"))),
98 *Result.Context->getTranslationUnitDecl(), *Result.Context);
99 for (
const auto &Match : CallMatches)
104 void UnusedParametersCheck::check(
const MatchFinder::MatchResult &Result) {
105 const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>(
"function");
106 if (!Function->doesThisDeclarationHaveABody() ||
107 !Function->hasWrittenPrototype())
109 if (
const auto *Method = dyn_cast<CXXMethodDecl>(Function))
110 if (Method->isLambdaStaticInvoker())
112 for (
unsigned i = 0, e = Function->getNumParams(); i != e; ++i) {
113 const auto *Param = Function->getParamDecl(i);
114 if (Param->isUsed() || Param->isReferenced() || !Param->getDeclName() ||
115 Param->hasAttr<UnusedAttr>())
117 warnOnUnusedParameter(Result, Function, i);
std::unique_ptr< ast_matchers::MatchFinder > Finder
static FixItHint removeArgument(const MatchFinder::MatchResult &Result, const CallExpr *Call, unsigned Index)
static FixItHint removeParameter(const MatchFinder::MatchResult &Result, const FunctionDecl *Function, unsigned Index)
static CharSourceRange removeNode(const MatchFinder::MatchResult &Result, const T *PrevNode, const T *Node, const T *NextNode)