summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compilerplugins/clang/noexceptmove.cxx319
-rw-r--r--compilerplugins/clang/test/noexceptmove.cxx102
-rw-r--r--connectivity/source/drivers/evoab2/NStatement.hxx2
-rw-r--r--cppu/source/uno/lbmap.cxx4
-rw-r--r--include/com/sun/star/uno/Reference.h4
-rw-r--r--include/com/sun/star/uno/Reference.hxx4
-rw-r--r--include/cppuhelper/weakref.hxx2
-rw-r--r--include/osl/pipe.hxx4
-rw-r--r--include/osl/pipe_decl.hxx4
-rw-r--r--include/osl/socket.hxx4
-rw-r--r--include/osl/socket_decl.hxx4
-rw-r--r--include/registry/registry.hxx2
-rw-r--r--include/rtl/byteseq.h4
-rw-r--r--include/rtl/byteseq.hxx4
-rw-r--r--include/rtl/ref.hxx2
-rw-r--r--include/rtl/string.hxx4
-rw-r--r--include/rtl/ustring.hxx4
-rw-r--r--include/sfx2/objsh.hxx4
-rw-r--r--include/store/store.hxx4
-rw-r--r--include/tools/globname.hxx4
-rw-r--r--include/tools/poly.hxx4
-rw-r--r--include/typelib/typedescription.hxx4
-rw-r--r--include/uno/dispatcher.hxx2
-rw-r--r--include/uno/environment.hxx2
-rw-r--r--include/uno/mapping.hxx4
-rw-r--r--include/unotools/itemholderbase.hxx2
-rw-r--r--include/unotools/tempfile.hxx2
-rw-r--r--include/vcl/alpha.hxx2
-rw-r--r--include/vcl/font.hxx4
-rw-r--r--include/vcl/region.hxx4
-rw-r--r--solenv/CompilerTest_compilerplugins_clang.mk1
-rw-r--r--sw/inc/IDocumentMarkAccess.hxx4
-rw-r--r--sw/source/core/doc/docbm.cxx4
-rw-r--r--tools/source/generic/poly.cxx4
-rw-r--r--tools/source/ref/globname.cxx2
-rw-r--r--unotools/source/ucbhelper/tempfile.cxx2
-rw-r--r--vcl/source/font/font.cxx4
-rw-r--r--vcl/source/gdi/region.cxx4
38 files changed, 481 insertions, 59 deletions
diff --git a/compilerplugins/clang/noexceptmove.cxx b/compilerplugins/clang/noexceptmove.cxx
new file mode 100644
index 000000000000..483ccaed44cf
--- /dev/null
+++ b/compilerplugins/clang/noexceptmove.cxx
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+// versions before 9.0 didn't have getExceptionSpecType
+
+#include "plugin.hxx"
+
+// clang before V9 does not have API to report exception spec type
+#if CLANG_VERSION >= 90000
+
+#include "check.hxx"
+
+#include <string>
+#include <set>
+
+/**
+ Look for move constructors that can be noexcept.
+*/
+
+namespace
+{
+/// Look for the stuff that can be marked noexcept, but only if we also mark some of the callees noexcept.
+/// Off by default so as not too annoy people.
+constexpr bool bLookForStuffWeCanFix = false;
+
+class NoExceptMove : public loplugin::FilteringPlugin<NoExceptMove>
+{
+public:
+ explicit NoExceptMove(loplugin::InstantiationData const& data)
+ : FilteringPlugin(data)
+ {
+ }
+
+ virtual void run() override
+ {
+ StringRef fn(handler.getMainFileName());
+ // ONDXPagePtr::operator= calls ONDXPage::ReleaseRef which cannot be noexcept
+ if (loplugin::isSamePathname(fn,
+ SRCDIR "/connectivity/source/drivers/dbase/dindexnode.cxx"))
+ return;
+ TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+ }
+
+ bool shouldVisitImplicitCode() const { return true; }
+
+ bool TraverseCXXConstructorDecl(CXXConstructorDecl*);
+ bool TraverseCXXMethodDecl(CXXMethodDecl*);
+ bool VisitCallExpr(const CallExpr*);
+ bool VisitCXXConstructExpr(const CXXConstructExpr*);
+ bool VisitVarDecl(const VarDecl*);
+
+private:
+ llvm::Optional<bool> IsCallThrows(const CallExpr* callExpr);
+ std::vector<bool> m_ConstructorThrows;
+ std::vector<std::vector<const Decl*>> m_Exclusions;
+ std::vector<bool> m_CannotFix;
+};
+
+bool NoExceptMove::TraverseCXXConstructorDecl(CXXConstructorDecl* constructorDecl)
+{
+ const bool isMove = constructorDecl->isMoveConstructor()
+ && constructorDecl->getExceptionSpecType() == EST_None
+ && !constructorDecl->isDefaulted() && !constructorDecl->isDeleted()
+ && !ignoreLocation(constructorDecl)
+ && constructorDecl->isThisDeclarationADefinition();
+ if (isMove)
+ {
+ m_ConstructorThrows.push_back(false);
+ m_Exclusions.emplace_back();
+ m_CannotFix.push_back(false);
+ }
+ bool rv = RecursiveASTVisitor::TraverseCXXConstructorDecl(constructorDecl);
+ if (isMove)
+ {
+ if (!m_ConstructorThrows.back())
+ {
+ report(DiagnosticsEngine::Warning, "move constructor can be noexcept",
+ constructorDecl->getSourceRange().getBegin())
+ << constructorDecl->getSourceRange();
+ auto canonicalDecl = constructorDecl->getCanonicalDecl();
+ if (canonicalDecl != constructorDecl)
+ report(DiagnosticsEngine::Note, "declaration here",
+ canonicalDecl->getSourceRange().getBegin())
+ << canonicalDecl->getSourceRange();
+ }
+ else if (bLookForStuffWeCanFix && !m_CannotFix.back())
+ {
+ report(DiagnosticsEngine::Warning, "move constructor can be noexcept",
+ constructorDecl->getSourceRange().getBegin())
+ << constructorDecl->getSourceRange();
+ auto canonicalDecl = constructorDecl->getCanonicalDecl();
+ if (canonicalDecl != constructorDecl)
+ report(DiagnosticsEngine::Note, "declaration here",
+ canonicalDecl->getSourceRange().getBegin())
+ << canonicalDecl->getSourceRange();
+ for (const Decl* callDecl : m_Exclusions.back())
+ report(DiagnosticsEngine::Warning, "but need to fix this to be noexcept",
+ callDecl->getSourceRange().getBegin())
+ << callDecl->getSourceRange();
+ }
+ m_ConstructorThrows.pop_back();
+ m_Exclusions.pop_back();
+ m_CannotFix.pop_back();
+ }
+ return rv;
+}
+
+bool NoExceptMove::TraverseCXXMethodDecl(CXXMethodDecl* methodDecl)
+{
+ bool isMove = methodDecl->isMoveAssignmentOperator()
+ && methodDecl->getExceptionSpecType() == EST_None && !methodDecl->isDefaulted()
+ && !methodDecl->isDeleted() && !ignoreLocation(methodDecl)
+ && methodDecl->isThisDeclarationADefinition();
+ if (isMove)
+ {
+ StringRef fn = getFileNameOfSpellingLoc(
+ compiler.getSourceManager().getSpellingLoc(compat::getBeginLoc(methodDecl)));
+ // SfxObjectShellLock::operator= calls SotObject::OwnerLock whichs in turn calls stuff which cannot be noexcept
+ if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/objsh.hxx"))
+ isMove = false;
+ }
+ if (isMove)
+ {
+ m_ConstructorThrows.push_back(false);
+ m_Exclusions.emplace_back();
+ m_CannotFix.push_back(false);
+ }
+ bool rv = RecursiveASTVisitor::TraverseCXXMethodDecl(methodDecl);
+ if (isMove)
+ {
+ if (!m_ConstructorThrows.back())
+ {
+ report(DiagnosticsEngine::Warning, "move operator= can be noexcept",
+ methodDecl->getSourceRange().getBegin())
+ << methodDecl->getSourceRange();
+ auto canonicalDecl = methodDecl->getCanonicalDecl();
+ if (canonicalDecl != methodDecl)
+ report(DiagnosticsEngine::Note, "declaration here",
+ canonicalDecl->getSourceRange().getBegin())
+ << canonicalDecl->getSourceRange();
+ }
+ else if (bLookForStuffWeCanFix && !m_CannotFix.back())
+ {
+ report(DiagnosticsEngine::Warning, "move operator= can be noexcept",
+ methodDecl->getSourceRange().getBegin())
+ << methodDecl->getSourceRange();
+ auto canonicalDecl = methodDecl->getCanonicalDecl();
+ if (canonicalDecl != methodDecl)
+ report(DiagnosticsEngine::Note, "declaration here",
+ canonicalDecl->getSourceRange().getBegin())
+ << canonicalDecl->getSourceRange();
+ for (const Decl* callDecl : m_Exclusions.back())
+ report(DiagnosticsEngine::Warning, "but need to fix this to be noexcept",
+ callDecl->getSourceRange().getBegin())
+ << callDecl->getSourceRange();
+ }
+ m_ConstructorThrows.pop_back();
+ m_Exclusions.pop_back();
+ m_CannotFix.pop_back();
+ }
+ return rv;
+}
+
+bool NoExceptMove::VisitCallExpr(const CallExpr* callExpr)
+{
+ if (ignoreLocation(callExpr))
+ return true;
+ if (m_ConstructorThrows.empty())
+ return true;
+ llvm::Optional<bool> bCallThrows = IsCallThrows(callExpr);
+ if (!bCallThrows)
+ {
+ callExpr->dump();
+ if (callExpr->getCalleeDecl())
+ callExpr->getCalleeDecl()->dump();
+ report(DiagnosticsEngine::Warning, "whats up doc?", callExpr->getSourceRange().getBegin())
+ << callExpr->getSourceRange();
+ m_ConstructorThrows.back() = true;
+ return true;
+ }
+ if (*bCallThrows)
+ m_ConstructorThrows.back() = true;
+ return true;
+}
+
+static bool IsCallThrowsSpec(clang::ExceptionSpecificationType est)
+{
+ return !(est == EST_DynamicNone || est == EST_NoThrow || est == EST_BasicNoexcept
+ || est == EST_NoexceptTrue);
+}
+
+bool NoExceptMove::VisitCXXConstructExpr(const CXXConstructExpr* constructExpr)
+{
+ if (ignoreLocation(constructExpr))
+ return true;
+ if (m_ConstructorThrows.empty())
+ return true;
+ auto constructorDecl = constructExpr->getConstructor();
+ auto est = constructorDecl->getExceptionSpecType();
+ if (constructorDecl->isDefaulted() && est == EST_None)
+ ; // ok, non-throwing
+ else if (IsCallThrowsSpec(est))
+ {
+ m_ConstructorThrows.back() = true;
+ }
+ return true;
+}
+
+bool NoExceptMove::VisitVarDecl(const VarDecl* varDecl)
+{
+ if (varDecl->getLocation().isValid() && ignoreLocation(varDecl))
+ return true;
+ if (m_ConstructorThrows.empty())
+ return true;
+ // The clang AST does not show me implicit calls to destructors at the end of a block,
+ // so assume any local var decls of class type will call their destructor.
+ if (!varDecl->getType()->isRecordType())
+ return true;
+ auto cxxRecordDecl = varDecl->getType()->getAsCXXRecordDecl();
+ if (!cxxRecordDecl)
+ return true;
+ auto destructorDecl = cxxRecordDecl->getDestructor();
+ if (!destructorDecl)
+ return true;
+ auto est = destructorDecl->getExceptionSpecType();
+ if (destructorDecl->isDefaulted() && est == EST_None)
+ ; // ok, non-throwing
+ else if (IsCallThrowsSpec(est))
+ {
+ m_ConstructorThrows.back() = true;
+ }
+ return true;
+}
+
+llvm::Optional<bool> NoExceptMove::IsCallThrows(const CallExpr* callExpr)
+{
+ const FunctionDecl* calleeFunctionDecl = callExpr->getDirectCallee();
+ if (calleeFunctionDecl)
+ {
+ auto est = calleeFunctionDecl->getExceptionSpecType();
+ if (bLookForStuffWeCanFix)
+ {
+ if (est == EST_None && !ignoreLocation(calleeFunctionDecl))
+ m_Exclusions.back().push_back(calleeFunctionDecl);
+ else
+ m_CannotFix.back() = true;
+ }
+ // Whitelist of functions that could be noexcept, but we can't change them because of backwards-compatibility reasons
+ // css::uno::XInterface::acquire
+ // css::uno::XInterface::release
+ if (calleeFunctionDecl->getIdentifier())
+ {
+ auto name = calleeFunctionDecl->getName();
+ if (auto cxxMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl))
+ if (loplugin::ContextCheck(cxxMethodDecl->getParent()->getDeclContext())
+ .Namespace("uno")
+ .Namespace("star")
+ .Namespace("sun")
+ .Namespace("com")
+ .GlobalNamespace()
+ && (name == "acquire" || name == "release"))
+ return false;
+ if (name == "osl_releasePipe" || name == "osl_destroySocketAddr")
+ return false;
+ }
+ return IsCallThrowsSpec(est);
+ }
+
+ auto calleeExpr = callExpr->getCallee();
+ if (isa<CXXDependentScopeMemberExpr>(calleeExpr) || isa<UnresolvedLookupExpr>(calleeExpr))
+ {
+ m_CannotFix.back() = true;
+ return true;
+ }
+
+ // check for call via function-pointer
+ clang::QualType calleeType;
+ if (auto fieldDecl = dyn_cast_or_null<FieldDecl>(callExpr->getCalleeDecl()))
+ calleeType = fieldDecl->getType();
+ else if (auto varDecl = dyn_cast_or_null<VarDecl>(callExpr->getCalleeDecl()))
+ calleeType = varDecl->getType();
+ else
+ {
+ m_CannotFix.back() = true;
+ return llvm::Optional<bool>();
+ }
+
+ // whitelist of functions that could be noexcept, but we can't change them because of backwards-compatibility reasons
+ if (auto typedefType = calleeType->getAs<TypedefType>())
+ if (typedefType->getDecl()->getName() == "uno_ReleaseMappingFunc")
+ return false;
+
+ if (calleeType->isPointerType())
+ calleeType = calleeType->getPointeeType();
+ auto funcProto = calleeType->getAs<FunctionProtoType>();
+ if (!funcProto)
+ {
+ m_CannotFix.back() = true;
+ return llvm::Optional<bool>();
+ }
+
+ auto est = funcProto->getExceptionSpecType();
+ if (bLookForStuffWeCanFix)
+ {
+ m_CannotFix.back() = true; // TODO, could improve
+ }
+ return IsCallThrowsSpec(est);
+}
+
+loplugin::Plugin::Registration<NoExceptMove> noexceptmove("noexceptmove");
+}
+
+#endif // CLANG_VERSION
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/test/noexceptmove.cxx b/compilerplugins/clang/test/noexceptmove.cxx
new file mode 100644
index 000000000000..fda58deae403
--- /dev/null
+++ b/compilerplugins/clang/test/noexceptmove.cxx
@@ -0,0 +1,102 @@
+/* -*- 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 "config_clang.h"
+
+// clang before V9 does not have API to report exception spec type
+#if CLANG_VERSION >= 90000
+
+namespace test1
+{
+class Mapping
+{
+ char* m_pMapping;
+
+ // expected-error@+1 {{move constructor can be noexcept [loplugin:noexceptmove]}}
+ Mapping(Mapping&& other)
+ : m_pMapping(other.m_pMapping)
+ {
+ other.m_pMapping = nullptr;
+ }
+
+ // expected-error@+1 {{move operator= can be noexcept [loplugin:noexceptmove]}}
+ Mapping& operator=(Mapping&& other)
+ {
+ m_pMapping = other.m_pMapping;
+ other.m_pMapping = nullptr;
+ return *this;
+ }
+};
+};
+
+// No warning expected, because calling throwing function.
+namespace test2
+{
+void foo() noexcept(false);
+
+class Bar
+{
+ Bar(Bar&&) { foo(); }
+};
+};
+
+// no warning expected, because calling throwing constructor
+namespace test3
+{
+struct Foo
+{
+ Foo() noexcept(false);
+};
+class Bar
+{
+ Bar(Bar&&) { Foo aFoo; }
+};
+
+class Bar2
+{
+ Foo m_foo;
+
+ Bar2(Bar2&&) {}
+};
+};
+
+// No warning expected, because calling throwing destructor.
+namespace test4
+{
+struct Foo
+{
+ ~Foo() noexcept(false);
+};
+
+class Bar
+{
+ Bar(Bar&&) { Foo aFoo; }
+};
+};
+
+// Check for calls to defaulted constructors.
+namespace test5
+{
+struct Foo
+{
+ Foo() = default; // non-throwing
+};
+class Bar
+{
+ Bar(Bar&&) // expected-error {{move constructor can be noexcept [loplugin:noexceptmove]}}
+ {
+ Foo aFoo;
+ (void)aFoo;
+ }
+};
+};
+
+#else
+// expected-no-diagnostics
+#endif // CLANG_VERSION
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/evoab2/NStatement.hxx b/connectivity/source/drivers/evoab2/NStatement.hxx
index a36e524af5c2..14c12700ca62 100644
--- a/connectivity/source/drivers/evoab2/NStatement.hxx
+++ b/connectivity/source/drivers/evoab2/NStatement.hxx
@@ -82,7 +82,7 @@ namespace connectivity
if (mpQuery)
e_book_query_ref(mpQuery);
}
- EBookQueryWrapper(EBookQueryWrapper&& rhs)
+ EBookQueryWrapper(EBookQueryWrapper&& rhs) noexcept
: mpQuery(rhs.mpQuery)
{
rhs.mpQuery = nullptr;
diff --git a/cppu/source/uno/lbmap.cxx b/cppu/source/uno/lbmap.cxx
index 6979c74042f9..a97d2a0dc829 100644
--- a/cppu/source/uno/lbmap.cxx
+++ b/cppu/source/uno/lbmap.cxx
@@ -60,13 +60,13 @@ class Mapping
public:
inline explicit Mapping( uno_Mapping * pMapping = nullptr );
inline Mapping( const Mapping & rMapping );
- Mapping(Mapping && other): _pMapping(other._pMapping)
+ Mapping(Mapping && other) noexcept : _pMapping(other._pMapping)
{ other._pMapping = nullptr; }
inline ~Mapping();
inline Mapping & operator = ( uno_Mapping * pMapping );
Mapping & operator = ( const Mapping & rMapping )
{ return operator = ( rMapping._pMapping ); }
- Mapping & operator =(Mapping && other) {
+ Mapping & operator =(Mapping && other) noexcept {
if (_pMapping != nullptr) {
(*_pMapping->release)(_pMapping);
}
diff --git a/include/com/sun/star/uno/Reference.h b/include/com/sun/star/uno/Reference.h
index 5f4c8ddea85f..50afd26a83b4 100644
--- a/include/com/sun/star/uno/Reference.h
+++ b/include/com/sun/star/uno/Reference.h
@@ -307,7 +307,7 @@ public:
@param rRef another reference
*/
- inline Reference( Reference< interface_type > && rRef );
+ inline Reference( Reference< interface_type > && rRef ) noexcept;
#endif
/** Up-casting conversion constructor: Copies interface reference.
@@ -586,7 +586,7 @@ public:
@param rRef an interface reference
@return this reference
*/
- inline Reference< interface_type > & SAL_CALL operator = ( Reference< interface_type > && rRef );
+ inline Reference< interface_type > & SAL_CALL operator = ( Reference< interface_type > && rRef ) noexcept;
#endif
/** Queries given interface reference for type interface_type.
diff --git a/include/com/sun/star/uno/Reference.hxx b/include/com/sun/star/uno/Reference.hxx
index c6869d922d7e..9edbd70d0f88 100644
--- a/include/com/sun/star/uno/Reference.hxx
+++ b/include/com/sun/star/uno/Reference.hxx
@@ -126,7 +126,7 @@ inline Reference< interface_type >::Reference( const Reference< interface_type >
#if defined LIBO_INTERNAL_ONLY
template< class interface_type >
-inline Reference< interface_type >::Reference( Reference< interface_type > && rRef )
+inline Reference< interface_type >::Reference( Reference< interface_type > && rRef ) noexcept
{
_pInterface = rRef._pInterface;
rRef._pInterface = nullptr;
@@ -353,7 +353,7 @@ inline Reference< interface_type > & Reference< interface_type >::operator = (
#if defined LIBO_INTERNAL_ONLY
template< class interface_type >
inline Reference< interface_type > & Reference< interface_type >::operator = (
- Reference< interface_type > && rRef )
+ Reference< interface_type > && rRef ) noexcept
{
if (_pInterface)
_pInterface->release();
diff --git a/include/cppuhelper/weakref.hxx b/include/cppuhelper/weakref.hxx
index cd05d3bee39b..c681284bac77 100644
--- a/include/cppuhelper/weakref.hxx
+++ b/include/cppuhelper/weakref.hxx
@@ -64,7 +64,7 @@ public:
WeakReferenceHelper( const WeakReferenceHelper & rWeakRef );
#if defined LIBO_INTERNAL_ONLY
- WeakReferenceHelper(WeakReferenceHelper && other): m_pImpl(other.m_pImpl)
+ WeakReferenceHelper(WeakReferenceHelper && other) noexcept : m_pImpl(other.m_pImpl)
{ other.m_pImpl = nullptr; }
#endif
diff --git a/include/osl/pipe.hxx b/include/osl/pipe.hxx
index e9cfe2e6c3f0..50022b7545c8 100644
--- a/include/osl/pipe.hxx
+++ b/include/osl/pipe.hxx
@@ -51,7 +51,7 @@ namespace osl
}
#if defined LIBO_INTERNAL_ONLY
- Pipe::Pipe(Pipe && other): m_handle(other.m_handle) {
+ Pipe::Pipe(Pipe && other) noexcept : m_handle(other.m_handle) {
other.m_handle = nullptr;
}
#endif
@@ -97,7 +97,7 @@ namespace osl
}
#if defined LIBO_INTERNAL_ONLY
- Pipe & Pipe::operator =(Pipe && other) {
+ Pipe & Pipe::operator =(Pipe && other) noexcept {
if (m_handle != nullptr) {
osl_releasePipe(m_handle);
}
diff --git a/include/osl/pipe_decl.hxx b/include/osl/pipe_decl.hxx
index 146b77a5624e..57f2c76b1c7c 100644
--- a/include/osl/pipe_decl.hxx
+++ b/include/osl/pipe_decl.hxx
@@ -59,7 +59,7 @@ public:
inline Pipe(const Pipe& pipe);
#if defined LIBO_INTERNAL_ONLY
- inline Pipe(Pipe && other);
+ inline Pipe(Pipe && other) noexcept;
#endif
/** Constructs a Pipe reference without acquiring the handle
@@ -108,7 +108,7 @@ public:
inline Pipe& SAL_CALL operator= (const Pipe& pipe);
#if defined LIBO_INTERNAL_ONLY
- inline Pipe & operator =(Pipe && other);
+ inline Pipe & operator =(Pipe && other) noexcept;
#endif
/** Assignment operator. If pipe was already created, the old one will
diff --git a/include/osl/socket.hxx b/include/osl/socket.hxx
index 0227095df089..640880144177 100644
--- a/include/osl/socket.hxx
+++ b/include/osl/socket.hxx
@@ -35,7 +35,7 @@ namespace osl
}
#if defined LIBO_INTERNAL_ONLY
- SocketAddr::SocketAddr(SocketAddr && other): m_handle(other.m_handle) {
+ SocketAddr::SocketAddr(SocketAddr && other) noexcept : m_handle(other.m_handle) {
other.m_handle = nullptr;
}
#endif
@@ -141,7 +141,7 @@ namespace osl
}
#if defined LIBO_INTERNAL_ONLY
- SocketAddr & SocketAddr::operator =(SocketAddr && other) {
+ SocketAddr & SocketAddr::operator =(SocketAddr && other) noexcept {
if (m_handle != nullptr) {
osl_destroySocketAddr(m_handle);
}
diff --git a/include/osl/socket_decl.hxx b/include/osl/socket_decl.hxx
index 3d2a05634348..25916897d0f9 100644
--- a/include/osl/socket_decl.hxx
+++ b/include/osl/socket_decl.hxx
@@ -51,7 +51,7 @@ namespace osl
inline SocketAddr(const SocketAddr& Addr);
#if defined LIBO_INTERNAL_ONLY
- inline SocketAddr(SocketAddr && other);
+ inline SocketAddr(SocketAddr && other) noexcept;
#endif
/** The SocketAddr takes over the responsibility of the handle (which means
@@ -141,7 +141,7 @@ namespace osl
inline SocketAddr & SAL_CALL operator= (const SocketAddr& Addr);
#if defined LIBO_INTERNAL_ONLY
- inline SocketAddr & operator =(SocketAddr && other);
+ inline SocketAddr & operator =(SocketAddr && other) noexcept;
#endif
/** Assigns the socket addr without copyconstructing it.
diff --git a/include/registry/registry.hxx b/include/registry/registry.hxx
index 200d91b4f426..9e264f4a30bd 100644
--- a/include/registry/registry.hxx
+++ b/include/registry/registry.hxx
@@ -90,7 +90,7 @@ public:
/// Copy constructor
inline Registry(const Registry& toCopy);
- Registry(Registry && other): m_pApi(other.m_pApi), m_hImpl(other.m_hImpl)
+ Registry(Registry && other) noexcept : m_pApi(other.m_pApi), m_hImpl(other.m_hImpl)
{ other.m_hImpl = nullptr; }
/// Destructor. The Destructor close the registry if it is open.
diff --git a/include/rtl/byteseq.h b/include/rtl/byteseq.h
index 0ec93c066652..e47d60e83e00 100644
--- a/include/rtl/byteseq.h
+++ b/include/rtl/byteseq.h
@@ -190,7 +190,7 @@ public:
*/
inline ByteSequence( const ByteSequence & rSeq );
#if defined LIBO_INTERNAL_ONLY
- inline ByteSequence( ByteSequence && rSeq );
+ inline ByteSequence( ByteSequence && rSeq ) noexcept;
#endif
/** Copy constructor Creates a copy from the C-Handle.
@@ -236,7 +236,7 @@ public:
*/
inline ByteSequence & SAL_CALL operator = ( const ByteSequence & rSeq );
#if defined LIBO_INTERNAL_ONLY
- inline ByteSequence & SAL_CALL operator = ( ByteSequence && rSeq );
+ inline ByteSequence & SAL_CALL operator = ( ByteSequence && rSeq ) noexcept;
#endif
/** Gets the length of sequence.
diff --git a/include/rtl/byteseq.hxx b/include/rtl/byteseq.hxx
index bf287830c77d..597e336e43ad 100644
--- a/include/rtl/byteseq.hxx
+++ b/include/rtl/byteseq.hxx
@@ -41,7 +41,7 @@ inline ByteSequence::ByteSequence( const ByteSequence & rSeq )
}
#if defined LIBO_INTERNAL_ONLY
-inline ByteSequence::ByteSequence( ByteSequence && rSeq )
+inline ByteSequence::ByteSequence( ByteSequence && rSeq ) noexcept
: _pSequence(rSeq._pSequence)
{
rSeq._pSequence = nullptr;
@@ -95,7 +95,7 @@ inline ByteSequence & ByteSequence::operator = ( const ByteSequence & rSeq )
}
#if defined LIBO_INTERNAL_ONLY
-inline ByteSequence & ByteSequence::operator = ( ByteSequence && rSeq )
+inline ByteSequence & ByteSequence::operator = ( ByteSequence && rSeq ) noexcept
{
::rtl_byte_sequence_release(_pSequence);
_pSequence = rSeq._pSequence;
diff --git a/include/rtl/ref.hxx b/include/rtl/ref.hxx
index 73c03ff7657d..b0324d99313d 100644
--- a/include/rtl/ref.hxx
+++ b/include/rtl/ref.hxx
@@ -77,7 +77,7 @@ public:
#ifdef LIBO_INTERNAL_ONLY
/** Move constructor...
*/
- Reference (Reference<reference_type> && handle)
+ Reference (Reference<reference_type> && handle) noexcept
: m_pBody (handle.m_pBody)
{
handle.m_pBody = nullptr;
diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx
index 3b33ee4f1ae5..d06a1b727394 100644
--- a/include/rtl/string.hxx
+++ b/include/rtl/string.hxx
@@ -129,7 +129,7 @@ public:
@param str an OString.
@since LibreOffice 5.2
*/
- OString( OString && str )
+ OString( OString && str ) noexcept
{
pData = str.pData;
str.pData = nullptr;
@@ -313,7 +313,7 @@ public:
@param str an OString.
@since LibreOffice 5.2
*/
- OString & operator=( OString && str )
+ OString & operator=( OString && str ) noexcept
{
rtl_string_release( pData );
pData = str.pData;
diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx
index 8050e0af9c41..18b717fd2b04 100644
--- a/include/rtl/ustring.hxx
+++ b/include/rtl/ustring.hxx
@@ -158,7 +158,7 @@ public:
@param str an OUString.
@since LibreOffice 5.2
*/
- OUString( OUString && str )
+ OUString( OUString && str ) noexcept
{
pData = str.pData;
str.pData = nullptr;
@@ -462,7 +462,7 @@ public:
@param str an OUString.
@since LibreOffice 5.2
*/
- OUString & operator=( OUString && str )
+ OUString & operator=( OUString && str ) noexcept
{
rtl_uString_release( pData );
pData = str.pData;
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index a25d60aa2db1..53797278c056 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -778,7 +778,7 @@ protected:
public:
SfxObjectShellLock() { pObj = nullptr; }
inline SfxObjectShellLock( const SfxObjectShellLock & rObj );
- inline SfxObjectShellLock( SfxObjectShellLock && rObj );
+ inline SfxObjectShellLock( SfxObjectShellLock && rObj ) noexcept;
inline SfxObjectShellLock( SfxObjectShell * pObjP );
inline void Clear();
inline ~SfxObjectShellLock();
@@ -797,7 +797,7 @@ inline SfxObjectShellLock::SfxObjectShellLock( const SfxObjectShellLock & rObj )
if( pObj )
pObj->OwnerLock( true );
}
-inline SfxObjectShellLock::SfxObjectShellLock( SfxObjectShellLock && rObj )
+inline SfxObjectShellLock::SfxObjectShellLock( SfxObjectShellLock && rObj ) noexcept
{
pObj = rObj.pObj;
rObj.pObj = nullptr;
diff --git a/include/store/store.hxx b/include/store/store.hxx
index fb4b430c5f2e..c4f4ce6db5fb 100644
--- a/include/store/store.hxx
+++ b/include/store/store.hxx
@@ -147,7 +147,7 @@ public:
/** Move construction.
*/
- OStoreDirectory (OStoreDirectory && rhs)
+ OStoreDirectory (OStoreDirectory && rhs) noexcept
: m_hImpl (rhs.m_hImpl)
{
rhs.m_hImpl = nullptr;
@@ -167,7 +167,7 @@ public:
/** Move assignment.
*/
- OStoreDirectory & operator= (OStoreDirectory && rhs)
+ OStoreDirectory & operator= (OStoreDirectory && rhs) noexcept
{
if (m_hImpl)
(void) store_releaseHandle (m_hImpl);
diff --git a/include/tools/globname.hxx b/include/tools/globname.hxx
index 3280cb69a2f6..9672f444ccad 100644
--- a/include/tools/globname.hxx
+++ b/include/tools/globname.hxx
@@ -60,7 +60,7 @@ public:
pImp( rObj.pImp )
{
}
- SvGlobalName( SvGlobalName && rObj ) :
+ SvGlobalName( SvGlobalName && rObj ) noexcept :
pImp( std::move(rObj.pImp) )
{
}
@@ -75,7 +75,7 @@ public:
SvGlobalName( const SvGUID & rId );
SvGlobalName & operator = ( const SvGlobalName & rObj );
- SvGlobalName & operator = ( SvGlobalName && rObj );
+ SvGlobalName & operator = ( SvGlobalName && rObj ) noexcept;
~SvGlobalName();
TOOLS_DLLPUBLIC friend SvStream & operator >> ( SvStream &, SvGlobalName & );
diff --git a/include/tools/poly.hxx b/include/tools/poly.hxx
index b0c6190b6eb8..aed40ece0367 100644
--- a/include/tools/poly.hxx
+++ b/include/tools/poly.hxx
@@ -98,7 +98,7 @@ public:
sal_uInt16 nPoints );
Polygon( const tools::Polygon& rPoly );
- Polygon( tools::Polygon&& rPoly);
+ Polygon( tools::Polygon&& rPoly) noexcept;
~Polygon();
void SetPoint( const Point& rPt, sal_uInt16 nPos );
@@ -155,7 +155,7 @@ public:
Point& operator[]( sal_uInt16 nPos );
tools::Polygon& operator=( const tools::Polygon& rPoly );
- tools::Polygon& operator=( tools::Polygon&& rPoly );
+ tools::Polygon& operator=( tools::Polygon&& rPoly ) noexcept;
bool operator==( const tools::Polygon& rPoly ) const;
bool operator!=( const tools::Polygon& rPoly ) const
{ return !(Polygon::operator==( rPoly )); }
diff --git a/include/typelib/typedescription.hxx b/include/typelib/typedescription.hxx
index ae8599bb1fdd..bfe7596801ea 100644
--- a/include/typelib/typedescription.hxx
+++ b/include/typelib/typedescription.hxx
@@ -83,7 +83,7 @@ public:
*/
inline TypeDescription( const TypeDescription & rDescr );
#if defined LIBO_INTERNAL_ONLY
- TypeDescription(TypeDescription && other): _pTypeDescr(other._pTypeDescr)
+ TypeDescription(TypeDescription && other) noexcept : _pTypeDescr(other._pTypeDescr)
{ other._pTypeDescr = nullptr; }
#endif
/** Constructor:
@@ -115,7 +115,7 @@ public:
{ return this->operator =( rTypeDescr.get() ); }
#if defined LIBO_INTERNAL_ONLY
- TypeDescription & operator =(TypeDescription && other) {
+ TypeDescription & operator =(TypeDescription && other) noexcept {
if (_pTypeDescr != nullptr) {
typelib_typedescription_release(_pTypeDescr);
}
diff --git a/include/uno/dispatcher.hxx b/include/uno/dispatcher.hxx
index bfd00d46b374..f23268e55593 100644
--- a/include/uno/dispatcher.hxx
+++ b/include/uno/dispatcher.hxx
@@ -59,7 +59,7 @@ public:
inline UnoInterfaceReference( UnoInterfaceReference const & ref );
#if defined LIBO_INTERNAL_ONLY
- UnoInterfaceReference(UnoInterfaceReference && other):
+ UnoInterfaceReference(UnoInterfaceReference && other) noexcept :
m_pUnoI(other.m_pUnoI)
{ other.m_pUnoI = nullptr; }
#endif
diff --git a/include/uno/environment.hxx b/include/uno/environment.hxx
index 5d5ef86021ef..0484790cfa36 100644
--- a/include/uno/environment.hxx
+++ b/include/uno/environment.hxx
@@ -95,7 +95,7 @@ public:
inline Environment( const Environment & rEnv );
#if defined LIBO_INTERNAL_ONLY
- Environment(Environment && other): _pEnv(other._pEnv)
+ Environment(Environment && other) noexcept : _pEnv(other._pEnv)
{ other._pEnv = nullptr; }
#endif
diff --git a/include/uno/mapping.hxx b/include/uno/mapping.hxx
index a575f251539f..be21909eb5c6 100644
--- a/include/uno/mapping.hxx
+++ b/include/uno/mapping.hxx
@@ -111,7 +111,7 @@ public:
inline Mapping( const Mapping & rMapping );
#if defined LIBO_INTERNAL_ONLY
- Mapping(Mapping && other): _pMapping(other._pMapping)
+ Mapping(Mapping && other) noexcept : _pMapping(other._pMapping)
{ other._pMapping = nullptr; }
#endif
@@ -134,7 +134,7 @@ public:
{ return operator = ( rMapping._pMapping ); }
#if defined LIBO_INTERNAL_ONLY
- Mapping & operator =(Mapping && other) {
+ Mapping & operator =(Mapping && other) noexcept {
if (_pMapping != nullptr) {
(*_pMapping->release)(_pMapping);
}
diff --git a/include/unotools/itemholderbase.hxx b/include/unotools/itemholderbase.hxx
index b401de3435c1..eeb5fa6ee9c0 100644
--- a/include/unotools/itemholderbase.hxx
+++ b/include/unotools/itemholderbase.hxx
@@ -83,7 +83,7 @@ struct TItemInfo
{
}
- TItemInfo(TItemInfo&& other)
+ TItemInfo(TItemInfo&& other) noexcept
: pItem(std::move(other.pItem))
, eItem(other.eItem)
{
diff --git a/include/unotools/tempfile.hxx b/include/unotools/tempfile.hxx
index b77d6e3a798f..b20a4f2fdf40 100644
--- a/include/unotools/tempfile.hxx
+++ b/include/unotools/tempfile.hxx
@@ -71,7 +71,7 @@ public:
TempFile( const OUString& rLeadingChars, bool _bStartWithZero=true, const OUString* pExtension=nullptr,
const OUString* pParent=nullptr, bool bCreateParentDirs=false );
- TempFile(TempFile && other);
+ TempFile(TempFile && other) noexcept;
/**
TempFile will be removed from disk in dtor if EnableKillingFile(true) was called before.
diff --git a/include/vcl/alpha.hxx b/include/vcl/alpha.hxx
index b0ea775e1516..f87ac133970a 100644
--- a/include/vcl/alpha.hxx
+++ b/include/vcl/alpha.hxx
@@ -42,7 +42,7 @@ public:
AlphaMask& operator=( const Bitmap& rBitmap );
AlphaMask& operator=( const AlphaMask& rAlphaMask ) { return static_cast<AlphaMask&>( Bitmap::operator=( rAlphaMask ) ); }
- AlphaMask& operator=( AlphaMask&& rAlphaMask ) { return static_cast<AlphaMask&>( Bitmap::operator=( std::move(rAlphaMask) ) ); }
+ AlphaMask& operator=( AlphaMask&& rAlphaMask ) noexcept { return static_cast<AlphaMask&>( Bitmap::operator=( std::move(rAlphaMask) ) ); }
bool operator!() const { return Bitmap::operator!(); }
bool operator==( const AlphaMask& rAlphaMask ) const { return Bitmap::operator==(rAlphaMask); }
bool operator!=( const AlphaMask& rAlphaMask ) const { return Bitmap::operator!=(rAlphaMask); }
diff --git a/include/vcl/font.hxx b/include/vcl/font.hxx
index 34ccf2ab5dd4..ac8c6d4c2153 100644
--- a/include/vcl/font.hxx
+++ b/include/vcl/font.hxx
@@ -48,7 +48,7 @@ class VCL_DLLPUBLIC Font
public:
explicit Font();
Font( const Font& ); // TODO make me explicit
- Font( Font&& );
+ Font( Font&& ) noexcept;
explicit Font( const OUString& rFamilyName, const Size& );
explicit Font( const OUString& rFamilyName, const OUString& rStyleName, const Size& );
explicit Font( FontFamily eFamily, const Size& );
@@ -150,7 +150,7 @@ public:
void GetFontAttributes( FontAttributes& rAttrs ) const;
Font& operator=( const Font& );
- Font& operator=( Font&& );
+ Font& operator=( Font&& ) noexcept;
bool operator==( const Font& ) const;
bool operator!=( const Font& rFont ) const
{ return !(Font::operator==( rFont )); }
diff --git a/include/vcl/region.hxx b/include/vcl/region.hxx
index 3edcaa033636..faa2da61141d 100644
--- a/include/vcl/region.hxx
+++ b/include/vcl/region.hxx
@@ -72,7 +72,7 @@ public:
explicit Region(const tools::PolyPolygon& rPolyPoly);
explicit Region(const basegfx::B2DPolyPolygon&);
Region(const vcl::Region& rRegion);
- Region(vcl::Region&& rRegion);
+ Region(vcl::Region&& rRegion) noexcept;
~Region();
// direct access to contents
@@ -114,7 +114,7 @@ public:
bool IsOver( const tools::Rectangle& rRect ) const;
vcl::Region& operator=( const vcl::Region& rRegion );
- vcl::Region& operator=( vcl::Region&& rRegion );
+ vcl::Region& operator=( vcl::Region&& rRegion ) noexcept;
vcl::Region& operator=( const tools::Rectangle& rRect );
bool operator==( const vcl::Region& rRegion ) const;
diff --git a/solenv/CompilerTest_compilerplugins_clang.mk b/solenv/CompilerTest_compilerplugins_clang.mk
index b791e5985587..167433f7974c 100644
--- a/solenv/CompilerTest_compilerplugins_clang.mk
+++ b/solenv/CompilerTest_compilerplugins_clang.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
compilerplugins/clang/test/loopvartoosmall \
compilerplugins/clang/test/nullptr \
compilerplugins/clang/test/mapindex \
+ compilerplugins/clang/test/noexceptmove \
compilerplugins/clang/test/oncevar \
compilerplugins/clang/test/oslendian-1 \
compilerplugins/clang/test/oslendian-2 \
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index a347c81d5bb3..4d12a236a4f1 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -76,8 +76,8 @@ class IDocumentMarkAccess
iterator(std::vector<::sw::mark::MarkBase*>::const_iterator const& rIter);
iterator(iterator const& rOther);
iterator& operator=(iterator const& rOther);
- iterator(iterator && rOther);
- iterator& operator=(iterator && rOther);
+ iterator(iterator && rOther) noexcept;
+ iterator& operator=(iterator && rOther) noexcept;
~iterator();
// FIXME unfortunately there's a requirement on input iterator
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 46b1d0ffb372..deb1048da936 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -80,12 +80,12 @@ auto IDocumentMarkAccess::iterator::operator=(iterator const& rOther) -> iterato
return *this;
}
-IDocumentMarkAccess::iterator::iterator(iterator && rOther)
+IDocumentMarkAccess::iterator::iterator(iterator && rOther) noexcept
: m_pIter(std::move(rOther.m_pIter))
{
}
-auto IDocumentMarkAccess::iterator::operator=(iterator && rOther) -> iterator&
+auto IDocumentMarkAccess::iterator::operator=(iterator && rOther) noexcept -> iterator&
{
m_pIter = std::move(rOther.m_pIter);
return *this;
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index 6f2d3115dfcf..0a597fdff1fc 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -872,7 +872,7 @@ Polygon::Polygon( const tools::Polygon& rPoly ) : mpImplPolygon(rPoly.mpImplPoly
{
}
-Polygon::Polygon( tools::Polygon&& rPoly)
+Polygon::Polygon( tools::Polygon&& rPoly) noexcept
: mpImplPolygon(std::move(rPoly.mpImplPolygon))
{
}
@@ -1555,7 +1555,7 @@ tools::Polygon& Polygon::operator=( const tools::Polygon& rPoly )
return *this;
}
-tools::Polygon& Polygon::operator=( tools::Polygon&& rPoly )
+tools::Polygon& Polygon::operator=( tools::Polygon&& rPoly ) noexcept
{
mpImplPolygon = std::move(rPoly.mpImplPolygon);
return *this;
diff --git a/tools/source/ref/globname.cxx b/tools/source/ref/globname.cxx
index 47f1da1577e5..0a87bcf17b5d 100644
--- a/tools/source/ref/globname.cxx
+++ b/tools/source/ref/globname.cxx
@@ -105,7 +105,7 @@ SvGlobalName & SvGlobalName::operator = ( const SvGlobalName & rObj )
return *this;
}
-SvGlobalName & SvGlobalName::operator = ( SvGlobalName && rObj )
+SvGlobalName & SvGlobalName::operator = ( SvGlobalName && rObj ) noexcept
{
pImp = std::move(rObj.pImp);
return *this;
diff --git a/unotools/source/ucbhelper/tempfile.cxx b/unotools/source/ucbhelper/tempfile.cxx
index 83c2effa919e..bce71120f4f9 100644
--- a/unotools/source/ucbhelper/tempfile.cxx
+++ b/unotools/source/ucbhelper/tempfile.cxx
@@ -370,7 +370,7 @@ TempFile::TempFile( const OUString& rLeadingChars, bool _bStartWithZero,
true, true, bCreateParentDirs );
}
-TempFile::TempFile(TempFile && other):
+TempFile::TempFile(TempFile && other) noexcept :
aName(std::move(other.aName)), pStream(std::move(other.pStream)), bIsDirectory(other.bIsDirectory),
bKillingFileEnabled(other.bKillingFileEnabled)
{
diff --git a/vcl/source/font/font.cxx b/vcl/source/font/font.cxx
index 914ea9880b82..1d3528b0d7d2 100644
--- a/vcl/source/font/font.cxx
+++ b/vcl/source/font/font.cxx
@@ -49,7 +49,7 @@ Font::Font( const vcl::Font& rFont ) : mpImplFont( rFont.mpImplFont )
{
}
-Font::Font( vcl::Font&& rFont ) : mpImplFont( std::move(rFont.mpImplFont) )
+Font::Font( vcl::Font&& rFont ) noexcept : mpImplFont( std::move(rFont.mpImplFont) )
{
}
@@ -283,7 +283,7 @@ Font& Font::operator=( const vcl::Font& rFont )
return *this;
}
-Font& Font::operator=( vcl::Font&& rFont )
+Font& Font::operator=( vcl::Font&& rFont ) noexcept
{
mpImplFont = std::move(rFont.mpImplFont);
return *this;
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
index 983d76305fa9..4f830a2195e8 100644
--- a/vcl/source/gdi/region.cxx
+++ b/vcl/source/gdi/region.cxx
@@ -365,7 +365,7 @@ Region::Region(const basegfx::B2DPolyPolygon& rPolyPoly)
Region::Region(const vcl::Region&) = default;
-Region::Region(vcl::Region&& rRegion)
+Region::Region(vcl::Region&& rRegion) noexcept
: mpB2DPolyPolygon(std::move(rRegion.mpB2DPolyPolygon)),
mpPolyPolygon(std::move(rRegion.mpPolyPolygon)),
mpRegionBand(std::move(rRegion.mpRegionBand)),
@@ -1425,7 +1425,7 @@ void vcl::Region::SetEmpty()
Region& vcl::Region::operator=( const vcl::Region& ) = default;
-Region& vcl::Region::operator=( vcl::Region&& rRegion )
+Region& vcl::Region::operator=( vcl::Region&& rRegion ) noexcept
{
mpB2DPolyPolygon = std::move(rRegion.mpB2DPolyPolygon);
mpPolyPolygon = std::move(rRegion.mpPolyPolygon);