From 5d80385fd167e5e88bb0ce959c78568d7d817842 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Fri, 21 Jul 2023 22:42:35 +0200 Subject: loplugin:stringconstant: Catch some O[U]String::getStr anti-patterns Change-Id: I36bc86fcffc3c10fe44e60d779c9aa48eeed00f2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154749 Tested-by: Jenkins Reviewed-by: Stephan Bergmann --- compilerplugins/clang/stringconstant.cxx | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'compilerplugins/clang/stringconstant.cxx') diff --git a/compilerplugins/clang/stringconstant.cxx b/compilerplugins/clang/stringconstant.cxx index cf1eb6afedbf..c64c2c9d6589 100644 --- a/compilerplugins/clang/stringconstant.cxx +++ b/compilerplugins/clang/stringconstant.cxx @@ -191,6 +191,8 @@ public: bool VisitCallExpr(CallExpr const * expr); + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const * expr); + bool VisitCXXConstructExpr(CXXConstructExpr const * expr); bool VisitReturnStmt(ReturnStmt const * stmt); @@ -856,6 +858,47 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) { return true; } +bool StringConstant::VisitCXXMemberCallExpr(CXXMemberCallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + FunctionDecl const * fdecl = expr->getDirectCallee(); + if (fdecl == nullptr) { + return true; + } + auto const c = loplugin::DeclCheck(fdecl).Function("getStr"); + if ((c.Class("OString").Namespace("rtl").GlobalNamespace() + || c.Class("OUString").Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 0) + { + auto const e1 = expr->getImplicitObjectArgument()->IgnoreImplicit()->IgnoreParens(); + if (auto const e2 = dyn_cast(e1)) { + if (e2->getNumArgs() != 0) { + return true; + } + report( + DiagnosticsEngine::Warning, + "in call of '%0', replace default-constructed %1 directly with an empty %select{ordinary|UTF-16}2 string literal", + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << e2->getType() << bool(loplugin::TypeCheck(e2->getType()).Class("OUString")) << expr->getSourceRange(); + return true; + } + if (auto const e2 = dyn_cast(e1)) { + auto const e3 = dyn_cast(e2->getSubExprAsWritten()->IgnoreParens()); + if (e3 == nullptr) { + return true; + } + report( + DiagnosticsEngine::Warning, + "in call of '%0', replace %1 constructed from a string literal directly with %select{the|a UTF-16}2 string literal", + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << e2->getType() << (loplugin::TypeCheck(e2->getType()).Class("OUString") && !e3->isUTF16()) << expr->getSourceRange(); + return true; + } + } + return true; +} + bool StringConstant::VisitCXXConstructExpr(CXXConstructExpr const * expr) { if (ignoreLocation(expr)) { return true; -- cgit