diff options
author | Noel <noel.grandin@collabora.co.uk> | 2021-01-28 11:01:28 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-01-28 11:11:28 +0100 |
commit | 1da69081732c8a429840edaaf10cfb789ea68df8 (patch) | |
tree | f343c9559e9dfb0263f7e33fe4306f81ec60e3fa /compilerplugins | |
parent | b3737c638671ab39c5e6aaeaf5426d102392cc0a (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.cxx | 83 | ||||
-rw-r--r-- | compilerplugins/clang/test/stringview.cxx | 12 |
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: */ |