Improve loplugin:stringadd
...after 9b5dad13b5
"loplugin:stringadd look for
unnecessary temporaries". There was no reason to check for implicit
MaterializeTemporaryExpr instead of explicitly written CXXFunctionalCastExpr,
and checking for the latter makes it easier to report the casted-from type,
which gives useful information how to change code that exhibits the warning.
See the comments at <https://gerrit.libreoffice.org/#/c/80724/>
"loplugin:stringadd look for unnecessary temporaries" for details.
(And while at it, remove some commented-out debug code that is probably no
longer relevant now.)
Change-Id: I7d4cab85432885d617dd7114c75163c1eb376fc2
Reviewed-on: https://gerrit.libreoffice.org/80823
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
This commit is contained in:
@@ -193,46 +193,30 @@ bool StringAdd::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* operatorCall
|
|||||||
&& !tc.Class("OString").Namespace("rtl").GlobalNamespace())
|
&& !tc.Class("OString").Namespace("rtl").GlobalNamespace())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto check = [/* operatorCall, */ this, &tc](const MaterializeTemporaryExpr* matTempExpr) {
|
auto check = [this, &tc](const Expr* expr) {
|
||||||
auto tc3 = loplugin::TypeCheck(matTempExpr->getType());
|
auto const e = dyn_cast<CXXFunctionalCastExpr>(expr->IgnoreParenImpCasts());
|
||||||
|
if (e == nullptr)
|
||||||
|
return;
|
||||||
|
auto tc3 = loplugin::TypeCheck(e->getType());
|
||||||
if (!tc3.Class("OUString").Namespace("rtl").GlobalNamespace()
|
if (!tc3.Class("OUString").Namespace("rtl").GlobalNamespace()
|
||||||
&& !tc3.Class("OString").Namespace("rtl").GlobalNamespace())
|
&& !tc3.Class("OString").Namespace("rtl").GlobalNamespace())
|
||||||
return;
|
return;
|
||||||
if (auto bindTemp
|
// we don't have OStringLiteral1, so char needs to generate a temporary
|
||||||
= dyn_cast<CXXBindTemporaryExpr>(matTempExpr->GetTemporaryExpr()->IgnoreCasts()))
|
if (tc.Class("OString").Namespace("rtl").GlobalNamespace()
|
||||||
{
|
|| tc.Struct("OStringConcat").Namespace("rtl").GlobalNamespace())
|
||||||
// ignore temporaries returned from function calls
|
if (auto bindTemp = dyn_cast<CXXBindTemporaryExpr>(e->getSubExpr()))
|
||||||
if (isa<CallExpr>(bindTemp->getSubExpr()))
|
|
||||||
return;
|
|
||||||
// we don't have OStringLiteral1, so char needs to generate a temporary
|
|
||||||
if (tc.Class("OString").Namespace("rtl").GlobalNamespace()
|
|
||||||
|| tc.Struct("OStringConcat").Namespace("rtl").GlobalNamespace())
|
|
||||||
if (auto cxxConstruct = dyn_cast<CXXConstructExpr>(bindTemp->getSubExpr()))
|
if (auto cxxConstruct = dyn_cast<CXXConstructExpr>(bindTemp->getSubExpr()))
|
||||||
if (loplugin::TypeCheck(
|
if (loplugin::TypeCheck(
|
||||||
cxxConstruct->getConstructor()->getParamDecl(0)->getType())
|
cxxConstruct->getConstructor()->getParamDecl(0)->getType())
|
||||||
.Char())
|
.Char())
|
||||||
return;
|
return;
|
||||||
// calls where we pass in an explicit character encoding
|
report(DiagnosticsEngine::Warning, "avoid constructing temporary object from %0 during +",
|
||||||
if (auto cxxTemp = dyn_cast<CXXTemporaryObjectExpr>(bindTemp->getSubExpr()))
|
compat::getBeginLoc(e))
|
||||||
if (cxxTemp->getNumArgs() > 1)
|
<< e->getSubExprAsWritten()->getType() << e->getSourceRange();
|
||||||
return;
|
|
||||||
}
|
|
||||||
// conditional operators ( a ? b : c ) will result in temporaries
|
|
||||||
if (isa<ConditionalOperator>(
|
|
||||||
matTempExpr->GetTemporaryExpr()->IgnoreCasts()->IgnoreParens()))
|
|
||||||
return;
|
|
||||||
report(DiagnosticsEngine::Warning, "avoid constructing temporary copies during +",
|
|
||||||
compat::getBeginLoc(matTempExpr))
|
|
||||||
<< matTempExpr->getSourceRange();
|
|
||||||
// operatorCall->dump();
|
|
||||||
// matTempExpr->getType()->dump();
|
|
||||||
// operatorCall->getType()->getUnqualifiedDesugaredType()->dump();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto matTempExpr = dyn_cast<MaterializeTemporaryExpr>(operatorCall->getArg(0)))
|
check(operatorCall->getArg(0));
|
||||||
check(matTempExpr);
|
check(operatorCall->getArg(1));
|
||||||
if (auto matTempExpr = dyn_cast<MaterializeTemporaryExpr>(operatorCall->getArg(1)))
|
|
||||||
check(matTempExpr);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -163,9 +163,9 @@ void f1(OUString s, OUString t, int i, const char* pChar)
|
|||||||
{
|
{
|
||||||
// no warning expected
|
// no warning expected
|
||||||
t = t + "xxx";
|
t = t + "xxx";
|
||||||
// expected-error@+1 {{avoid constructing temporary copies during + [loplugin:stringadd]}}
|
// expected-error@+1 {{avoid constructing temporary object from 'const char [4]' during + [loplugin:stringadd]}}
|
||||||
s = s + OUString("xxx");
|
s = s + OUString("xxx");
|
||||||
// expected-error@+1 {{avoid constructing temporary copies during + [loplugin:stringadd]}}
|
// expected-error@+1 {{avoid constructing temporary object from 'const rtl::OUString' during + [loplugin:stringadd]}}
|
||||||
s = s + OUString(getByRef());
|
s = s + OUString(getByRef());
|
||||||
|
|
||||||
// no warning expected
|
// no warning expected
|
||||||
@@ -183,7 +183,7 @@ void f1(OUString s, OUString t, int i, const char* pChar)
|
|||||||
void f2(char ch)
|
void f2(char ch)
|
||||||
{
|
{
|
||||||
OString s;
|
OString s;
|
||||||
// expected-error@+1 {{avoid constructing temporary copies during + [loplugin:stringadd]}}
|
// expected-error@+1 {{avoid constructing temporary object from 'const char [4]' during + [loplugin:stringadd]}}
|
||||||
s = s + OString("xxx");
|
s = s + OString("xxx");
|
||||||
// no warning expected, no OStringLiteral1
|
// no warning expected, no OStringLiteral1
|
||||||
s = s + OString(ch);
|
s = s + OString(ch);
|
||||||
|
Reference in New Issue
Block a user