blob: 02cb6216e38c7fa8d98777ecaf2dcabe81fec81f [file] [log] [blame]
Daniel Jasper9c6df882015-07-20 01:06:44 +00001//===--- UnusedParametersCheck.cpp - clang-tidy----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "UnusedParametersCheck.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13
14using namespace clang::ast_matchers;
15
16namespace clang {
17namespace tidy {
18
19void UnusedParametersCheck::registerMatchers(MatchFinder *Finder) {
Daniel Jasper9fe55a322015-07-27 13:46:37 +000020 Finder->addMatcher(functionDecl().bind("function"), this);
Daniel Jasper9c6df882015-07-20 01:06:44 +000021}
22
Daniel Jasper82efabb2015-07-20 03:42:38 +000023static FixItHint removeParameter(const FunctionDecl *Function, unsigned Index) {
24 const ParmVarDecl *Param = Function->getParamDecl(Index);
25 unsigned ParamCount = Function->getNumParams();
26 SourceRange RemovalRange = Param->getSourceRange();
27 if (ParamCount == 1)
28 return FixItHint::CreateRemoval(RemovalRange);
29
30 if (Index == 0)
31 RemovalRange.setEnd(
32 Function->getParamDecl(Index + 1)->getLocStart().getLocWithOffset(-1));
33 else
34 RemovalRange.setBegin(
35 Function->getParamDecl(Index - 1)->getLocEnd().getLocWithOffset(1));
36
37 return FixItHint::CreateRemoval(RemovalRange);
38}
39
40static FixItHint removeArgument(const CallExpr *Call, unsigned Index) {
41 unsigned ArgCount = Call->getNumArgs();
42 const Expr *Arg = Call->getArg(Index);
43 SourceRange RemovalRange = Arg->getSourceRange();
44 if (ArgCount == 1)
45 return FixItHint::CreateRemoval(RemovalRange);
46 if (Index == 0)
47 RemovalRange.setEnd(
48 Call->getArg(Index + 1)->getLocStart().getLocWithOffset(-1));
49 else
50 RemovalRange.setBegin(
51 Call->getArg(Index - 1)->getLocEnd().getLocWithOffset(1));
52 return FixItHint::CreateRemoval(RemovalRange);
53}
54
Daniel Jasper9fe55a322015-07-27 13:46:37 +000055void UnusedParametersCheck::warnOnUnusedParameter(
56 const MatchFinder::MatchResult &Result, const FunctionDecl *Function,
57 unsigned ParamIndex) {
58 const auto *Param = Function->getParamDecl(ParamIndex);
Daniel Jasper9c6df882015-07-20 01:06:44 +000059 auto MyDiag = diag(Param->getLocation(), "parameter '%0' is unused")
60 << Param->getName();
61
Daniel Jasper82efabb2015-07-20 03:42:38 +000062 auto UsedByRef = [&] {
63 return !ast_matchers::match(
64 decl(hasDescendant(
65 declRefExpr(to(equalsNode(Function)),
66 unless(hasAncestor(
67 callExpr(callee(equalsNode(Function)))))))),
68 *Result.Context->getTranslationUnitDecl(), *Result.Context)
69 .empty();
70 };
71
72 // Comment out parameter name for non-local functions.
73 if ((Function->isExternallyVisible() &&
74 Function->getStorageClass() != StorageClass::SC_Static) ||
75 UsedByRef()) {
76 SourceRange RemovalRange(Param->getLocation(), Param->getLocEnd());
77 MyDiag << FixItHint::CreateReplacement(
78 RemovalRange, (Twine(" /*") + Param->getName() + "*/").str());
79 return;
80 }
81
Daniel Jasper82efabb2015-07-20 03:42:38 +000082 // Fix all redeclarations.
83 for (const FunctionDecl *FD : Function->redecls())
84 MyDiag << removeParameter(FD, ParamIndex);
85
86 // Fix all call sites.
87 auto CallMatches = ast_matchers::match(
88 decl(forEachDescendant(
89 callExpr(callee(functionDecl(equalsNode(Function)))).bind("x"))),
90 *Result.Context->getTranslationUnitDecl(), *Result.Context);
91 for (const auto &Match : CallMatches)
92 MyDiag << removeArgument(Match.getNodeAs<CallExpr>("x"), ParamIndex);
Daniel Jasper9c6df882015-07-20 01:06:44 +000093}
94
Daniel Jasper9fe55a322015-07-27 13:46:37 +000095void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) {
96 const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("function");
97 if (!Function->doesThisDeclarationHaveABody())
98 return;
99 for (unsigned i = 0, e = Function->getNumParams(); i != e; ++i) {
100 const auto *Param = Function->getParamDecl(i);
101 if (Param->isUsed() || Param->isReferenced() || !Param->getDeclName() ||
102 Param->hasAttr<UnusedAttr>())
103 continue;
104 warnOnUnusedParameter(Result, Function, i);
105 }
106}
107
Daniel Jasper9c6df882015-07-20 01:06:44 +0000108} // namespace tidy
109} // namespace clang