1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
17 #include <unordered_set>
18 #include "config_clang.h"
23 Look for places where we can pass by move && param and so avoid
25 Empirically, when we are passing a container type to a function, 80% of the time,
26 we are passing a local temporary that can be moved instead of being copied.
28 TODO this could be a lot smarter, with ignoring false+ e.g. when copying a param
34 class MoveParam
: public loplugin::FilteringPlugin
<MoveParam
>
37 explicit MoveParam(loplugin::InstantiationData
const& data
)
38 : FilteringPlugin(data
)
42 virtual bool preRun() override
44 std::string
fn(handler
.getMainFileName());
45 loplugin::normalizeDotDotInFilePath(fn
);
46 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/filter/source/msfilter/escherex.cxx"))
48 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sc/source/ui/docshell/docfunc.cxx"))
50 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sc/source/ui/view/viewfunc.cxx"))
52 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/basegfx/source/polygon/b2dpolygontools.cxx"))
54 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/basegfx/source/polygon/b3dpolygontools.cxx"))
56 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/connectivity/source/commontools/dbtools.cxx"))
61 virtual void run() override
64 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
67 bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr
*);
68 bool VisitCXXConstructExpr(const CXXConstructExpr
*);
70 bool isContainerType(QualType qt
);
73 bool MoveParam::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr
* callExpr
)
75 if (ignoreLocation(callExpr
))
77 if (!callExpr
->isAssignmentOp())
79 auto qt
= callExpr
->getType();
80 if (!isContainerType(qt
))
82 auto declRef
= dyn_cast
<DeclRefExpr
>(callExpr
->getArg(1)->IgnoreParenImpCasts());
86 auto parmVarDecl
= dyn_cast_or_null
<ParmVarDecl
>(declRef
->getDecl());
90 if (!loplugin::TypeCheck(parmVarDecl
->getType()).LvalueReference().Const())
93 StringRef aFileName
= getFilenameOfLocation(
94 compiler
.getSourceManager().getSpellingLoc(parmVarDecl
->getBeginLoc()));
95 if (loplugin::hasPathnamePrefix(aFileName
,
96 SRCDIR
"/svx/source/sidebar/line/LineWidthValueSet.cxx"))
99 report(DiagnosticsEngine::Warning
, "rather use move && param1", callExpr
->getBeginLoc());
104 bool MoveParam::VisitCXXConstructExpr(const CXXConstructExpr
* constructExpr
)
106 if (ignoreLocation(constructExpr
->getBeginLoc()))
108 if (isInUnoIncludeFile(constructExpr
->getBeginLoc()))
111 auto qt
= constructExpr
->getType();
112 if (!isContainerType(qt
))
115 if (constructExpr
->getNumArgs() != 1)
118 auto declRef
= dyn_cast
<DeclRefExpr
>(constructExpr
->getArg(0)->IgnoreParenImpCasts());
122 auto parmVarDecl
= dyn_cast_or_null
<ParmVarDecl
>(declRef
->getDecl());
126 if (!loplugin::TypeCheck(parmVarDecl
->getType()).LvalueReference().Const())
129 StringRef aFileName
= getFilenameOfLocation(
130 compiler
.getSourceManager().getSpellingLoc(parmVarDecl
->getBeginLoc()));
131 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
132 "/include/drawinglayer/primitive2d/Primitive2DContainer.hxx"))
134 if (loplugin::hasPathnamePrefix(aFileName
,
135 SRCDIR
"/include/drawinglayer/primitive3d/baseprimitive3d.hxx"))
137 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/svx/source/svdraw/svdmrkv.cxx"))
139 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/include/editeng/swafopt.hxx"))
141 if (loplugin::hasPathnamePrefix(
142 aFileName
, SRCDIR
"/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx"))
144 if (loplugin::hasPathnamePrefix(aFileName
,
145 SRCDIR
"/chart2/source/tools/InternalDataProvider.cxx"))
147 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/sc/source/core/data/attrib.cxx"))
149 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/sw/source/core/doc/docfmt.cxx"))
151 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/configmgr/source/modifications.cxx"))
153 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/svx/source/dialog/srchdlg.cxx"))
155 if (loplugin::hasPathnamePrefix(aFileName
,
156 SRCDIR
"/stoc/source/servicemanager/servicemanager.cxx"))
159 report(DiagnosticsEngine::Warning
, "rather use move && param3", constructExpr
->getBeginLoc());
164 bool MoveParam::isContainerType(QualType qt
)
166 auto tc
= loplugin::TypeCheck(qt
);
167 return tc
.Class("Primitive2DContainer")
168 .Namespace("primitive2d")
169 .Namespace("drawinglayer")
171 || tc
.ClassOrStruct("sorted_vector").Namespace("o3tl").GlobalNamespace()
172 || tc
.ClassOrStruct("array").StdNamespace() || tc
.ClassOrStruct("vector").StdNamespace()
173 || tc
.ClassOrStruct("deque").StdNamespace()
174 || tc
.ClassOrStruct("forward_list").StdNamespace()
175 || tc
.ClassOrStruct("list").StdNamespace() || tc
.ClassOrStruct("set").StdNamespace()
176 || tc
.ClassOrStruct("map").StdNamespace() || tc
.ClassOrStruct("multiset").StdNamespace()
177 || tc
.ClassOrStruct("multimap").StdNamespace()
178 || tc
.ClassOrStruct("unordered_set").StdNamespace()
179 || tc
.ClassOrStruct("unordered_map").StdNamespace()
180 || tc
.ClassOrStruct("unordered_multiset").StdNamespace()
181 || tc
.ClassOrStruct("unordered_multimap").StdNamespace()
182 || tc
.ClassOrStruct("stack").StdNamespace() || tc
.ClassOrStruct("queue").StdNamespace()
183 || tc
.ClassOrStruct("priority_queue").StdNamespace();
186 /** off by default because it needs some hand-holding */
187 loplugin::Plugin::Registration
<MoveParam
> moveparam("moveparam", false);
191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */