summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel <noel.grandin@collabora.co.uk>2021-01-28 11:01:28 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-01-28 11:11:28 +0100
commit1da69081732c8a429840edaaf10cfb789ea68df8 (patch)
treef343c9559e9dfb0263f7e33fe4306f81ec60e3fa /compilerplugins
parentb3737c638671ab39c5e6aaeaf5426d102392cc0a (diff)
add string_view variants of methods to O[U]StringBuffer
and update the stringview loplugin to detect cases where we can use these new methods. Change-Id: I998efe02e35c8efcb3abfb4d7186165bbe6dfb2c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110046 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/stringview.cxx83
-rw-r--r--compilerplugins/clang/test/stringview.cxx12
2 files changed, 92 insertions, 3 deletions
diff --git a/compilerplugins/clang/stringview.cxx b/compilerplugins/clang/stringview.cxx
index abfc87f78fd6..5df91dcad054 100644
--- a/compilerplugins/clang/stringview.cxx
+++ b/compilerplugins/clang/stringview.cxx
@@ -51,8 +51,11 @@ public:
bool VisitFunctionDecl(FunctionDecl const*);
bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*);
bool VisitImplicitCastExpr(ImplicitCastExpr const*);
+ bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*);
+ bool VisitCXXConstructExpr(CXXConstructExpr const*);
private:
+ void handleSubExprThatCouldBeView(Expr const* expr);
void handleCXXConstructExpr(CXXConstructExpr const* expr);
void handleCXXMemberCallExpr(CXXMemberCallExpr const* expr);
};
@@ -88,6 +91,20 @@ bool StringView::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOperator
check(cxxOperatorCallExpr->getArg(1));
else if (op == OO_Subscript)
check(cxxOperatorCallExpr->getArg(0));
+ else if (op == OO_Equal)
+ {
+ if (loplugin::TypeCheck(cxxOperatorCallExpr->getType())
+ .Class("OUStringBuffer")
+ .Namespace("rtl")
+ .GlobalNamespace()
+ || loplugin::TypeCheck(cxxOperatorCallExpr->getType())
+ .Class("OStringBuffer")
+ .Namespace("rtl")
+ .GlobalNamespace())
+ {
+ check(cxxOperatorCallExpr->getArg(1));
+ }
+ }
return true;
}
@@ -111,12 +128,18 @@ bool StringView::VisitImplicitCastExpr(ImplicitCastExpr const* expr)
{
return true;
}
- auto const e = expr->getSubExprAsWritten()->IgnoreParens();
+ handleSubExprThatCouldBeView(expr->getSubExprAsWritten());
+ return true;
+}
+
+void StringView::handleSubExprThatCouldBeView(Expr const* subExpr)
+{
+ auto const e = subExpr->IgnoreParens();
auto const tc = loplugin::TypeCheck(e->getType());
if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace()
|| tc.Class("OUString").Namespace("rtl").GlobalNamespace()))
{
- return true;
+ return;
}
if (auto const e1 = dyn_cast<CXXConstructExpr>(e))
{
@@ -138,7 +161,6 @@ bool StringView::VisitImplicitCastExpr(ImplicitCastExpr const* expr)
{
handleCXXMemberCallExpr(e3);
}
- return true;
}
void StringView::handleCXXConstructExpr(CXXConstructExpr const* expr)
@@ -229,6 +251,61 @@ void StringView::handleCXXMemberCallExpr(CXXMemberCallExpr const* expr)
<< expr->getSourceRange();
}
+/** check for calls to O[U]StringBuffer::append that could be passed as a
+ std::u16string_view */
+bool StringView::VisitCXXMemberCallExpr(CXXMemberCallExpr const* expr)
+{
+ if (ignoreLocation(expr))
+ {
+ return true;
+ }
+ if (!loplugin::TypeCheck(expr->getType())
+ .Class("OUStringBuffer")
+ .Namespace("rtl")
+ .GlobalNamespace()
+ && !loplugin::TypeCheck(expr->getType())
+ .Class("OStringBuffer")
+ .Namespace("rtl")
+ .GlobalNamespace())
+ {
+ return true;
+ }
+ auto const dc = loplugin::DeclCheck(expr->getMethodDecl());
+ if (dc.Function("append") || dc.Function("indexOf") || dc.Function("lastIndexOf"))
+ {
+ handleSubExprThatCouldBeView(compat::IgnoreImplicit(expr->getArg(0)));
+ }
+ else if (dc.Function("insert"))
+ {
+ handleSubExprThatCouldBeView(compat::IgnoreImplicit(expr->getArg(1)));
+ }
+ return true;
+}
+
+/** check for calls to O[U]StringBuffer constructor that could be passed as a
+ std::u16string_view */
+bool StringView::VisitCXXConstructExpr(CXXConstructExpr const* expr)
+{
+ if (ignoreLocation(expr))
+ {
+ return true;
+ }
+ if (!loplugin::TypeCheck(expr->getType())
+ .Class("OUStringBuffer")
+ .Namespace("rtl")
+ .GlobalNamespace()
+ && !loplugin::TypeCheck(expr->getType())
+ .Class("OStringBuffer")
+ .Namespace("rtl")
+ .GlobalNamespace())
+ {
+ return true;
+ }
+ if (expr->getNumArgs() > 0)
+ handleSubExprThatCouldBeView(compat::IgnoreImplicit(expr->getArg(0)));
+ return true;
+}
+
loplugin::Plugin::Registration<StringView> stringview("stringview");
}
diff --git a/compilerplugins/clang/test/stringview.cxx b/compilerplugins/clang/test/stringview.cxx
index d40ee50175a1..142bba799008 100644
--- a/compilerplugins/clang/test/stringview.cxx
+++ b/compilerplugins/clang/test/stringview.cxx
@@ -140,4 +140,16 @@ void f5(char const* s1, sal_Int32 n1, char16_t const* s2, sal_Int32 n2)
call_view(OUString(OUString::number(0)));
}
+void f5(OUString s)
+{
+ // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}}
+ OUStringBuffer buf(s.copy(5));
+ // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}}
+ buf = s.copy(5);
+ // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}}
+ buf.append(s.copy(12));
+ // expected-error@+1 {{instead of an 'rtl::OUString', pass a 'std::u16string_view' [loplugin:stringview]}}
+ buf.append(OUString(std::u16string_view(u"foo")));
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */