11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
15 using namespace clang::ast_matchers;
23 if (
const auto *MD = dyn_cast<CXXMethodDecl>(Function))
24 return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
29 void UnusedParametersCheck::registerMatchers(MatchFinder *
Finder) {
30 Finder->addMatcher(functionDecl().bind(
"function"),
this);
35 const T *PrevNode,
const T *Node,
38 return CharSourceRange::getCharRange(Node->getLocStart(),
39 NextNode->getLocStart());
42 return CharSourceRange::getTokenRange(
43 Lexer::getLocForEndOfToken(PrevNode->getLocEnd(), 0,
44 *Result.SourceManager,
45 Result.Context->getLangOpts()),
48 return CharSourceRange::getTokenRange(Node->getSourceRange());
52 const FunctionDecl *Function,
unsigned Index) {
54 Result, Index > 0 ? Function->getParamDecl(Index - 1) :
nullptr,
55 Function->getParamDecl(Index),
56 Index + 1 < Function->getNumParams() ? Function->getParamDecl(Index + 1)
61 const CallExpr *Call,
unsigned Index) {
63 Result, Index > 0 ? Call->getArg(Index - 1) :
nullptr,
65 Index + 1 < Call->getNumArgs() ? Call->getArg(Index + 1) :
nullptr));
68 void UnusedParametersCheck::warnOnUnusedParameter(
69 const MatchFinder::MatchResult &
Result,
const FunctionDecl *Function,
70 unsigned ParamIndex) {
71 const auto *Param = Function->getParamDecl(ParamIndex);
72 auto MyDiag = diag(Param->getLocation(),
"parameter %0 is unused") << Param;
75 declRefExpr(to(equalsNode(Function)),
76 unless(hasAncestor(callExpr(callee(equalsNode(Function))))));
79 if (Function->isExternallyVisible() ||
80 !Result.SourceManager->isInMainFile(Function->getLocation()) ||
81 !ast_matchers::match(DeclRefExpr, *Result.Context).empty() ||
83 SourceRange RemovalRange(Param->getLocation(), Param->getLocEnd());
87 MyDiag << FixItHint::CreateReplacement(
88 RemovalRange, (Twine(
" /*") + Param->getName() +
"*/").str());
93 for (
const FunctionDecl *FD : Function->redecls())
98 auto CallMatches = ast_matchers::match(
99 decl(forEachDescendant(
100 callExpr(callee(functionDecl(equalsNode(Function)))).bind(
"x"))),
101 *Result.Context->getTranslationUnitDecl(), *Result.Context);
102 for (
const auto &Match : CallMatches)
107 void UnusedParametersCheck::check(
const MatchFinder::MatchResult &Result) {
108 const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>(
"function");
109 if (!Function->doesThisDeclarationHaveABody() ||
110 !Function->hasWrittenPrototype() ||
111 Function->isTemplateInstantiation())
113 if (
const auto *Method = dyn_cast<CXXMethodDecl>(Function))
114 if (Method->isLambdaStaticInvoker())
116 for (
unsigned i = 0, e = Function->getNumParams(); i != e; ++i) {
117 const auto *Param = Function->getParamDecl(i);
118 if (Param->isUsed() || Param->isReferenced() || !Param->getDeclName() ||
119 Param->hasAttr<UnusedAttr>())
121 warnOnUnusedParameter(Result, Function, i);
static FixItHint removeArgument(const MatchFinder::MatchResult &Result, const CallExpr *Call, unsigned Index)
std::unique_ptr< ast_matchers::MatchFinder > Finder
static bool isOverrideMethod(const CXXMethodDecl *MD)
Finds out if the given method overrides some method.
static CharSourceRange removeNode(const MatchFinder::MatchResult &Result, const T *PrevNode, const T *Node, const T *NextNode)
static FixItHint removeParameter(const MatchFinder::MatchResult &Result, const FunctionDecl *Function, unsigned Index)