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:
@@ -185,24 +185,50 @@ void PassStuffByRef::checkParams(const FunctionDecl * functionDecl) {
|
|||||||
if (!functionDecl->doesThisDeclarationHaveABody()) {
|
if (!functionDecl->doesThisDeclarationHaveABody()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto cxxConstructorDecl = dyn_cast<CXXConstructorDecl>(functionDecl);
|
||||||
unsigned n = functionDecl->getNumParams();
|
unsigned n = functionDecl->getNumParams();
|
||||||
for (unsigned i = 0; i != n; ++i) {
|
for (unsigned i = 0; i != n; ++i) {
|
||||||
const ParmVarDecl * pvDecl = functionDecl->getParamDecl(i);
|
const ParmVarDecl * pvDecl = functionDecl->getParamDecl(i);
|
||||||
auto const t = pvDecl->getType();
|
auto const t = pvDecl->getType();
|
||||||
if (isFat(t)) {
|
if (!isFat(t)) {
|
||||||
report(
|
continue;
|
||||||
DiagnosticsEngine::Warning,
|
}
|
||||||
("passing %0 by value, rather pass by const lvalue reference"),
|
// Ignore cases where the parameter is std::move'd.
|
||||||
pvDecl->getLocation())
|
// This is a fairly simple check, might need some more complexity if the parameter is std::move'd
|
||||||
<< t << pvDecl->getSourceRange();
|
// somewhere else in the constructor.
|
||||||
auto can = functionDecl->getCanonicalDecl();
|
bool bFoundMove = false;
|
||||||
if (can->getLocation() != functionDecl->getLocation()) {
|
if (cxxConstructorDecl) {
|
||||||
report(
|
for (CXXCtorInitializer const * cxxCtorInitializer : cxxConstructorDecl->inits()) {
|
||||||
DiagnosticsEngine::Note, "function is declared here:",
|
if (cxxCtorInitializer->isMemberInitializer())
|
||||||
can->getLocation())
|
{
|
||||||
<< can->getSourceRange();
|
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
|
// ignore stuff that forms part of the stable URE interface
|
||||||
if (isInUnoIncludeFile(functionDecl)) {
|
if (isInUnoIncludeFile(functionDecl)) {
|
||||||
|
28
compilerplugins/clang/test/passstuffbyref.cxx
Normal file
28
compilerplugins/clang/test/passstuffbyref.cxx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||||
|
/*
|
||||||
|
* This file is part of the LibreOffice project.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtl/ustring.hxx>
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
OUString mv;
|
||||||
|
|
||||||
|
// request from vmiklos: make sure we ignore cases where the passed in parameter is std::move'd
|
||||||
|
S(OUString v)
|
||||||
|
: mv(std::move(v)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void f() // expected-error {{Unreferenced externally visible function definition [loplugin:unreffun]}}
|
||||||
|
{
|
||||||
|
S* s;
|
||||||
|
OUString v;
|
||||||
|
s = new S(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
@@ -12,6 +12,7 @@ $(eval $(call gb_CompilerTest_CompilerTest,compilerplugins_clang))
|
|||||||
$(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
|
$(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
|
||||||
compilerplugins/clang/test/datamembershadow \
|
compilerplugins/clang/test/datamembershadow \
|
||||||
compilerplugins/clang/test/finalprotected \
|
compilerplugins/clang/test/finalprotected \
|
||||||
|
compilerplugins/clang/test/passstuffbyref \
|
||||||
compilerplugins/clang/test/oslendian-1 \
|
compilerplugins/clang/test/oslendian-1 \
|
||||||
compilerplugins/clang/test/oslendian-2 \
|
compilerplugins/clang/test/oslendian-2 \
|
||||||
compilerplugins/clang/test/oslendian-3 \
|
compilerplugins/clang/test/oslendian-3 \
|
||||||
|
Reference in New Issue
Block a user