1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 // Find places where we call a method with values == the values specified in the parameter defaults.
16 // i.e. where the code might as well not specify anything.
21 public loplugin::FilteringPlugin
<DefaultParams
>
24 explicit DefaultParams(InstantiationData
const & data
): FilteringPlugin(data
) {}
26 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
28 bool VisitCallExpr(CallExpr
* callExpr
);
30 bool evaluate(const Expr
* expr
, APSInt
& x
);
33 bool DefaultParams::VisitCallExpr(CallExpr
* callExpr
) {
34 if (ignoreLocation(callExpr
)) {
37 if (callExpr
->getDirectCallee() == nullptr) {
40 const FunctionDecl
* functionDecl
= callExpr
->getDirectCallee()->getCanonicalDecl();
41 auto n
= functionDecl
->getNumParams();
42 if (n
== 0 || !functionDecl
->getParamDecl(n
- 1)->hasDefaultArg()) {
45 assert(callExpr
->getNumArgs() <= n
); // can be < in template code
46 for (unsigned i
= callExpr
->getNumArgs(); i
!= 0;) {
48 Expr
* arg
= callExpr
->getArg(i
);
49 if (arg
->isDefaultArgument()) {
52 // ignore this, it seems to trigger an infinite recursion
53 if (isa
<UnaryExprOrTypeTraitExpr
>(arg
))
55 const ParmVarDecl
* parmVarDecl
= functionDecl
->getParamDecl(i
);
56 if (!parmVarDecl
->hasDefaultArg()
57 || parmVarDecl
->hasUninstantiatedDefaultArg())
61 const Expr
* defaultArgExpr
= parmVarDecl
->getDefaultArg();
62 if (!defaultArgExpr
) {
66 if (defaultArgExpr
->isNullPointerConstant(compiler
.getASTContext(), Expr::NPC_NeverValueDependent
)
67 && arg
->isNullPointerConstant(compiler
.getASTContext(), Expr::NPC_NeverValueDependent
))
74 if (evaluate(defaultArgExpr
, x1
) && evaluate(arg
, x2
) && x1
== x2
)
79 // catch params with defaults like "= OUString()"
81 && isa
<MaterializeTemporaryExpr
>(arg
)
82 && isa
<MaterializeTemporaryExpr
>(defaultArgExpr
))
84 const CXXBindTemporaryExpr
* strippedArg
= dyn_cast_or_null
<CXXBindTemporaryExpr
>(arg
->IgnoreParenCasts());
85 if (strippedArg
&& isa
<CXXTemporaryObjectExpr
>(strippedArg
->getSubExpr())
86 && dyn_cast
<CXXTemporaryObjectExpr
>(strippedArg
->getSubExpr())->getNumArgs() == 0)
93 // Ignore CPPUNIT, it's macros contain some stuff that triggers us
94 StringRef aFileName
= compiler
.getSourceManager().getFilename(compiler
.getSourceManager().getSpellingLoc(parmVarDecl
->getLocStart()));
95 if (aFileName
.find("include/cppunit") != std::string::npos
)
98 DiagnosticsEngine::Warning
,
99 "not necessary to pass this argument, it defaults to the same value",
100 arg
->getSourceRange().getBegin())
101 << arg
->getSourceRange();
103 DiagnosticsEngine::Note
,
104 "default method parameter declaration here",
105 parmVarDecl
->getSourceRange().getBegin())
106 << parmVarDecl
->getSourceRange();
111 bool DefaultParams::evaluate(const Expr
* expr
, APSInt
& x
)
113 if (isa
<CXXNullPtrLiteralExpr
>(expr
)) {
117 if (expr
->EvaluateAsInt(x
, compiler
.getASTContext()))
124 loplugin::Plugin::Registration
< DefaultParams
> X("defaultparams");
128 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */