make passstuffbyref plugin ignore std::move'd params

request from vmiklos

Change-Id: If263beb0623d725e406003bb1660df10fe4b4e35
Reviewed-on: https://gerrit.libreoffice.org/31555
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin
2016-12-02 17:03:37 +02:00
parent 86801fd5c1
commit 8cf59c6743
3 changed files with 67 additions and 12 deletions

View File

@@ -185,24 +185,50 @@ void PassStuffByRef::checkParams(const FunctionDecl * functionDecl) {
if (!functionDecl->doesThisDeclarationHaveABody()) {
return;
}
auto cxxConstructorDecl = dyn_cast<CXXConstructorDecl>(functionDecl);
unsigned n = functionDecl->getNumParams();
for (unsigned i = 0; i != n; ++i) {
const ParmVarDecl * pvDecl = functionDecl->getParamDecl(i);
auto const t = pvDecl->getType();
if (isFat(t)) {
report(
DiagnosticsEngine::Warning,
("passing %0 by value, rather pass by const lvalue reference"),
pvDecl->getLocation())
<< t << pvDecl->getSourceRange();
auto can = functionDecl->getCanonicalDecl();
if (can->getLocation() != functionDecl->getLocation()) {
report(
DiagnosticsEngine::Note, "function is declared here:",
can->getLocation())
<< can->getSourceRange();
if (!isFat(t)) {
continue;
}
// Ignore cases where the parameter is std::move'd.
// This is a fairly simple check, might need some more complexity if the parameter is std::move'd
// somewhere else in the constructor.
bool bFoundMove = false;
if (cxxConstructorDecl) {
for (CXXCtorInitializer const * cxxCtorInitializer : cxxConstructorDecl->inits()) {
if (cxxCtorInitializer->isMemberInitializer())
{
auto cxxConstructExpr = dyn_cast<CXXConstructExpr>(cxxCtorInitializer->getInit());
if (cxxConstructExpr && cxxConstructExpr->getNumArgs() == 1)
{
if (auto callExpr = dyn_cast<CallExpr>(cxxConstructExpr->getArg(0))) {
if (loplugin::DeclCheck(callExpr->getCalleeDecl()).Function("move").StdNamespace()) {
bFoundMove = true;
break;
}
}
}
}
}
}
if (bFoundMove) {
continue;
}
report(
DiagnosticsEngine::Warning,
("passing %0 by value, rather pass by const lvalue reference"),
pvDecl->getLocation())
<< t << pvDecl->getSourceRange();
auto can = functionDecl->getCanonicalDecl();
if (can->getLocation() != functionDecl->getLocation()) {
report(
DiagnosticsEngine::Note, "function is declared here:",
can->getLocation())
<< can->getSourceRange();
}
}
// ignore stuff that forms part of the stable URE interface
if (isInUnoIncludeFile(functionDecl)) {