bump product version to 6.3.0.0.beta1
[LibreOffice.git] / compilerplugins / clang / store / defaultparams.cxx
blob71a637e72c04128ae038ef435e0d805fce95c1e1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <string>
11 #include <set>
13 #include "plugin.hxx"
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.
18 namespace {
20 class DefaultParams:
21 public loplugin::FilteringPlugin<DefaultParams>
23 public:
24 explicit DefaultParams(InstantiationData const & data): FilteringPlugin(data) {}
26 virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
28 bool VisitCallExpr(CallExpr * callExpr);
29 private:
30 bool evaluate(const Expr* expr, APSInt& x);
33 bool DefaultParams::VisitCallExpr(CallExpr * callExpr) {
34 if (ignoreLocation(callExpr)) {
35 return true;
37 if (callExpr->getDirectCallee() == nullptr) {
38 return true;
40 const FunctionDecl* functionDecl = callExpr->getDirectCallee()->getCanonicalDecl();
41 auto n = functionDecl->getNumParams();
42 if (n == 0 || !functionDecl->getParamDecl(n - 1)->hasDefaultArg()) {
43 return true;
45 assert(callExpr->getNumArgs() <= n); // can be < in template code
46 for (unsigned i = callExpr->getNumArgs(); i != 0;) {
47 --i;
48 Expr* arg = callExpr->getArg(i);
49 if (arg->isDefaultArgument()) {
50 continue;
52 // ignore this, it seems to trigger an infinite recursion
53 if (isa<UnaryExprOrTypeTraitExpr>(arg))
54 break;
55 const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i);
56 if (!parmVarDecl->hasDefaultArg()
57 || parmVarDecl->hasUninstantiatedDefaultArg())
59 break;
61 const Expr* defaultArgExpr = parmVarDecl->getDefaultArg();
62 if (!defaultArgExpr) {
63 break;
65 bool found = false;
66 if (defaultArgExpr->isNullPointerConstant(compiler.getASTContext(), Expr::NPC_NeverValueDependent)
67 && arg->isNullPointerConstant(compiler.getASTContext(), Expr::NPC_NeverValueDependent))
69 found = true;
71 if (!found)
73 APSInt x1, x2;
74 if (evaluate(defaultArgExpr, x1) && evaluate(arg, x2) && x1 == x2)
76 found = true;
79 // catch params with defaults like "= OUString()"
80 if (!found
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)
88 found = true;
91 if (!found)
92 break;
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)
96 break;
97 report(
98 DiagnosticsEngine::Warning,
99 "not necessary to pass this argument, it defaults to the same value",
100 arg->getSourceRange().getBegin())
101 << arg->getSourceRange();
102 report(
103 DiagnosticsEngine::Note,
104 "default method parameter declaration here",
105 parmVarDecl->getSourceRange().getBegin())
106 << parmVarDecl->getSourceRange();
108 return true;
111 bool DefaultParams::evaluate(const Expr* expr, APSInt& x)
113 if (isa<CXXNullPtrLiteralExpr>(expr)) {
114 x = 0;
115 return true;
117 if (expr->EvaluateAsInt(x, compiler.getASTContext()))
119 return true;
121 return false;
124 loplugin::Plugin::Registration< DefaultParams > X("defaultparams");
128 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */