teach lolugin:stringconstant about calling constructors
so we can remove unnecessary calls to the OUString(literal) constructor when calling constructors like this: Foo(OUString("xxx"), 1) Change-Id: I1de60ef561437c86b27dc9cb095a5deb2e103b36 Reviewed-on: https://gerrit.libreoffice.org/33698 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
@@ -152,6 +152,10 @@ private:
|
||||
CallExpr const * expr, unsigned arg, FunctionDecl const * callee,
|
||||
bool explicitFunctionalCastNotation);
|
||||
|
||||
void handleOUStringCtor(
|
||||
Expr const * expr, Expr const * argExpr, FunctionDecl const * callee,
|
||||
bool explicitFunctionalCastNotation);
|
||||
|
||||
void handleFunArgOstring(
|
||||
CallExpr const * expr, unsigned arg, FunctionDecl const * callee);
|
||||
|
||||
@@ -1054,37 +1058,33 @@ bool StringConstant::VisitCXXConstructExpr(CXXConstructExpr const * expr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string file(compiler.getSourceManager().getFilename(
|
||||
compiler.getSourceManager().getSpellingLoc(expr->getLocStart())));
|
||||
if (file == SRCDIR "/sal/qa/rtl/oustringbuffer/test_oustringbuffer_tostring.cxx")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (isInUnoIncludeFile(expr->getLocStart())) {
|
||||
return true;
|
||||
}
|
||||
auto consDecl = expr->getConstructor();
|
||||
for (unsigned i = 0; i != consDecl->getNumParams(); ++i) {
|
||||
auto t = consDecl->getParamDecl(i)->getType();
|
||||
if (loplugin::TypeCheck(t).NotSubstTemplateTypeParmType()
|
||||
.LvalueReference().Const().NotSubstTemplateTypeParmType()
|
||||
.Class("OUString").Namespace("rtl").GlobalNamespace())
|
||||
{
|
||||
auto argExpr = expr->getArg(i);
|
||||
if (argExpr && i <= consDecl->getNumParams())
|
||||
{
|
||||
if (!hasOverloads(consDecl, expr->getNumArgs()))
|
||||
{
|
||||
handleOUStringCtor(expr, argExpr, consDecl, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now check for calls to one of our exception classes where an unnecessary OUString
|
||||
// constructor is used for the first parameter.
|
||||
if (isInUnoIncludeFile(expr->getConstructor()->getCanonicalDecl())) {
|
||||
return true;
|
||||
}
|
||||
if (!expr->getConstructor()->getParent()->getName().endswith("Exception")) {
|
||||
return true;
|
||||
}
|
||||
if (expr->getNumArgs() == 0) {
|
||||
return true;
|
||||
}
|
||||
MaterializeTemporaryExpr const * subExpr1 = dyn_cast<MaterializeTemporaryExpr>(expr->getArg(0));
|
||||
if (!subExpr1) {
|
||||
return true;
|
||||
}
|
||||
if (!loplugin::TypeCheck(subExpr1->getType()).Class("OUString").Namespace("rtl").GlobalNamespace()) {
|
||||
return true;
|
||||
}
|
||||
ImplicitCastExpr const * subExpr2 = dyn_cast<ImplicitCastExpr>(subExpr1->GetTemporaryExpr());
|
||||
if (!subExpr2) {
|
||||
return true;
|
||||
}
|
||||
CXXFunctionalCastExpr const * subExpr3 = dyn_cast<CXXFunctionalCastExpr>(subExpr2->getSubExpr());
|
||||
if (!subExpr3) {
|
||||
return true;
|
||||
}
|
||||
report(DiagnosticsEngine::Warning,
|
||||
"no need to use an explicit OUString constructor here",
|
||||
subExpr3->getLocStart())
|
||||
<< subExpr3->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1592,7 +1592,14 @@ void StringConstant::handleOUStringCtor(
|
||||
CallExpr const * expr, unsigned arg, FunctionDecl const * callee,
|
||||
bool explicitFunctionalCastNotation)
|
||||
{
|
||||
auto e0 = expr->getArg(arg)->IgnoreParenImpCasts();
|
||||
handleOUStringCtor(expr, expr->getArg(arg), callee, explicitFunctionalCastNotation);
|
||||
}
|
||||
|
||||
void StringConstant::handleOUStringCtor(
|
||||
Expr const * expr, Expr const * argExpr, FunctionDecl const * callee,
|
||||
bool explicitFunctionalCastNotation)
|
||||
{
|
||||
auto e0 = argExpr->IgnoreParenImpCasts();
|
||||
auto e1 = dyn_cast<CXXFunctionalCastExpr>(e0);
|
||||
if (e1 == nullptr) {
|
||||
if (explicitFunctionalCastNotation) {
|
||||
|
@@ -14,6 +14,12 @@
|
||||
#include "com/sun/star/uno/Reference.hxx"
|
||||
#include "rtl/strbuf.hxx"
|
||||
|
||||
extern void foo(OUString const &); // expected-error {{extern prototype in main file without definition}}
|
||||
|
||||
struct Foo {
|
||||
Foo(OUString const &, int) {}
|
||||
};
|
||||
|
||||
int main() {
|
||||
char const s1[] = "foo";
|
||||
char const * const s2 = "foo";
|
||||
@@ -47,6 +53,11 @@ int main() {
|
||||
sb.insert(0, "foo", std::strlen("foo")); // expected-error {{rewrite call of 'rtl::OStringBuffer::insert' with string constant and matching length arguments as call of 'rtl::OStringBuffer::insert' [loplugin:stringconstant]}}
|
||||
sb.insert(0, s1, 3/*std::strlen(s1)*/); // expected-error {{rewrite call of 'rtl::OStringBuffer::insert' with string constant and matching length arguments as call of 'rtl::OStringBuffer::insert' [loplugin:stringconstant]}}
|
||||
sb.insert(0, s2, 3/*std::strlen(s2)*/); // expected-error {{rewrite call of 'rtl::OStringBuffer::insert' with string constant and matching length arguments as call of 'rtl::OStringBuffer::insert', and turn the non-array string constant into an array [loplugin:stringconstant]}}
|
||||
|
||||
foo(OUString("xxx")); // expected-error {{in call of 'foo', replace 'OUString' constructed from a string literal directly with the string literal [loplugin:stringconstant}}
|
||||
Foo aFoo(OUString("xxx"), 1); // expected-error {{in call of 'Foo::Foo', replace 'OUString' constructed from a string literal directly with the string literal}}
|
||||
(void)aFoo;
|
||||
}
|
||||
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||
|
Reference in New Issue
Block a user