b512ce255f
The main reason for the "home-grown" UpCast introduced with904b3d1fce
"Up-cast conversion constructor for css::uno::Reference" in 2013 was probably that we could not yet rely on C++11 std::is_base_of back then. A (welcome) side effect was that the derived class could be incomplete. However, specializations of UpCast relying on whether or not T2 is incomplete are obviously an ODR violation if the type is incomplete in some TUs and complete (and derived from T1) in others. And even if UpCast had internal linkage, it would still be brittle that its behavior depends on the completeness of T2 at the point of the template's instantiation, and not necessarily at the point of use. That means we should better base that ctor on std::is_base_of (which we can do now since39a1edd6fe
"Make css::uno::Reference upcast ctor LIBO_INTERNAL_ONLY"), which causes a compilation error at least on Clang and GCC if the completeness requirements are not met. This change fixes all the cases where types need to be complete now, plus any resulting loplugin:referencecasting warnings ("the source reference is already a subtype of the destination reference"). Change-Id: Ieb9e3552e90adbf2c5a5af933dcb872e20661a2f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92950 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
477 lines
13 KiB
C++
477 lines
13 KiB
C++
/* -*- 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/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#ifndef INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX
|
|
#define INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX
|
|
|
|
#include "sal/config.h"
|
|
|
|
#include <cstddef>
|
|
#include <ostream>
|
|
|
|
#include "com/sun/star/uno/Reference.h"
|
|
#include "com/sun/star/uno/RuntimeException.hpp"
|
|
#include "com/sun/star/uno/XInterface.hpp"
|
|
#include "com/sun/star/uno/Any.hxx"
|
|
#include "cppu/cppudllapi.h"
|
|
|
|
extern "C" CPPU_DLLPUBLIC rtl_uString * SAL_CALL cppu_unsatisfied_iquery_msg(
|
|
typelib_TypeDescriptionReference * pType )
|
|
SAL_THROW_EXTERN_C();
|
|
extern "C" CPPU_DLLPUBLIC rtl_uString * SAL_CALL cppu_unsatisfied_iset_msg(
|
|
typelib_TypeDescriptionReference * pType )
|
|
SAL_THROW_EXTERN_C();
|
|
|
|
namespace com
|
|
{
|
|
namespace sun
|
|
{
|
|
namespace star
|
|
{
|
|
namespace uno
|
|
{
|
|
|
|
|
|
inline XInterface * BaseReference::iquery(
|
|
XInterface * pInterface, const Type & rType )
|
|
{
|
|
if (pInterface)
|
|
{
|
|
Any aRet( pInterface->queryInterface( rType ) );
|
|
if (typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass)
|
|
{
|
|
XInterface * pRet = static_cast< XInterface * >( aRet.pReserved );
|
|
aRet.pReserved = NULL;
|
|
return pRet;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline XInterface * Reference< interface_type >::iquery(
|
|
XInterface * pInterface )
|
|
{
|
|
return BaseReference::iquery(pInterface, interface_type::static_type());
|
|
}
|
|
|
|
inline XInterface * BaseReference::iquery_throw(
|
|
XInterface * pInterface, const Type & rType )
|
|
{
|
|
XInterface * pQueried = iquery( pInterface, rType );
|
|
if (pQueried)
|
|
return pQueried;
|
|
throw RuntimeException(
|
|
::rtl::OUString( cppu_unsatisfied_iquery_msg( rType.getTypeLibType() ), SAL_NO_ACQUIRE ),
|
|
Reference< XInterface >( pInterface ) );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline XInterface * Reference< interface_type >::iquery_throw(
|
|
XInterface * pInterface )
|
|
{
|
|
return BaseReference::iquery_throw(
|
|
pInterface, interface_type::static_type());
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline interface_type * Reference< interface_type >::iset_throw(
|
|
interface_type * pInterface )
|
|
{
|
|
if (pInterface)
|
|
{
|
|
castToXInterface(pInterface)->acquire();
|
|
return pInterface;
|
|
}
|
|
throw RuntimeException(
|
|
::rtl::OUString( cppu_unsatisfied_iset_msg( interface_type::static_type().getTypeLibType() ), SAL_NO_ACQUIRE ),
|
|
NULL );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::~Reference() COVERITY_NOEXCEPT_FALSE
|
|
{
|
|
if (_pInterface)
|
|
_pInterface->release();
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference()
|
|
{
|
|
_pInterface = NULL;
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef )
|
|
{
|
|
_pInterface = rRef._pInterface;
|
|
if (_pInterface)
|
|
_pInterface->acquire();
|
|
}
|
|
|
|
#if defined LIBO_INTERNAL_ONLY
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( Reference< interface_type > && rRef ) noexcept
|
|
{
|
|
_pInterface = rRef._pInterface;
|
|
rRef._pInterface = nullptr;
|
|
}
|
|
|
|
template< class interface_type > template< class derived_type >
|
|
inline Reference< interface_type >::Reference(
|
|
const Reference< derived_type > & rRef,
|
|
std::enable_if_t<
|
|
std::is_base_of_v<interface_type, derived_type>
|
|
&& !std::is_same_v<interface_type, XInterface>, void *>)
|
|
{
|
|
interface_type * p = rRef.get();
|
|
_pInterface = p;
|
|
if (_pInterface)
|
|
_pInterface->acquire();
|
|
}
|
|
#endif
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( interface_type * pInterface )
|
|
{
|
|
_pInterface = castToXInterface(pInterface);
|
|
if (_pInterface)
|
|
_pInterface->acquire();
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( interface_type * pInterface, __sal_NoAcquire )
|
|
{
|
|
_pInterface = castToXInterface(pInterface);
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_NoAcquire )
|
|
{
|
|
_pInterface = castToXInterface(pInterface);
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_Query )
|
|
{
|
|
_pInterface = iquery( rRef.get() );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_Query )
|
|
{
|
|
_pInterface = iquery( pInterface );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_Query )
|
|
{
|
|
_pInterface = (typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass
|
|
? iquery( static_cast< XInterface * >( rAny.pReserved ) ) : NULL);
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_QueryThrow )
|
|
{
|
|
_pInterface = iquery_throw( rRef.get() );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_QueryThrow )
|
|
{
|
|
_pInterface = iquery_throw( pInterface );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_QueryThrow )
|
|
{
|
|
_pInterface = iquery_throw( typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass
|
|
? static_cast< XInterface * >( rAny.pReserved ) : NULL );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef, UnoReference_SetThrow )
|
|
{
|
|
_pInterface = castToXInterface( iset_throw( rRef.get() ) );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_SetThrow )
|
|
{
|
|
_pInterface = castToXInterface( iset_throw( pInterface ) );
|
|
}
|
|
|
|
|
|
template< class interface_type >
|
|
inline void Reference< interface_type >::clear()
|
|
{
|
|
if (_pInterface)
|
|
{
|
|
XInterface * const pOld = _pInterface;
|
|
_pInterface = NULL;
|
|
pOld->release();
|
|
}
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
interface_type * pInterface )
|
|
{
|
|
if (pInterface)
|
|
castToXInterface(pInterface)->acquire();
|
|
XInterface * const pOld = _pInterface;
|
|
_pInterface = castToXInterface(pInterface);
|
|
if (pOld)
|
|
pOld->release();
|
|
return (NULL != pInterface);
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
interface_type * pInterface, __sal_NoAcquire )
|
|
{
|
|
XInterface * const pOld = _pInterface;
|
|
_pInterface = castToXInterface(pInterface);
|
|
if (pOld)
|
|
pOld->release();
|
|
return (NULL != pInterface);
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
interface_type * pInterface, UnoReference_NoAcquire )
|
|
{
|
|
return set( pInterface, SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
const Reference< interface_type > & rRef )
|
|
{
|
|
return set( castFromXInterface( rRef._pInterface ) );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
XInterface * pInterface, UnoReference_Query )
|
|
{
|
|
return set( castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
const BaseReference & rRef, UnoReference_Query )
|
|
{
|
|
return set( castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
|
|
template< class interface_type >
|
|
inline bool Reference< interface_type >::set(
|
|
Any const & rAny, UnoReference_Query )
|
|
{
|
|
return set(
|
|
castFromXInterface(
|
|
iquery(
|
|
rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE
|
|
? static_cast< XInterface * >( rAny.pReserved ) : NULL )),
|
|
SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
|
|
template< class interface_type >
|
|
inline void Reference< interface_type >::set(
|
|
XInterface * pInterface, UnoReference_QueryThrow )
|
|
{
|
|
set( castFromXInterface(iquery_throw( pInterface )), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline void Reference< interface_type >::set(
|
|
const BaseReference & rRef, UnoReference_QueryThrow )
|
|
{
|
|
set( castFromXInterface(iquery_throw( rRef.get() )), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
|
|
template< class interface_type >
|
|
inline void Reference< interface_type >::set(
|
|
Any const & rAny, UnoReference_QueryThrow )
|
|
{
|
|
set( castFromXInterface(
|
|
iquery_throw(
|
|
rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE
|
|
? static_cast< XInterface * >( rAny.pReserved ) : NULL )),
|
|
SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline void Reference< interface_type >::set(
|
|
interface_type * pInterface, UnoReference_SetThrow )
|
|
{
|
|
set( iset_throw( pInterface ), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline void Reference< interface_type >::set(
|
|
const Reference< interface_type > & rRef, UnoReference_SetThrow )
|
|
{
|
|
set( rRef.get(), UNO_SET_THROW );
|
|
}
|
|
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type > & Reference< interface_type >::operator = (
|
|
interface_type * pInterface )
|
|
{
|
|
set( pInterface );
|
|
return *this;
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type > & Reference< interface_type >::operator = (
|
|
const Reference< interface_type > & rRef )
|
|
{
|
|
set( castFromXInterface( rRef._pInterface ) );
|
|
return *this;
|
|
}
|
|
|
|
#if defined LIBO_INTERNAL_ONLY
|
|
template< class interface_type >
|
|
inline Reference< interface_type > & Reference< interface_type >::operator = (
|
|
Reference< interface_type > && rRef ) noexcept
|
|
{
|
|
if (_pInterface)
|
|
_pInterface->release();
|
|
_pInterface = rRef._pInterface;
|
|
rRef._pInterface = nullptr;
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type > Reference< interface_type >::query(
|
|
const BaseReference & rRef )
|
|
{
|
|
return Reference< interface_type >(
|
|
castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
template< class interface_type >
|
|
inline Reference< interface_type > Reference< interface_type >::query(
|
|
XInterface * pInterface )
|
|
{
|
|
return Reference< interface_type >(
|
|
castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE );
|
|
}
|
|
|
|
|
|
inline bool BaseReference::operator == ( XInterface * pInterface ) const
|
|
{
|
|
if (_pInterface == pInterface)
|
|
return true;
|
|
try
|
|
{
|
|
// only the query to XInterface must return the same pointer if they belong to same objects
|
|
Reference< XInterface > x1( _pInterface, UNO_QUERY );
|
|
Reference< XInterface > x2( pInterface, UNO_QUERY );
|
|
return (x1._pInterface == x2._pInterface);
|
|
}
|
|
catch (RuntimeException &)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
inline bool BaseReference::operator < (
|
|
const BaseReference & rRef ) const
|
|
{
|
|
if (_pInterface == rRef._pInterface)
|
|
return false;
|
|
try
|
|
{
|
|
// only the query to XInterface must return the same pointer:
|
|
Reference< XInterface > x1( _pInterface, UNO_QUERY );
|
|
Reference< XInterface > x2( rRef, UNO_QUERY );
|
|
return (x1._pInterface < x2._pInterface);
|
|
}
|
|
catch (RuntimeException &)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
inline bool BaseReference::operator != ( XInterface * pInterface ) const
|
|
{
|
|
return (! operator == ( pInterface ));
|
|
}
|
|
|
|
inline bool BaseReference::operator == ( const BaseReference & rRef ) const
|
|
{
|
|
return operator == ( rRef._pInterface );
|
|
}
|
|
|
|
inline bool BaseReference::operator != ( const BaseReference & rRef ) const
|
|
{
|
|
return (! operator == ( rRef._pInterface ));
|
|
}
|
|
|
|
#if defined LIBO_INTERNAL_ONLY
|
|
/**
|
|
Support for BaseReference in std::ostream (and thus in CPPUNIT_ASSERT or
|
|
SAL_INFO macros, for example).
|
|
|
|
@since LibreOffice 5.4
|
|
*/
|
|
template<typename charT, typename traits> std::basic_ostream<charT, traits> &
|
|
operator <<(
|
|
std::basic_ostream<charT, traits> & stream, BaseReference const & ref)
|
|
{ return stream << ref.get(); }
|
|
#endif
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined LIBO_INTERNAL_ONLY
|
|
namespace std
|
|
{
|
|
|
|
/**
|
|
Make css::uno::Reference hashable by default for use in STL containers.
|
|
|
|
@since LibreOffice 6.3
|
|
*/
|
|
template<typename T>
|
|
struct hash<::css::uno::Reference<T>>
|
|
{
|
|
std::size_t operator()(::css::uno::Reference<T> const & s) const
|
|
{ return size_t(s.get()); }
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|