chart2/qa/extras/chart2dump/chart2dump.cxx | 4 +- compilerplugins/clang/stringconstant.cxx | 43 ++++++++++++++++++++++++++ compilerplugins/clang/test/stringconstant.cxx | 13 +++++++ desktop/qa/desktop_lib/test_desktop_lib.cxx | 4 +- sal/qa/rtl/locale/rtl_locale.cxx | 12 +++---- 5 files changed, 66 insertions(+), 10 deletions(-)
New commits: commit 5d80385fd167e5e88bb0ce959c78568d7d817842 Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Fri Jul 21 22:42:35 2023 +0200 Commit: Stephan Bergmann <sberg...@redhat.com> CommitDate: Mon Jul 31 23:24:52 2023 +0200 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 <sberg...@redhat.com> diff --git a/chart2/qa/extras/chart2dump/chart2dump.cxx b/chart2/qa/extras/chart2dump/chart2dump.cxx index 030a536f320a..339a69bb80bd 100644 --- a/chart2/qa/extras/chart2dump/chart2dump.cxx +++ b/chart2/qa/extras/chart2dump/chart2dump.cxx @@ -1100,7 +1100,7 @@ DECLARE_DUMP_TEST( PivotChartDataButtonTest, Chart2DumpTest, false ) { return xShapeNode->getShapeType() == "com.sun.star.drawing.TextShape"; } ); - CPPUNIT_ASSERT_MESSAGE( OString( "Cannot find Data button shape" ).getStr(), xButton.is() ); + CPPUNIT_ASSERT_MESSAGE( "Cannot find Data button shape", xButton.is() ); // Make sure that there is no arrow shape with the Data button uno::Reference<drawing::XShape> xArrow = getShapeByName( xShapes, "FieldButton.Row.8", @@ -1108,7 +1108,7 @@ DECLARE_DUMP_TEST( PivotChartDataButtonTest, Chart2DumpTest, false ) { return xShapeNode->getShapeType() == "com.sun.star.drawing.PolyPolygonShape"; } ); - CPPUNIT_ASSERT_MESSAGE( OString( "Arrow shape should not be present for the Data button" ).getStr(), !xArrow.is() ); + CPPUNIT_ASSERT_MESSAGE( "Arrow shape should not be present for the Data button", !xArrow.is() ); // Assert the background color of the Data button util::Color aButtonFillColor = 0; 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<CXXTemporaryObjectExpr>(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<CXXFunctionalCastExpr>(e1)) { + auto const e3 = dyn_cast<clang::StringLiteral>(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; diff --git a/compilerplugins/clang/test/stringconstant.cxx b/compilerplugins/clang/test/stringconstant.cxx index 02f83b531068..ada901b877ce 100644 --- a/compilerplugins/clang/test/stringconstant.cxx +++ b/compilerplugins/clang/test/stringconstant.cxx @@ -128,6 +128,19 @@ int main() { ub.append(static_cast<char const *>(sc2)); // at runtime: append "foo" ub.append(static_cast<char const *>(sc3)); // at runtime: assert ub.append(static_cast<char const *>(sc4)); // at runtime: UB + + // expected-error-re@+1 {{in call of 'rtl::OString::getStr', replace default-constructed '{{(rtl::)?}}OString' directly with an empty ordinary string literal}} + OString().getStr(); + // expected-error-re@+1 {{in call of 'rtl::OString::getStr', replace '{{(rtl::)?}}OString' constructed from a string literal directly with the string literal}} + OString("foo").getStr(); + // expected-error-re@+1 {{in call of 'rtl::OString::getStr', replace '{{(rtl::)?}}OString' constructed from a string literal directly with the string literal}} + (OString(("foo"))).getStr(); + // expected-error-re@+1 {{in call of 'rtl::OUString::getStr', replace default-constructed '{{(rtl::)?}}OUString' directly with an empty UTF-16 string literal}} + OUString().getStr(); + // expected-error-re@+1 {{in call of 'rtl::OUString::getStr', replace '{{(rtl::)?}}OUString' constructed from a string literal directly with a UTF-16 string literal}} + OUString("foo").getStr(); + // expected-error-re@+1 {{in call of 'rtl::OUString::getStr', replace '{{(rtl::)?}}OUString' constructed from a string literal directly with the string literal}} + OUString(u"foo").getStr(); } diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index b698cc5976b7..e93cf695068f 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -2638,10 +2638,10 @@ void DesktopLOKTest::testRunMacro() bool bGoodMacro, bNonExistentMacro; // Tools macros come pre-installed in system share/basic folder, - bGoodMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, OString("macro:///Tools.Debug.ActivateReadOnlyFlag()").getStr()); + bGoodMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, "macro:///Tools.Debug.ActivateReadOnlyFlag()"); CPPUNIT_ASSERT(bGoodMacro); - bNonExistentMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, OString("macro:///I.Am.Not(There)").getStr()); + bNonExistentMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, "macro:///I.Am.Not(There)"); CPPUNIT_ASSERT(!bNonExistentMacro); } diff --git a/sal/qa/rtl/locale/rtl_locale.cxx b/sal/qa/rtl/locale/rtl_locale.cxx index 27e30db9f9d4..f1b4e12ee4b7 100644 --- a/sal/qa/rtl/locale/rtl_locale.cxx +++ b/sal/qa/rtl/locale/rtl_locale.cxx @@ -30,7 +30,7 @@ namespace rtl_locale // default locale for test purpose static void setDefaultLocale() { - rtl_locale_setDefault(OUString("de").getStr(), OUString("DE").getStr(), /* OUString() */ OUString("hochdeutsch").getStr() ); + rtl_locale_setDefault(u"de", u"DE", /* OUString() */ u"hochdeutsch" ); } class getDefault : public CppUnit::TestFixture @@ -76,7 +76,7 @@ public: // insert your test code here. void setDefault_001() { - rtl_locale_setDefault(OUString("en").getStr(), OUString("US").getStr(), OUString().getStr()); + rtl_locale_setDefault(u"en", u"US", u""); rtl_Locale* pData = rtl_locale_getDefault(); CPPUNIT_ASSERT_MESSAGE("locale must not null", pData != nullptr); @@ -241,8 +241,8 @@ public: // insert your test code here. void equals_001() { - rtl_Locale* pData1 = rtl_locale_register(OUString("en").getStr(), OUString("US").getStr(), OUString().getStr()); - rtl_Locale* pData2 = rtl_locale_register(OUString("en").getStr(), OUString("US").getStr(), OUString().getStr()); + rtl_Locale* pData1 = rtl_locale_register(u"en", u"US", u""); + rtl_Locale* pData2 = rtl_locale_register(u"en", u"US", u""); bool bLocaleAreEqual = (pData1 == pData2); @@ -251,8 +251,8 @@ public: void equals_002() { - rtl_Locale* pData1 = rtl_locale_register(OUString("en").getStr(), OUString("US").getStr(), OUString().getStr()); - rtl_Locale* pData2 = rtl_locale_register(OUString("en").getStr(), OUString("US").getStr(), OUString().getStr()); + rtl_Locale* pData1 = rtl_locale_register(u"en", u"US", u""); + rtl_Locale* pData2 = rtl_locale_register(u"en", u"US", u""); sal_Int32 nEqual = rtl_locale_equals(pData1, pData2); CPPUNIT_ASSERT(nEqual != 0);