diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-04-15 09:39:14 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-04-15 13:54:53 +0200 |
commit | 46ce0d28b4c765076c7871358375c4e85e44534b (patch) | |
tree | b17378d5258a51185001eac455a764897e6dda11 /compilerplugins | |
parent | 00f7309fb786efcc0bbca04fb29de80f275a16ba (diff) |
loplugin:stringliteralvar look for assignments
to O[U]String from char array literals, we can convert the char literals
to O[U]StringLiteral and avoid a runtime allocation
Change-Id: I15d8dddb2cd428b90740e39f20daf98e0941aa6d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114125
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/stringliteralvar.cxx | 52 | ||||
-rw-r--r-- | compilerplugins/clang/test/stringliteralvar.cxx | 14 |
2 files changed, 64 insertions, 2 deletions
diff --git a/compilerplugins/clang/stringliteralvar.cxx b/compilerplugins/clang/stringliteralvar.cxx index bf06f47f5089..f8dfe916cc5b 100644 --- a/compilerplugins/clang/stringliteralvar.cxx +++ b/compilerplugins/clang/stringliteralvar.cxx @@ -7,8 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// Find constant character array variables that are passed into O[U]String constructors and should -// thus be turned into O[U]StringLiteral variables. +// Find constant character array variables that are either +// (a) passed into O[U]String constructors +// (b) assigned to O[U]String +// and should thus be turned into O[U]StringLiteral variables. // // Such a variable may have been used in multiple places, not all of which would be compatible with // changing the variable's type to O[U]StringLiteral. However, this plugin is aggressive and @@ -155,6 +157,52 @@ public: return true; } + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getOperator() != OO_Equal) + { + return true; + } + loplugin::TypeCheck const tc(expr->getType()); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace())) + { + return true; + } + if (expr->getNumArgs() != 2) + { + return true; + } + auto const e = dyn_cast<DeclRefExpr>(expr->getArg(1)->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + auto const t = e->getType(); + if (!(t.isConstQualified() && t->isConstantArrayType())) + { + return true; + } + auto const d = e->getDecl(); + if (!reportedArray_.insert(d).second) + { + return true; + } + report(DiagnosticsEngine::Warning, + "change type of variable %0 from constant character array (%1) to " + "%select{OStringLiteral|OUStringLiteral}2%select{|, and make it static}3", + d->getLocation()) + << d << d->getType() << (tc.Class("OString").Namespace("rtl").GlobalNamespace() ? 0 : 1) + << isAutomaticVariable(cast<VarDecl>(d)) << d->getSourceRange(); + report(DiagnosticsEngine::Note, "first assigned here", compat::getBeginLoc(expr)) + << expr->getSourceRange(); + return true; + } + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const* expr) { if (ignoreLocation(expr)) diff --git a/compilerplugins/clang/test/stringliteralvar.cxx b/compilerplugins/clang/test/stringliteralvar.cxx index 535f0e36ee72..b34274c45219 100644 --- a/compilerplugins/clang/test/stringliteralvar.cxx +++ b/compilerplugins/clang/test/stringliteralvar.cxx @@ -95,4 +95,18 @@ void f10() f(OUString(literal, 3)); } +void f11(int nStreamType) +{ + // expected-error@+1 {{change type of variable 'sDocumentType' from constant character array ('const char [4]') to OUStringLiteral, and make it static [loplugin:stringliteralvar]}} + const char sDocumentType[] = "foo"; + OUString sStreamType; + switch (nStreamType) + { + case 1: + // expected-note@+1 {{first assigned here [loplugin:stringliteralvar]}} + sStreamType = sDocumentType; + break; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |