new loplugin:noexceptmove
idea from mike kaganski look for places where we can mark move operators as noexcept, which makes some STL operations more efficient Change-Id: Id732b89d1fcadd5ceb0ea2b9d159fed06136330f Reviewed-on: https://gerrit.libreoffice.org/78251 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 & );
|
||||
|
||||
@@ -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 )); }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ struct TItemInfo
|
||||
{
|
||||
}
|
||||
|
||||
TItemInfo(TItemInfo&& other)
|
||||
TItemInfo(TItemInfo&& other) noexcept
|
||||
: pItem(std::move(other.pItem))
|
||||
, eItem(other.eItem)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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 )); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user