summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2021-04-15 09:39:14 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-04-15 13:54:53 +0200
commit46ce0d28b4c765076c7871358375c4e85e44534b (patch)
treeb17378d5258a51185001eac455a764897e6dda11 /compilerplugins
parent00f7309fb786efcc0bbca04fb29de80f275a16ba (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.cxx52
-rw-r--r--compilerplugins/clang/test/stringliteralvar.cxx14
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: */