Skip to content

Commit

Permalink
Revert "stronger typing for SwClient::GetRegisteredIn"
Browse files Browse the repository at this point in the history
This reverts commit 687080c, as it caused e.g.
CppunitTest_sw_docbookexport to fail with

> sw/inc/calbck.hxx:428:18: runtime error: downcast of address 0x7ba8053a9db8 which does not point to an object of type 'SwClient' (aka 'ClientBase<SwModify>')
> 0x7ba8053a9da0: note: object is base class subobject at offset 24 within object of type 'SwFormatHeader'
>  00 00 00 00  d0 8b c9 ae 47 7b 00 00  01 00 00 00 66 00 48 01  40 6c 00 00 88 be be be  50 8c c9 ae
>               ^                                                                          ~~~~~~~~~~~
>                                                                                          vptr for 'sw::ClientBase<SwFrameFormat>' base class of 'SwFormatHeader'
>  #0 in SwIterator<sw::ClientBase<SwModify>, SwModify, (sw::IteratorMode)0>::First() at sw/inc/calbck.hxx:428:18
>  #1 in SwModify::CallSwClientNotify(SfxHint const&) const at sw/source/core/attr/calbck.cxx:237:35
>  #2 in sw::BroadcastingModify::CallSwClientNotify(SfxHint const&) const at sw/source/core/attr/calbck.cxx:259:15
>  #3 in SwModify::SwClientNotify(SwModify const&, SfxHint const&) at sw/source/core/attr/calbck.cxx:229:5
>  #4 in SwFormat::SwClientNotify(SwModify const&, SfxHint const&) at sw/source/core/attr/format.cxx:309:19
>  #5 in SwFrameFormat::SwClientNotify(SwModify const&, SfxHint const&) at sw/source/core/layout/atrfrm.cxx:2849:15
>  #6 in sw::ClientNotifyAttrChg(SwModify&, SwAttrSet const&, SwAttrSet&, SwAttrSet&) at sw/source/core/attr/calbck.cxx:268:13
>  #7 in SwFormat::SetFormatAttr(SfxItemSet const&) at sw/source/core/attr/format.cxx:604:13
>  #8 in FillHdFt(SwFrameFormat*, SfxItemSet const&) at sw/source/uibase/utlui/uitool.cxx:239:14
>  #9 in ItemSetToPageDesc(SfxItemSet const&, SwPageDesc&) at sw/source/uibase/utlui/uitool.cxx:340:13
>  #10 in SwDocStyleSheet::SetItemSet(SfxItemSet const&, bool, bool) at sw/source/uibase/app/docstyle.cxx:1894:13
>  #11 in SwXPageStyle::SetPropertyValues_Impl(com::sun::star::uno::Sequence<rtl::OUString> const&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) at sw/source/core/unocore/unostyle.cxx:3157:33
>  #12 in SwXPageStyle::setPropertyValue(rtl::OUString const&, com::sun::star::uno::Any const&) at sw/source/core/unocore/unostyle.cxx:3453:5
>  #13 in writerfilter::dmapper::DomainMapper_Impl::PushPageHeaderFooter(writerfilter::dmapper::PagePartType, writerfilter::dmapper::PageType) at sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx:3910:25
>  #14 in writerfilter::dmapper::DomainMapper_Impl::substream(unsigned int, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&) at sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx:10049:13
>  #15 in writerfilter::dmapper::DomainMapper::lcl_substream(unsigned int, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&) at sw/source/writerfilter/dmapper/DomainMapper.cxx:4746:14
>  #16 in writerfilter::LoggedStream::substream(unsigned int, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&) at sw/source/writerfilter/dmapper/LoggedResources.cxx:272:5
>  #17 in writerfilter::ooxml::OOXMLDocumentImpl::resolveFastSubStreamWithId(writerfilter::Stream&, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&, unsigned int) at sw/source/writerfilter/ooxml/OOXMLDocumentImpl.cxx:127:13
>  #18 in writerfilter::ooxml::OOXMLDocumentImpl::resolveHeader(writerfilter::Stream&, int, rtl::OUString const&) at sw/source/writerfilter/ooxml/OOXMLDocumentImpl.cxx:384:10
>  #19 in writerfilter::ooxml::OOXMLFastContextHandler::resolveHeader(int, rtl::OUString const&) at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:895:35
>  #20 in writerfilter::ooxml::OOXMLHeaderHandler::finalize() at sw/source/writerfilter/ooxml/Handler.cxx:214:20
>  #21 in writerfilter::ooxml::OOXMLFastContextHandlerProperties::handleHdrFtr() at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:1117:28
>  #22 in writerfilter::ooxml::OOXMLFactory_wml::endAction(writerfilter::ooxml::OOXMLFastContextHandler*) at workdir/CustomTarget/sw/source/writerfilter/ooxml/OOXMLFactory_wml.cxx:7530:26
>  #23 in writerfilter::ooxml::OOXMLFactory::endAction(writerfilter::ooxml::OOXMLFastContextHandler*) at sw/source/writerfilter/ooxml/OOXMLFactory.cxx:157:19
>  #24 in writerfilter::ooxml::OOXMLFastContextHandler::endAction() at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:320:5
>  #25 in writerfilter::ooxml::OOXMLFastContextHandlerProperties::lcl_endFastElement(int) at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:1038:9
>  #26 in writerfilter::ooxml::OOXMLFastContextHandler::endFastElement(int) at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:227:9
>  #27 in (anonymous namespace)::Entity::endElement() at sax/source/fastparser/fastparser.cxx:515:27
>  #28 in sax_fastparser::FastSaxParserImpl::callbackEndElement() at sax/source/fastparser/fastparser.cxx:1338:17
>  #29 in (anonymous namespace)::call_callbackEndElement(void*, unsigned char const*, unsigned char const*, unsigned char const*) at sax/source/fastparser/fastparser.cxx:339:18
>  #30 in xmlParseTryOrFinish at workdir/UnpackedTarball/libxml2/parser.c:11254:8
>  #31 in xmlParseChunk at workdir/UnpackedTarball/libxml2/parser.c:11636:5
>  #32 in sax_fastparser::FastSaxParserImpl::parse() at sax/source/fastparser/fastparser.cxx:1117:25
>  #33 in sax_fastparser::FastSaxParserImpl::parseStream(com::sun::star::xml::sax::InputSource const&) at sax/source/fastparser/fastparser.cxx:896:9
>  #34 in sax_fastparser::FastSaxParser::parseStream(com::sun::star::xml::sax::InputSource const&) at sax/source/fastparser/fastparser.cxx:1477:13
>  #35 in writerfilter::ooxml::OOXMLDocumentImpl::resolve(writerfilter::Stream&) at sw/source/writerfilter/ooxml/OOXMLDocumentImpl.cxx:514:18
>  #36 in (anonymous namespace)::WriterFilter::filter(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at sw/source/writerfilter/filter/WriterFilter.cxx:210:24
>  #37 in SfxObjectShell::ImportFrom(SfxMedium&, com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at sfx2/source/doc/objstor.cxx:2719:34
>  #38 in SfxObjectShell::DoLoad(SfxMedium*) at sfx2/source/doc/objstor.cxx:767:23
>  #39 in SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at sfx2/source/doc/sfxbasemodel.cxx:1991:36
>  #40 in (anonymous namespace)::SfxFrameLoader_Impl::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&) at sfx2/source/view/frmload.cxx:725:28
>  #41 in framework::LoadEnv::impl_loadContent() at framework/source/loadenv/loadenv.cxx:1180:37
>  #42 in framework::LoadEnv::start() at framework/source/loadenv/loadenv.cxx:415:20
>  #43 in framework::LoadEnv::startLoading(rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&, rtl::OUString const&, int, LoadEnvFeatures) at framework/source/loadenv/loadenv.cxx:311:5
>  #44 in framework::LoadEnv::loadComponentFromURL(com::sun::star::uno::Reference<com::sun::star::frame::XComponentLoader> const&, com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&, rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at framework/source/loadenv/loadenv.cxx:167:14
>  #45 in framework::Desktop::loadComponentFromURL(rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at framework/source/services/desktop.cxx:592:16
>  #46 in non-virtual thunk to framework::Desktop::loadComponentFromURL(rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at framework/source/services/desktop.cxx
>  #47 in unotest::MacrosTest::loadFromDesktop(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at unotest/source/cpp/macros_test.cxx:72:62
>  #48 in UnoApiTest::loadWithParams(rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at test/source/unoapi_test.cxx:126:19
>  #49 in UnoApiTest::loadFromURL(rtl::OUString const&, char const*) at test/source/unoapi_test.cxx:108:5
>  #50 in SwModelTestBase::loadURL(rtl::OUString const&, char const*) at sw/qa/unit/swmodeltestbase.cxx:384:5
>  #51 in SwModelTestBase::createSwDoc(char const*, char const*) at sw/qa/unit/swmodeltestbase.cxx:433:9
>  #52 in (anonymous namespace)::testtdf91095::TestBody() at sw/qa/extras/docbookexport/docbookexport.cxx:35:5

Change-Id: I1e6d6888c8b311988e627845107148c7970fbaab
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179502
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <[email protected]>
  • Loading branch information
stbergmann committed Dec 29, 2024
1 parent 1389f46 commit 9d69c20
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 182 deletions.
170 changes: 45 additions & 125 deletions sw/inc/calbck.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <svl/hint.hxx>
#include <svl/broadcast.hxx>
#include <svl/poolitem.hxx>
#include <tools/debug.hxx>
#include "swdllapi.h"
#include "ring.hxx"
#include <type_traits>
Expand Down Expand Up @@ -65,18 +64,10 @@ class SwFindNearestNode;
This is still subject to refactoring.
*/


namespace sw
{
class ClientIteratorBase;
class ListenerEntry;
enum class IteratorMode { Exact, UnwrapMulti };
}

template<typename TElementType, typename TSource, sw::IteratorMode eMode> class SwIterator;

namespace sw
{
void ClientNotifyAttrChg(SwModify& rModify, const SwAttrSet& aSet, SwAttrSet& aOld, SwAttrSet& aNew);
struct SAL_DLLPUBLIC_RTTI LegacyModifyHint final: SfxHint
{
Expand Down Expand Up @@ -135,58 +126,52 @@ namespace sw
virtual const SwRowFrame* DynCastRowFrame() const { return nullptr; }
virtual const SwTable* DynCastTable() const { return nullptr; }
};
enum class IteratorMode { Exact, UnwrapMulti };
}

template<typename T>
class SW_DLLPUBLIC ClientBase : public ::sw::WriterListener
{
// avoids making the details of the linked list and the callback method public
friend class ::SwModify;
friend class sw::ClientIteratorBase;
friend class sw::ListenerEntry;
template<typename E, typename S, sw::IteratorMode> friend class ::SwIterator;

T *m_pRegisteredIn; ///< event source
// SwClient
class SW_DLLPUBLIC SwClient : public ::sw::WriterListener
{
// avoids making the details of the linked list and the callback method public
friend class SwModify;
friend class sw::ClientIteratorBase;
friend class sw::ListenerEntry;
template<typename E, typename S, sw::IteratorMode> friend class SwIterator;

protected:
// single argument ctors shall be explicit.
inline explicit ClientBase( T* pToRegisterIn )
: m_pRegisteredIn( nullptr )
{
if(pToRegisterIn)
pToRegisterIn->Add(*this);
}
SwModify *m_pRegisteredIn; ///< event source

// write access to pRegisteredIn shall be granted only to the object itself (protected access)
T* GetRegisteredInNonConst() const { return m_pRegisteredIn; }
protected:
// single argument ctors shall be explicit.
inline explicit SwClient( SwModify* pToRegisterIn );

// when overriding this, you MUST call SwClient::SwClientNotify() in the override!
virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override;
// write access to pRegisteredIn shall be granted only to the object itself (protected access)
SwModify* GetRegisteredInNonConst() const { return m_pRegisteredIn; }

public:
ClientBase() : m_pRegisteredIn(nullptr) {}
ClientBase(ClientBase&&) noexcept;
virtual ~ClientBase() override;
// when overriding this, you MUST call SwClient::SwClientNotify() in the override!
virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override;

public:
SwClient() : m_pRegisteredIn(nullptr) {}
SwClient(SwClient&&) noexcept;
virtual ~SwClient() override;

// in case an SwModify object is destroyed that itself is registered in another SwModify,
// its SwClient objects can decide to get registered to the latter instead by calling this method
std::optional<sw::ModifyChangedHint> CheckRegistration( const SfxPoolItem* pOldValue );
// SwFormat wants to die different than the rest: It wants to reparent every client to its parent
// and then send a SwFormatChg hint.
void CheckRegistrationFormat(SwFormat& rOld);

const T* GetRegisteredIn() const { return m_pRegisteredIn; }
T* GetRegisteredIn() { return m_pRegisteredIn; }
void EndListeningAll();
void StartListeningToSameModifyAs(const ClientBase&);
// in case an SwModify object is destroyed that itself is registered in another SwModify,
// its SwClient objects can decide to get registered to the latter instead by calling this method
std::optional<sw::ModifyChangedHint> CheckRegistration( const SfxPoolItem* pOldValue );
// SwFormat wants to die different than the rest: It wants to reparent every client to its parent
// and then send a SwFormatChg hint.
void CheckRegistrationFormat(SwFormat& rOld);

const SwModify* GetRegisteredIn() const { return m_pRegisteredIn; }
SwModify* GetRegisteredIn() { return m_pRegisteredIn; }
void EndListeningAll();
void StartListeningToSameModifyAs(const SwClient&);

// get information about attribute
virtual bool GetInfo( SwFindNearestNode& ) const { return true; }
};
}

typedef sw::ClientBase<SwModify> SwClient;
// get information about attribute
virtual bool GetInfo( SwFindNearestNode& ) const { return true; }
};


// SwModify
Expand All @@ -196,13 +181,12 @@ class SW_DLLPUBLIC SwModify: public SwClient
{
friend class sw::ClientIteratorBase;
friend void sw::ClientNotifyAttrChg(SwModify&, const SwAttrSet&, SwAttrSet&, SwAttrSet&);
template<typename E, typename S, sw::IteratorMode> friend class ::SwIterator;
template<typename E, typename S, sw::IteratorMode> friend class SwIterator;
sw::WriterListener* m_pWriterListeners; // the start of the linked list of clients
bool m_bModifyLocked; // don't broadcast changes now

SwModify(SwModify const &) = delete;
SwModify &operator =(const SwModify&) = delete;
void EnsureBroadcasting();
protected:
virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override;
public:
Expand All @@ -215,8 +199,8 @@ public:

virtual ~SwModify() override;

template<typename T> void Add(sw::ClientBase<T>& rDepend);
template<typename T> void Remove(sw::ClientBase<T>& rDepend);
void Add(SwClient& rDepend);
void Remove(SwClient& rDepend);
bool HasWriterListeners() const { return m_pWriterListeners; }
bool HasOnlyOneListener() const { return m_pWriterListeners && m_pWriterListeners->IsLast(); }

Expand All @@ -228,6 +212,7 @@ public:
bool IsModifyLocked() const { return m_bModifyLocked; }
};

template<typename TElementType, typename TSource, sw::IteratorMode eMode> class SwIterator;

namespace sw
{
Expand Down Expand Up @@ -291,7 +276,8 @@ namespace sw
};
class ClientIteratorBase : public sw::Ring< ::sw::ClientIteratorBase >
{
friend class ::SwModify;
friend void SwModify::Remove(SwClient&);
friend void SwModify::Add(SwClient&);
protected:
const SwModify& m_rRoot;
// the current object in an iteration
Expand Down Expand Up @@ -435,77 +421,11 @@ public:
using sw::ClientIteratorBase::IsChanged;
};

template<typename T>
void SwModify::Add(sw::ClientBase<T>& rDepend)
SwClient::SwClient( SwModify* pToRegisterIn )
: m_pRegisteredIn( nullptr )
{
DBG_TESTSOLARMUTEX();
#ifdef DBG_UTIL
EnsureBroadcasting();
assert(dynamic_cast<T*>(this));
#endif

if (rDepend.GetRegisteredIn() == this)
return;

// deregister new client in case it is already registered elsewhere
if( rDepend.GetRegisteredIn() != nullptr )
rDepend.m_pRegisteredIn->Remove(rDepend);

if( !m_pWriterListeners )
{
// first client added
m_pWriterListeners = &rDepend;
m_pWriterListeners->m_pLeft = nullptr;
m_pWriterListeners->m_pRight = nullptr;
}
else
{
// append client
rDepend.m_pRight = m_pWriterListeners->m_pRight;
m_pWriterListeners->m_pRight = &rDepend;
rDepend.m_pLeft = m_pWriterListeners;
if( rDepend.m_pRight )
rDepend.m_pRight->m_pLeft = &rDepend;
}

// connect client to me
rDepend.m_pRegisteredIn = static_cast<T*>(this);
if(pToRegisterIn)
pToRegisterIn->Add(*this);
}

template<typename T>
void SwModify::Remove(sw::ClientBase<T>& rDepend)
{
DBG_TESTSOLARMUTEX();
assert(rDepend.m_pRegisteredIn == this);

// SwClient is my listener
// remove it from my list
::sw::WriterListener* pR = rDepend.m_pRight;
::sw::WriterListener* pL = rDepend.m_pLeft;
if( m_pWriterListeners == &rDepend )
m_pWriterListeners = pL ? pL : pR;

if( pL )
pL->m_pRight = pR;
if( pR )
pR->m_pLeft = pL;

// update ClientIterators
if(sw::ClientIteratorBase::s_pClientIters)
{
for(auto& rIter : sw::ClientIteratorBase::s_pClientIters->GetRingContainer())
{
if (&rIter.m_rRoot == this &&
(rIter.m_pCurrent == &rDepend || rIter.m_pPosition == &rDepend))
{
// if object being removed is the current or next object in an
// iterator, advance this iterator
rIter.m_pPosition = pR;
}
}
}
rDepend.m_pLeft = nullptr;
rDepend.m_pRight = nullptr;
rDepend.m_pRegisteredIn = nullptr;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
18 changes: 7 additions & 11 deletions sw/inc/fmthdft.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,12 @@
#include "calbck.hxx"
#include "frmfmt.hxx"

namespace sw {
typedef ClientBase<::SwFrameFormat> FrameFormatClient;
}

class IntlWrapper;

/** Header, for PageFormats
Client of FrameFormat describing the header. */

class SW_DLLPUBLIC SwFormatHeader final : public SfxPoolItem, public sw::FrameFormatClient
class SW_DLLPUBLIC SwFormatHeader final : public SfxPoolItem, public SwClient
{
bool m_bActive; ///< Only for controlling (creation of content).

Expand All @@ -55,18 +51,18 @@ public:
OUString &rText,
const IntlWrapper& rIntl ) const override;

const SwFrameFormat *GetHeaderFormat() const { return GetRegisteredIn(); }
SwFrameFormat *GetHeaderFormat() { return GetRegisteredIn(); }
const SwFrameFormat *GetHeaderFormat() const { return static_cast<const SwFrameFormat*>(GetRegisteredIn()); }
SwFrameFormat *GetHeaderFormat() { return static_cast<SwFrameFormat*>(GetRegisteredIn()); }

void RegisterToFormat( SwFrameFormat& rFormat );
void RegisterToFormat( SwFormat& rFormat );
bool IsActive() const { return m_bActive; }
void dumpAsXml(xmlTextWriterPtr pWriter) const override;
};

/**Footer, for pageformats
Client of FrameFormat describing the footer */

class SW_DLLPUBLIC SwFormatFooter final : public SfxPoolItem, public sw::FrameFormatClient
class SW_DLLPUBLIC SwFormatFooter final : public SfxPoolItem, public SwClient
{
bool m_bActive; // Only for controlling (creation of content).

Expand All @@ -87,8 +83,8 @@ public:
OUString &rText,
const IntlWrapper& rIntl ) const override;

const SwFrameFormat *GetFooterFormat() const { return GetRegisteredIn(); }
SwFrameFormat *GetFooterFormat() { return GetRegisteredIn(); }
const SwFrameFormat *GetFooterFormat() const { return static_cast<const SwFrameFormat*>(GetRegisteredIn()); }
SwFrameFormat *GetFooterFormat() { return static_cast<SwFrameFormat*>(GetRegisteredIn()); }

void RegisterToFormat( SwFormat& rFormat );
bool IsActive() const { return m_bActive; }
Expand Down
1 change: 0 additions & 1 deletion sw/inc/ring.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#ifndef INCLUDED_SW_INC_RING_HXX
#define INCLUDED_SW_INC_RING_HXX

#include <cassert>
#include <utility>
#include <sal/types.h>
#include <iterator>
Expand Down
Loading

0 comments on commit 9d69c20

Please sign in to comment.