summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/stringview.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/stringview.cxx')
-rw-r--r--compilerplugins/clang/stringview.cxx83
1 files changed, 80 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");
}