diff options
-rw-r--r-- | compilerplugins/clang/check.cxx | 16 | ||||
-rw-r--r-- | compilerplugins/clang/check.hxx | 10 | ||||
-rw-r--r-- | compilerplugins/clang/compat.hxx | 13 | ||||
-rw-r--r-- | compilerplugins/clang/getstr.cxx | 172 | ||||
-rw-r--r-- | compilerplugins/clang/test/getstr.cxx | 41 | ||||
-rw-r--r-- | desktop/source/app/crashreport.cxx | 4 | ||||
-rw-r--r-- | include/oox/helper/helper.hxx | 4 | ||||
-rw-r--r-- | include/rtl/ustring.hxx | 2 | ||||
-rw-r--r-- | lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx | 2 | ||||
-rw-r--r-- | oox/source/ppt/commonbehaviorcontext.cxx | 2 | ||||
-rw-r--r-- | pyuno/source/module/pyuno_module.cxx | 2 | ||||
-rw-r--r-- | sal/osl/unx/uunxapi.cxx | 8 | ||||
-rw-r--r-- | solenv/CompilerTest_compilerplugins_clang.mk | 1 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 4 |
14 files changed, 264 insertions, 17 deletions
diff --git a/compilerplugins/clang/check.cxx b/compilerplugins/clang/check.cxx index d53bfabbe9cf..be1b1f764eb1 100644 --- a/compilerplugins/clang/check.cxx +++ b/compilerplugins/clang/check.cxx @@ -10,6 +10,7 @@ #include <cassert> #include <clang/AST/DeclCXX.h> +#include <clang/AST/DeclTemplate.h> #include "check.hxx" @@ -131,6 +132,21 @@ TypeCheck TypeCheck::Typedef() const { return TypeCheck(); } +DeclCheck TypeCheck::TemplateSpecializationClass() const { + if (!type_.isNull()) { + if (auto const t = type_->getAs<clang::TemplateSpecializationType>()) { + if (!t->isTypeAlias()) { + if (auto const d = llvm::dyn_cast_or_null<clang::ClassTemplateDecl>( + t->getTemplateName().getAsTemplateDecl())) + { + return DeclCheck(d->getTemplatedDecl()); + } + } + } + } + return DeclCheck(); +} + TypeCheck TypeCheck::NotSubstTemplateTypeParmType() const { return (!type_.isNull() diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx index 7aa56cb8523d..8e835b8b6a96 100644 --- a/compilerplugins/clang/check.hxx +++ b/compilerplugins/clang/check.hxx @@ -29,6 +29,8 @@ inline ContextCheck checkRecordDecl( } +class DeclCheck; + class TypeCheck { public: explicit TypeCheck(clang::QualType type): type_(type) {} @@ -71,6 +73,8 @@ public: inline ContextCheck Typedef(llvm::StringRef id) const; + DeclCheck TemplateSpecializationClass() const; + TypeCheck NotSubstTemplateTypeParmType() const; private: @@ -80,6 +84,8 @@ private: }; class DeclCheck { + friend TypeCheck; + public: explicit DeclCheck(clang::Decl const * decl): decl_(decl) {} @@ -102,7 +108,9 @@ public: ContextCheck MemberFunction() const; private: - clang::Decl const * const decl_; + DeclCheck() = default; + + clang::Decl const * const decl_ = nullptr; }; class ContextCheck { diff --git a/compilerplugins/clang/compat.hxx b/compilerplugins/clang/compat.hxx index cb13f44cfa66..c091c51601f7 100644 --- a/compilerplugins/clang/compat.hxx +++ b/compilerplugins/clang/compat.hxx @@ -240,6 +240,19 @@ inline const clang::Expr *getSubExprAsWritten(const clang::CastExpr *This) { return getSubExprAsWritten(const_cast<clang::CastExpr *>(This)); } +inline clang::QualType getObjectType(clang::CXXMemberCallExpr const * expr) { +#if CLANG_VERSION >= 100000 + return expr->getObjectType(); +#else + // <https://github.com/llvm/llvm-project/commit/88559637641e993895337e1047a0bd787fecc647> + // "[OpenCL] Improve destructor support in C++ for OpenCL": + clang::QualType Ty = expr->getImplicitObjectArgument()->getType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + return Ty; +#endif +} + inline bool isExplicitSpecified(clang::CXXConstructorDecl const * decl) { #if CLANG_VERSION >= 90000 return decl->getExplicitSpecifier().isExplicit(); diff --git a/compilerplugins/clang/getstr.cxx b/compilerplugins/clang/getstr.cxx new file mode 100644 index 000000000000..15f340296bea --- /dev/null +++ b/compilerplugins/clang/getstr.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include <cassert> +#include <stack> + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +// Find matches of +// +// ... << s.getStr() +// +// (for the rtl string classes) that can be written as just +// +// ... << s + +namespace +{ +class GetStr final : public loplugin::FilteringPlugin<GetStr> +{ +public: + explicit GetStr(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool PreTraverseFunctionDecl(FunctionDecl* decl) + { + functions_.push(decl); + return true; + } + + bool PostTraverseFunctionDecl(FunctionDecl*, bool) + { + assert(!functions_.empty()); + functions_.pop(); + return true; + } + + bool TraverseFunctionDecl(FunctionDecl* decl) + { + bool ret = true; + if (PreTraverseFunctionDecl(decl)) + { + ret = FilteringPlugin::TraverseFunctionDecl(decl); + PostTraverseFunctionDecl(decl, ret); + } + return ret; + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getOperator() != OO_LessLess) + { + return true; + } + assert(expr->getNumArgs() == 2); + if (!loplugin::TypeCheck(expr->getArg(0)->getType()) + .TemplateSpecializationClass() + .ClassOrStruct("basic_ostream") + .StdNamespace()) //TODO: check template args + { + return true; + } + auto const arg1 = expr->getArg(1); + auto const e = dyn_cast<CXXMemberCallExpr>(arg1->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + bool castToVoid = false; + if (auto const ic = dyn_cast<ImplicitCastExpr>(arg1)) + { + if (loplugin::TypeCheck(arg1->getType()).Pointer().Void()) + { + castToVoid = true; + } + } + auto const t = compat::getObjectType(e); + auto const tc = loplugin::TypeCheck(t); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || (castToVoid + && (tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace())))) + { + return true; + } + if (!loplugin::DeclCheck(e->getMethodDecl()).Function("getStr")) + { + return true; + } + if (castToVoid) + { + report(DiagnosticsEngine::Warning, + ("suspicious use of 'getStr' on an object of type %0; the result is implicitly" + " cast to a void pointer in a call of 'operator <<'"), + e->getExprLoc()) + << t.getLocalUnqualifiedType() << expr->getSourceRange(); + return true; + } + if (!functions_.empty()) + { + // Filter out occurrences of `s << t.getStr()` in the implementation of + // `operator <<(std::basic_ostream<...> & s, T const & t)`: + auto const fd = functions_.top(); + if (fd->getOverloadedOperator() == OO_LessLess) + { + assert(fd->getNumParams() == 2); + if (loplugin::TypeCheck(fd->getParamDecl(0)->getType()) + .LvalueReference() + .NonConstVolatile() + .TemplateSpecializationClass() + .ClassOrStruct("basic_ostream") + .StdNamespace()) //TODO: check template args + { + if (auto const t2 + = fd->getParamDecl(1)->getType()->getAs<LValueReferenceType>()) + { + auto const t3 = t2->getPointeeType(); + if (t3.isConstQualified() && !t3.isVolatileQualified() + && (t3.getCanonicalType().getTypePtr() + == t.getCanonicalType().getTypePtr())) + { + return true; + } + } + } + } + } + report(DiagnosticsEngine::Warning, + ("directly use object of type %0 in a call of 'operator <<', instead of calling" + " 'getStr' first"), + e->getExprLoc()) + << t.getLocalUnqualifiedType() << expr->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + std::stack<FunctionDecl*> functions_; + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +loplugin::Plugin::Registration<GetStr> getstr("getstr"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/getstr.cxx b/compilerplugins/clang/test/getstr.cxx new file mode 100644 index 000000000000..358f2e2b1e7d --- /dev/null +++ b/compilerplugins/clang/test/getstr.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <ostream> + +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> + +using S = OString; + +void f(std::ostream& st, OString const& s1, OStringBuffer const& s2, OUString const& s3, + OUStringBuffer const& s4, S const& s5, OString* p1, OStringBuffer* p2, OUString* p3, + OUStringBuffer* p4, S* p5, char const* (OString::*pf)() const) +{ + st << s1.getStr() // expected-error {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << s2.getStr() + << s3.getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUString'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} + << s4.getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUStringBuffer'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} + << s5.getStr() // expected-error {{directly use object of type 'S' (aka 'rtl::OString') in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << p1->getStr() // expected-error {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << p2->getStr() + << p3->getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUString'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} + << p4->getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUStringBuffer'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} + << p5->getStr() // expected-error {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << (s1.*pf)(); + SAL_INFO( // expected-error 1+ {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + "test", s1.getStr()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/desktop/source/app/crashreport.cxx b/desktop/source/app/crashreport.cxx index 794e4e6b6b63..3420f20c4496 100644 --- a/desktop/source/app/crashreport.cxx +++ b/desktop/source/app/crashreport.cxx @@ -50,8 +50,8 @@ void CrashReporter::writeToFile(std::ios_base::openmode Openmode) for (auto& keyValue : maKeyValues) { - ini_file << OUStringToOString(keyValue.first, RTL_TEXTENCODING_UTF8).getStr() << "="; - ini_file << OUStringToOString(keyValue.second, RTL_TEXTENCODING_UTF8).getStr() << "\n"; + ini_file << OUStringToOString(keyValue.first, RTL_TEXTENCODING_UTF8) << "="; + ini_file << OUStringToOString(keyValue.second, RTL_TEXTENCODING_UTF8) << "\n"; } maKeyValues.clear(); diff --git a/include/oox/helper/helper.hxx b/include/oox/helper/helper.hxx index bc208af02662..d2077aaaa319 100644 --- a/include/oox/helper/helper.hxx +++ b/include/oox/helper/helper.hxx @@ -41,10 +41,6 @@ namespace oox { #define STATIC_ARRAY_SELECT( array, index, def ) \ ((static_cast<size_t>(index) < SAL_N_ELEMENTS(array)) ? ((array)[static_cast<size_t>(index)]) : (def)) -/** Convert an OUString to an ASCII C string. Use for debug purposes only. */ -#define OUSTRING_TO_CSTR( str ) \ - OUStringToOString( str, RTL_TEXTENCODING_ASCII_US ).getStr() - // Common constants =========================================================== const sal_uInt8 WINDOWS_CHARSET_ANSI = 0; diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx index a7ede5f9a32a..a2bb6c09c086 100644 --- a/include/rtl/ustring.hxx +++ b/include/rtl/ustring.hxx @@ -3766,7 +3766,7 @@ inline std::basic_ostream<charT, traits> & operator <<( std::basic_ostream<charT, traits> & stream, OUString const & rString) { return stream << - OUStringToOString(rString, RTL_TEXTENCODING_UTF8).getStr(); + OUStringToOString(rString, RTL_TEXTENCODING_UTF8); // best effort; potentially loses data due to conversion failures // (stray surrogate halves) and embedded null characters } diff --git a/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx b/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx index 2008395319e0..3434482486ed 100644 --- a/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx +++ b/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx @@ -235,7 +235,7 @@ bool LoadDictionary(HDInfo& rDict) { SAL_WARN( "lingucomponent", - "Couldn't find file " << OU2ENC(dictpath, osl_getThreadTextEncoding())); + "Couldn't find file " << dictpath); return false; } rDict.aPtr = dict; diff --git a/oox/source/ppt/commonbehaviorcontext.cxx b/oox/source/ppt/commonbehaviorcontext.cxx index b94710777731..3112e084f8a6 100644 --- a/oox/source/ppt/commonbehaviorcontext.cxx +++ b/oox/source/ppt/commonbehaviorcontext.cxx @@ -91,7 +91,7 @@ namespace oox { namespace ppt { RTL_TEXTENCODING_ASCII_US ); attr.type = attrConv->meAttribute; maAttributes.push_back( attr ); - SAL_INFO("oox.ppt", "OOX: attrName is " << OUSTRING_TO_CSTR( msCurrentAttribute ) << " -> " << attrConv->mpAPIName ); + SAL_INFO("oox.ppt", "OOX: attrName is " << msCurrentAttribute << " -> " << attrConv->mpAPIName ); break; } attrConv++; diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx index a6566182b546..715d5c6dbb27 100644 --- a/pyuno/source/module/pyuno_module.cxx +++ b/pyuno/source/module/pyuno_module.cxx @@ -863,7 +863,7 @@ static PyObject *sal_debug( OUString line = pyString2ustring( PyTuple_GetItem( args, 0 ) ); - SAL_DEBUG(line.toUtf8().getStr()); + SAL_DEBUG(line); return Py_None; } diff --git a/sal/osl/unx/uunxapi.cxx b/sal/osl/unx/uunxapi.cxx index 1005140a2c91..aecfab6d85a0 100644 --- a/sal/osl/unx/uunxapi.cxx +++ b/sal/osl/unx/uunxapi.cxx @@ -183,9 +183,9 @@ int osl::access(const OString& pstrPath, int mode) int result = ::access(fn.getStr(), mode); int saved_errno = errno; if (result == -1) - SAL_INFO("sal.file", "access(" << fn.getStr() << ",0" << std::oct << mode << std::dec << "): " << UnixErrnoString(saved_errno)); + SAL_INFO("sal.file", "access(" << fn << ",0" << std::oct << mode << std::dec << "): " << UnixErrnoString(saved_errno)); else - SAL_INFO("sal.file", "access(" << fn.getStr() << ",0" << std::oct << mode << std::dec << "): OK"); + SAL_INFO("sal.file", "access(" << fn << ",0" << std::oct << mode << std::dec << "): OK"); done_accessing_file_path(fn.getStr(), state); @@ -232,9 +232,9 @@ template<typename T> bool realpath_(const T& pstrFileName, T& ppstrResolvedName) bool bRet = realpath(fn.getStr(), rp); int saved_errno = errno; if (!bRet) - SAL_INFO("sal.file", "realpath(" << fn.getStr() << "): " << UnixErrnoString(saved_errno)); + SAL_INFO("sal.file", "realpath(" << fn << "): " << UnixErrnoString(saved_errno)); else - SAL_INFO("sal.file", "realpath(" << fn.getStr() << "): OK"); + SAL_INFO("sal.file", "realpath(" << fn << "): OK"); done_accessing_file_path(fn.getStr(), state); diff --git a/solenv/CompilerTest_compilerplugins_clang.mk b/solenv/CompilerTest_compilerplugins_clang.mk index 644e8179180d..d83542bfbfc4 100644 --- a/solenv/CompilerTest_compilerplugins_clang.mk +++ b/solenv/CompilerTest_compilerplugins_clang.mk @@ -36,6 +36,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \ compilerplugins/clang/test/finalprotected \ compilerplugins/clang/test/flatten \ compilerplugins/clang/test/fragiledestructor \ + compilerplugins/clang/test/getstr \ compilerplugins/clang/test/indentation \ compilerplugins/clang/test/logexceptionnicely \ compilerplugins/clang/test/loopvartoosmall \ diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 49c2ca9050b8..0048cc548d54 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -10828,7 +10828,7 @@ bool PDFWriterImpl::setStructureAttribute( enum PDFWriter::StructAttribute eAttr "rejecting setStructureAttribute( " << getAttributeTag( eAttr ) << ", " << getAttributeValueTag( eVal ) << " ) on " << getStructureTag( m_aStructure[ m_nCurrentStructElement ].m_eType ) - << " (" << m_aStructure[ m_nCurrentStructElement ].m_aAlias.getStr() + << " (" << m_aStructure[ m_nCurrentStructElement ].m_aAlias << ") element"); return bInsert; @@ -10960,7 +10960,7 @@ bool PDFWriterImpl::setStructureAttributeNumerical( enum PDFWriter::StructAttrib "rejecting setStructureAttributeNumerical( " << getAttributeTag( eAttr ) << ", " << static_cast<int>(nValue) << " ) on " << getStructureTag( m_aStructure[ m_nCurrentStructElement ].m_eType ) - << " (" << m_aStructure[ m_nCurrentStructElement ].m_aAlias.getStr() + << " (" << m_aStructure[ m_nCurrentStructElement ].m_aAlias << ") element"); return bInsert; |