include/svl/itemset.hxx                   |    5 +
 include/svl/poolitem.hxx                  |   94 ++++++++++++++----------------
 include/svl/voiditem.hxx                  |    8 --
 sc/source/ui/cctrl/tbzoomsliderctrl.cxx   |    2 
 sd/source/ui/app/scalectrl.cxx            |    3 
 sd/source/ui/app/tmplctrl.cxx             |    3 
 sfx2/source/control/ctrlitem.cxx          |    2 
 sfx2/source/control/dispatch.cxx          |    4 -
 sfx2/source/control/itemdel.cxx           |    2 
 sfx2/source/control/unoctitm.cxx          |    6 -
 sfx2/source/doc/objxtor.cxx               |    2 
 sfx2/source/statbar/stbitem.cxx           |    2 
 sfx2/source/toolbox/tbxitem.cxx           |    2 
 svl/source/items/itempool.cxx             |   16 ++---
 svl/source/items/itemset.cxx              |   40 +++++++++++-
 svl/source/items/poolitem.cxx             |   11 ++-
 svl/source/items/voiditem.cxx             |   15 ++++
 svx/source/stbctrls/zoomsliderctrl.cxx    |    2 
 sw/source/uibase/docvw/romenu.cxx         |    2 
 sw/source/uibase/utlui/bookctrl.cxx       |    2 
 sw/source/uibase/utlui/viewlayoutctrl.cxx |    2 
 vcl/source/app/svapp.cxx                  |    5 +
 22 files changed, 143 insertions(+), 87 deletions(-)

New commits:
commit 5f7a3126fcad1b490b6e1ef6775b31bac99f3c18
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Sun Sep 10 20:35:26 2023 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Mon Sep 11 12:59:53 2023 +0200

    ITEM: Diverse further changes/cleanups/preparation
    
    Added a counter for SfxItemSet usages, similar to the
    already added one for SfxPoolItems to allow quick info
    about evtl. problems/drawbacks of changes.
    
    Replaced enum SfxItemKind in favour of settable boolean flags
    directly at SfxPoolItem. These are organized as bitfield, do
    not need more space as the enum and allow to be set separately
    and multiple ones at the same time.
    
    Flags for PoolDefault/StaticDefault/DeleteOnIdle use this now
    and are quickly accessible booleans. It is not a problem that
    theoretically the flags for PoolDefault/StaticDefault could now
    both be set - this is internal to SfxItem stuff and not accessible
    from normal code, so can be managed.
    
    Added for debug build a bitfield boolean m_bDeleted
    that will be set in the SfxPoolItem destructor. Of course
    it's usability will depend on the freed space not yet being
    re-used, but will hopefully help in the debugger to detect
    reasons for failure (would have helped at least me before).
    
    Added for replacement of virtual method IsVoidItem() another
    bitfield bool m_bIsVoidItem that is set in the constructors
    of SfxVoidItem. Also had to add some constructors to do that
    which were defaulted before. This is mainly because the base
    class SfxPoolItem does *not* have a copy-constructor that
    copies the members (flags/RefCnt/WhichID) and we should keep
    that 'indirect reset' when Cloning. isVoidItem() is now a simple
    boolean member access - the bitfield does the needed masking.
    This spares one entry in the virtual function table of
    SfxPoolItem which is derived more than 500 times.
    
    Used the results of the experiment at
    https://gerrit.libreoffice.org/c/core/+/156774 to change
    some accesses to IsVoidItem() to use SfxItemState instead.
    This is for preparation of splitting up the two usages of
    SfxVoidItems, see commit text in the experiment.
    If this shows problems in the future those six places documented
    there may have to be changed back to use the new isVoidItem(),
    but should also check the ptr this time to be non-zero.
    
    Removed SFX_ITEMS_SPECIAL that is no more used anywhere.
    
    Change-Id: Ib687ca2362d72a4651c75aee0c67029088f68947
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156805
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index ba14c21b8e6c..6d95ec505c0f 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -33,6 +33,11 @@
 
 class SfxItemPool;
 
+#ifdef DBG_UTIL
+SVL_DLLPUBLIC size_t getAllocatedSfxItemSetCount();
+SVL_DLLPUBLIC size_t getUsedSfxItemSetCount();
+#endif
+
 class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
 {
     friend class SfxItemIter;
diff --git a/include/svl/poolitem.hxx b/include/svl/poolitem.hxx
index 46dd8b0a76f5..ce4d94e782f9 100644
--- a/include/svl/poolitem.hxx
+++ b/include/svl/poolitem.hxx
@@ -35,17 +35,8 @@
 
 class IntlWrapper;
 
-enum class SfxItemKind : sal_Int8
-{
-   NONE,
-   DeleteOnIdle,
-   StaticDefault,
-   PoolDefault
-};
-
 #define SFX_ITEMS_OLD_MAXREF                0xffef
 #define SFX_ITEMS_MAXREF                    0xfffffffe
-#define SFX_ITEMS_SPECIAL                   0xffffffff
 
 #define CONVERT_TWIPS                       0x80    // Uno conversion for 
measurement (for MemberId)
 
@@ -124,15 +115,51 @@ friend class SfxItemSet;
 
     mutable sal_uInt32 m_nRefCount;
     sal_uInt16  m_nWhich;
-    SfxItemKind  m_nKind;
+
+    // bitfield for flags (instead of SfxItemKind)
+    bool        m_bIsVoidItem : 1;
+    bool        m_bDeleteOnIdle : 1;
+    bool        m_bStaticDefault : 1;
+    bool        m_bPoolDefault : 1;
+#ifdef DBG_UTIL
+    // this flag will make debugging item stuff much simpler
+    bool        m_bDeleted : 1;
+#endif
 
 private:
-    inline void              SetRefCount(sal_uInt32 n);
-    inline void              SetKind( SfxItemKind n );
+    inline void SetRefCount(sal_uInt32 n)
+    {
+        m_nRefCount = n;
+        m_bStaticDefault = m_bPoolDefault = false;
+    }
+
+protected:
+    void setVoidItem() { m_bIsVoidItem = true; }
+    void setDeleteOnIdle() { m_bDeleteOnIdle = true; }
+    void setStaticDefault() { m_bStaticDefault = true; }
+    void setPoolDefault() { m_bPoolDefault = true; }
+
 public:
-    inline void              AddRef(sal_uInt32 n = 1) const;
+    inline void AddRef(sal_uInt32 n = 1) const
+    {
+        assert(m_nRefCount <= SFX_ITEMS_MAXREF && "AddRef with non-Pool-Item");
+        assert(n <= SFX_ITEMS_MAXREF - m_nRefCount && "AddRef: refcount 
overflow");
+        m_nRefCount += n;
+    }
+
+    bool isVoidItem() const { return m_bIsVoidItem; }
+    bool isDeleteOnIdle() const { return m_bDeleteOnIdle; }
+    bool isStaticDefault() const { return m_bStaticDefault; }
+    bool isPoolDefault() const { return m_bPoolDefault; }
+
 private:
-    inline sal_uInt32        ReleaseRef(sal_uInt32 n = 1) const;
+    inline sal_uInt32 ReleaseRef(sal_uInt32 n = 1) const
+    {
+        assert(m_nRefCount <= SFX_ITEMS_MAXREF && "ReleaseRef with 
non-Pool-Item");
+        assert(n <= m_nRefCount);
+        m_nRefCount -= n;
+        return m_nRefCount;
+    }
 
 protected:
                              explicit SfxPoolItem( sal_uInt16 nWhich = 0 );
@@ -226,61 +253,28 @@ public:
     }
 
     sal_uInt32               GetRefCount() const { return m_nRefCount; }
-    SfxItemKind       GetKind() const { return m_nKind; }
     virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
     virtual boost::property_tree::ptree dumpAsJSON() const;
 
-    /** Only SfxVoidItem shall and must return true for this.
-
-        This avoids costly calls to dynamic_cast<const SfxVoidItem*>()
-        specifically in SfxItemSet::GetItemState()
-     */
-    virtual bool             IsVoidItem() const;
-
 private:
     SfxPoolItem&             operator=( const SfxPoolItem& ) = delete;
 };
 
-inline void SfxPoolItem::SetRefCount(sal_uInt32 n)
-{
-    m_nRefCount = n;
-    m_nKind = SfxItemKind::NONE;
-}
 
-inline void SfxPoolItem::SetKind( SfxItemKind n )
-{
-    m_nRefCount = SFX_ITEMS_SPECIAL;
-    m_nKind = n;
-}
-
-inline void SfxPoolItem::AddRef(sal_uInt32 n) const
-{
-    assert(m_nRefCount <= SFX_ITEMS_MAXREF && "AddRef with non-Pool-Item");
-    assert(n <= SFX_ITEMS_MAXREF - m_nRefCount && "AddRef: refcount overflow");
-    m_nRefCount += n;
-}
-
-inline sal_uInt32 SfxPoolItem::ReleaseRef(sal_uInt32 n) const
-{
-    assert(m_nRefCount <= SFX_ITEMS_MAXREF && "ReleaseRef with non-Pool-Item");
-    assert(n <= m_nRefCount);
-    m_nRefCount -= n;
-    return m_nRefCount;
-}
 
 inline bool IsPoolDefaultItem(const SfxPoolItem *pItem )
 {
-    return pItem && pItem->GetKind() == SfxItemKind::PoolDefault;
+    return pItem && pItem->isPoolDefault();
 }
 
 inline bool IsStaticDefaultItem(const SfxPoolItem *pItem )
 {
-    return pItem && pItem->GetKind() == SfxItemKind::StaticDefault;
+    return pItem && pItem->isStaticDefault();
 }
 
 inline bool IsDefaultItem( const SfxPoolItem *pItem )
 {
-    return pItem && (pItem->GetKind() == SfxItemKind::StaticDefault || 
pItem->GetKind() == SfxItemKind::PoolDefault);
+    return pItem && (pItem->isPoolDefault() || pItem->isStaticDefault());
 }
 
 inline bool IsPooledItem( const SfxPoolItem *pItem )
diff --git a/include/svl/voiditem.hxx b/include/svl/voiditem.hxx
index b06f28e84b2e..911c691470fb 100644
--- a/include/svl/voiditem.hxx
+++ b/include/svl/voiditem.hxx
@@ -26,11 +26,12 @@ class SVL_DLLPUBLIC SfxVoidItem final : public SfxPoolItem
 {
 public:
     static SfxPoolItem* CreateDefault();
+
     explicit SfxVoidItem(sal_uInt16 nWhich);
+    SfxVoidItem(const SfxVoidItem& rCopy);
+    SfxVoidItem(SfxVoidItem&& rOrig);
     virtual ~SfxVoidItem() override;
 
-    SfxVoidItem(SfxVoidItem const&) = default;
-    SfxVoidItem(SfxVoidItem&&) = default;
     SfxVoidItem& operator=(SfxVoidItem const&) = delete; // due to SfxPoolItem
     SfxVoidItem& operator=(SfxVoidItem&&) = delete; // due to SfxPoolItem
 
@@ -43,9 +44,6 @@ public:
 
     // create a copy of itself
     virtual SfxVoidItem* Clone(SfxItemPool* pPool = nullptr) const override;
-
-    /** Always returns true as this is an SfxVoidItem. */
-    virtual bool IsVoidItem() const override;
 };
 
 #endif
diff --git a/sc/source/ui/cctrl/tbzoomsliderctrl.cxx 
b/sc/source/ui/cctrl/tbzoomsliderctrl.cxx
index 0168eaf3e93a..4ec776de100c 100644
--- a/sc/source/ui/cctrl/tbzoomsliderctrl.cxx
+++ b/sc/source/ui/cctrl/tbzoomsliderctrl.cxx
@@ -59,7 +59,7 @@ void ScZoomSliderControl::StateChangedAtToolBoxControl( 
sal_uInt16 /*nSID*/, Sfx
     ScZoomSliderWnd*        pBox = 
static_cast<ScZoomSliderWnd*>(rTbx.GetItemWindow( nId ));
     OSL_ENSURE( pBox ,"Control not found!" );
 
-    if ( SfxItemState::DEFAULT != eState || pState->IsVoidItem() )
+    if (SfxItemState::DEFAULT != eState || SfxItemState::DISABLED == eState)
     {
         SvxZoomSliderItem aZoomSliderItem( 100 );
         pBox->Disable();
diff --git a/sd/source/ui/app/scalectrl.cxx b/sd/source/ui/app/scalectrl.cxx
index 84667f41cebb..c2d3f034a031 100644
--- a/sd/source/ui/app/scalectrl.cxx
+++ b/sd/source/ui/app/scalectrl.cxx
@@ -47,8 +47,9 @@ SdScaleControl::~SdScaleControl() {}
 void SdScaleControl::StateChangedAtStatusBarControl(sal_uInt16 /*nSID*/, 
SfxItemState eState,
                                                     const SfxPoolItem* pState)
 {
-    if (eState != SfxItemState::DEFAULT || pState->IsVoidItem())
+    if (eState != SfxItemState::DEFAULT || SfxItemState::DISABLED == eState)
         return;
+
     auto pStringItem = dynamic_cast<const SfxStringItem*>(pState);
     if (!pStringItem)
     {
diff --git a/sd/source/ui/app/tmplctrl.cxx b/sd/source/ui/app/tmplctrl.cxx
index c8a8da9e5027..ffc79e923c71 100644
--- a/sd/source/ui/app/tmplctrl.cxx
+++ b/sd/source/ui/app/tmplctrl.cxx
@@ -51,8 +51,9 @@ SdTemplateControl::~SdTemplateControl()
 void SdTemplateControl::StateChangedAtStatusBarControl(
     sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
 {
-    if( eState != SfxItemState::DEFAULT || pState->IsVoidItem() )
+    if (eState != SfxItemState::DEFAULT || SfxItemState::DISABLED == eState)
         GetStatusBar().SetItemText( GetId(), OUString() );
+
     else if ( auto pStringItem = dynamic_cast< const SfxStringItem *>( pState 
) )
     {
         msTemplate = pStringItem->GetValue();
diff --git a/sfx2/source/control/ctrlitem.cxx b/sfx2/source/control/ctrlitem.cxx
index 21618056469a..9a8c6e0203a2 100644
--- a/sfx2/source/control/ctrlitem.cxx
+++ b/sfx2/source/control/ctrlitem.cxx
@@ -293,7 +293,7 @@ SfxItemState SfxControllerItem::GetItemState
                 ? SfxItemState::DISABLED
                 : IsInvalidItem(pState)
                     ? SfxItemState::DONTCARE
-                    : pState->IsVoidItem() && !pState->Which()
+                    : pState->isVoidItem() && !pState->Which()
                         ? SfxItemState::UNKNOWN
                         : SfxItemState::DEFAULT;
 }
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index af57a5e3ab2f..c047f854a810 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -1694,7 +1694,7 @@ bool SfxDispatcher::FillState_(const SfxSlotServer& rSvr, 
SfxItemSet& rState,
                   pItem;
                   pItem = aIter.NextItem() )
             {
-                if ( !IsInvalidItem(pItem) && !pItem->IsVoidItem() )
+                if ( !IsInvalidItem(pItem) && !pItem->isVoidItem() )
                 {
                     sal_uInt16 nSlotId = 
rState.GetPool()->GetSlotId(pItem->Which());
                     SAL_INFO_IF(
@@ -1995,7 +1995,7 @@ SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, 
css::uno::Any& rAny )
         else
         {
             css::uno::Any aState;
-            if ( !pItem->IsVoidItem() )
+            if ( !pItem->isVoidItem() )
             {
                 sal_uInt16 nSubId( 0 );
                 SfxItemPool& rPool = pShell->GetPool();
diff --git a/sfx2/source/control/itemdel.cxx b/sfx2/source/control/itemdel.cxx
index c96a9d0f4ba3..ce6f4e1b9303 100644
--- a/sfx2/source/control/itemdel.cxx
+++ b/sfx2/source/control/itemdel.cxx
@@ -31,7 +31,7 @@ class SfxItemDisruptor_Impl
 public:
     static void DeleteItemOnIdle(std::unique_ptr<SfxPoolItem> pItem)
     {
-        pItem->SetKind(SfxItemKind::DeleteOnIdle);
+        pItem->setDeleteOnIdle();
         Application::PostUserEvent(LINK(nullptr, SfxItemDisruptor_Impl, 
Delete), pItem.release());
         // coverity[leaked_storage] - pDisruptor takes care of its own 
destruction at idle time
     }
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
index 9b75d0a51118..89e94caff794 100644
--- a/sfx2/source/control/unoctitm.cxx
+++ b/sfx2/source/control/unoctitm.cxx
@@ -670,7 +670,7 @@ void SfxDispatchController_Impl::dispatch( const 
css::util::URL& aURL,
                         {
                             if (const SfxBoolItem* pBoolItem = 
dynamic_cast<const SfxBoolItem*>(pItem))
                                 bSuccess = pBoolItem->GetValue();
-                            else if ( !pItem->IsVoidItem() )
+                            else if ( !pItem->isVoidItem() )
                                 bSuccess = true;  // all other types are true
                         }
                         // else bSuccess = false look to line 664 it is false
@@ -733,7 +733,7 @@ void SfxDispatchController_Impl::dispatch( const 
css::util::URL& aURL,
         aEvent.State = css::frame::DispatchResultState::FAILURE;
 
     aEvent.Source = static_cast<css::frame::XDispatch*>(pDispatch);
-    if ( bSuccess && pItem && !pItem->IsVoidItem() )
+    if ( bSuccess && pItem && !pItem->isVoidItem() )
     {
         sal_uInt16 nSubId( 0 );
         if ( eMapUnit == MapUnit::MapTwip )
@@ -834,7 +834,7 @@ void SfxDispatchController_Impl::StateChanged( sal_uInt16 
nSID, SfxItemState eSt
         return;
 
     css::uno::Any aState;
-    if ( ( eState >= SfxItemState::DEFAULT ) && pState && !IsInvalidItem( 
pState ) && !pState->IsVoidItem() )
+    if ( ( eState >= SfxItemState::DEFAULT ) && pState && !IsInvalidItem( 
pState ) && !pState->isVoidItem() )
     {
         // Retrieve metric from pool to have correct sub ID when calling 
QueryValue
         sal_uInt16     nSubId( 0 );
diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx
index 917935d907d1..8c3029edd128 100644
--- a/sfx2/source/doc/objxtor.cxx
+++ b/sfx2/source/doc/objxtor.cxx
@@ -587,7 +587,7 @@ bool SfxObjectShell::PrepareClose
                 pPoolItem = pFrame->GetBindings().ExecuteSynchron( 
SID_SAVEDOC, ppArgs );
             }
 
-            if ( !pPoolItem || pPoolItem->IsVoidItem() )
+            if ( !pPoolItem || pPoolItem->isVoidItem() )
                 return false;
             if ( auto pBoolItem = dynamic_cast< const SfxBoolItem *>( 
pPoolItem ) )
                 if ( !pBoolItem->GetValue() )
diff --git a/sfx2/source/statbar/stbitem.cxx b/sfx2/source/statbar/stbitem.cxx
index 2387557d6ba9..6e9ee1bcaa95 100644
--- a/sfx2/source/statbar/stbitem.cxx
+++ b/sfx2/source/statbar/stbitem.cxx
@@ -376,7 +376,7 @@ void SfxStatusBarControl::StateChangedAtStatusBarControl
         pBar->SetItemText( nSID, pStr->GetValue() );
     else
     {
-        DBG_ASSERT( eState != SfxItemState::DEFAULT || pState->IsVoidItem(),
+        DBG_ASSERT( eState != SfxItemState::DEFAULT || pState->isVoidItem(),
                     "wrong SfxPoolItem subclass in SfxStatusBarControl" );
         pBar->SetItemText( nSID, OUString() );
     }
diff --git a/sfx2/source/toolbox/tbxitem.cxx b/sfx2/source/toolbox/tbxitem.cxx
index f355806aaa00..bf01be5e1921 100644
--- a/sfx2/source/toolbox/tbxitem.cxx
+++ b/sfx2/source/toolbox/tbxitem.cxx
@@ -234,7 +234,7 @@ SfxItemState SfxToolBoxControl::GetItemState(
                 ? SfxItemState::DISABLED
                 : IsInvalidItem(pState)
                     ? SfxItemState::DONTCARE
-                    : pState->IsVoidItem() && !pState->Which()
+                    : pState->isVoidItem() && !pState->Which()
                         ? SfxItemState::UNKNOWN
                         : SfxItemState::DEFAULT;
 }
diff --git a/svl/source/items/itempool.cxx b/svl/source/items/itempool.cxx
index 3cef59683ad7..525adf309fb8 100644
--- a/svl/source/items/itempool.cxx
+++ b/svl/source/items/itempool.cxx
@@ -281,7 +281,7 @@ SfxItemPool::SfxItemPool
         for ( sal_uInt16 n = 0; n <= pImpl->mnEnd - pImpl->mnStart; ++n )
         {
             (*ppDefaults)[n] = 
(*rPool.pImpl->mpStaticDefaults)[n]->Clone(this);
-            (*ppDefaults)[n]->SetKind(SfxItemKind::StaticDefault);
+            (*ppDefaults)[n]->setStaticDefault();
         }
 
         SetDefaults( ppDefaults );
@@ -294,7 +294,7 @@ SfxItemPool::SfxItemPool
         if (rPool.pImpl->maPoolDefaults[n])
         {
             pImpl->maPoolDefaults[n] = 
rPool.pImpl->maPoolDefaults[n]->Clone(this); //resets kind
-            pImpl->maPoolDefaults[n]->SetKind(SfxItemKind::PoolDefault);
+            pImpl->maPoolDefaults[n]->setPoolDefault();
         }
 
     // Repair linkage
@@ -318,7 +318,7 @@ void SfxItemPool::SetDefaults( std::vector<SfxPoolItem*>* 
pDefaults )
         {
             assert(  ((*pImpl->mpStaticDefaults)[n]->Which() == n + 
pImpl->mnStart)
                         && "items ids in pool-ranges and in static-defaults do 
not match" );
-            (*pImpl->mpStaticDefaults)[n]->SetKind(SfxItemKind::StaticDefault);
+            (*pImpl->mpStaticDefaults)[n]->setStaticDefault();
             DBG_ASSERT( pImpl->maPoolItemArrays[n].empty(), "defaults with 
setitems with items?!" );
         }
     }
@@ -589,7 +589,7 @@ void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem 
&rItem)
         auto& rOldDefault =
             pImpl->maPoolDefaults[GetIndex_Impl(rItem.Which())];
         SfxPoolItem *pNewDefault = rItem.Clone(this);
-        pNewDefault->SetKind(SfxItemKind::PoolDefault);
+        pNewDefault->setPoolDefault();
         if (rOldDefault)
         {
             rOldDefault->SetRefCount(0);
@@ -650,7 +650,7 @@ const SfxPoolItem& SfxItemPool::PutImpl( const SfxPoolItem& 
rItem, sal_uInt16 nW
     if (bSID)
     {
         assert((rItem.Which() != nWhich ||
-            !IsDefaultItem(&rItem) || rItem.GetKind() == 
SfxItemKind::DeleteOnIdle)
+            !IsDefaultItem(&rItem) || rItem.isDeleteOnIdle())
                 && "a non Pool Item is Default?!");
         SfxPoolItem *pPoolItem = rItem.Clone(pImpl->mpMaster);
         pPoolItem->SetWhich(nWhich);
@@ -776,14 +776,16 @@ void SfxItemPool::Remove( const SfxPoolItem& rItem )
         return;
     }
 
-    assert(rItem.GetRefCount() && "RefCount == 0, Remove impossible");
-
     const sal_uInt16 nIndex = GetIndex_Impl(nWhich);
     // Static Defaults are just there
     if ( IsStaticDefaultItem(&rItem) &&
          &rItem == (*pImpl->mpStaticDefaults)[nIndex])
         return;
 
+    // moved below StaticDefaultItem detection - StaticDefaultItems
+    // do not need a RefCnt of SFX_ITEMS_SPECIAL (0xffffffff) anymore
+    assert(rItem.GetRefCount() && "RefCount == 0, Remove impossible");
+
     // Find Item in own Pool
     SfxPoolItemArray_Impl& rItemArr = pImpl->maPoolItemArrays[nIndex];
 
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index 7be410c2bd78..4f71a8aafb5e 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -36,6 +36,13 @@
 
 #include <items_helper.hxx>
 
+#ifdef DBG_UTIL
+static size_t nAllocatedSfxItemSetCount(0);
+static size_t nUsedSfxItemSetCount(0);
+size_t getAllocatedSfxItemSetCount() { return nAllocatedSfxItemSetCount; }
+size_t getUsedSfxItemSetCount() { return nUsedSfxItemSetCount; }
+#endif
+
 /**
  * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
  * the supplied SfxItemPool.
@@ -55,6 +62,10 @@ SfxItemSet::SfxItemSet(SfxItemPool& rPool)
     , m_pWhichRanges(rPool.GetFrozenIdRanges())
     , m_aCallback()
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount++;
+    nUsedSfxItemSetCount++;
+#endif
     assert(svl::detail::validRanges2(m_pWhichRanges));
 }
 
@@ -68,6 +79,10 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, 
SfxAllItemSetFlag )
     , m_pWhichRanges()
     , m_aCallback()
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount++;
+    nUsedSfxItemSetCount++;
+#endif
 }
 
 /** special constructor for SfxItemSetFixed */
@@ -81,6 +96,10 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, 
WhichRangesContainer&& ranges, SfxPo
     , m_pWhichRanges(std::move(ranges))
     , m_aCallback()
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount++;
+    nUsedSfxItemSetCount++;
+#endif
     assert(ppItems);
     assert(m_pWhichRanges.size() > 0);
     assert(svl::detail::validRanges2(m_pWhichRanges));
@@ -96,6 +115,10 @@ SfxItemSet::SfxItemSet(SfxItemPool& pool, 
WhichRangesContainer wids)
     , m_pWhichRanges(std::move(wids))
     , m_aCallback()
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount++;
+    nUsedSfxItemSetCount++;
+#endif
     assert(svl::detail::CountRanges(m_pWhichRanges) != 0);
     assert(svl::detail::validRanges2(m_pWhichRanges));
 }
@@ -186,6 +209,10 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rASet )
     , m_pWhichRanges( rASet.m_pWhichRanges )
     , m_aCallback(rASet.m_aCallback)
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount++;
+    nUsedSfxItemSetCount++;
+#endif
     if (rASet.GetRanges().empty())
     {
         return;
@@ -217,6 +244,10 @@ SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept
     , m_pWhichRanges( std::move(rASet.m_pWhichRanges) )
     , m_aCallback(rASet.m_aCallback)
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount++;
+    nUsedSfxItemSetCount++;
+#endif
     if (rASet.m_bItemsFixed)
     {
         // have to make a copy
@@ -242,6 +273,9 @@ SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept
 
 SfxItemSet::~SfxItemSet()
 {
+#ifdef DBG_UTIL
+    nAllocatedSfxItemSetCount--;
+#endif
     // cleanup items. No std::fill needed, we are done with this ItemSet.
     // the callback is not set in destructor, so no worries about that
     ClearAllItemsImpl();
@@ -289,7 +323,7 @@ sal_uInt16 SfxItemSet::ClearSingleItem_ForOffset( 
sal_uInt16 nOffset )
 {
     assert(nOffset < TotalCount());
     const_iterator aEntry(begin() + nOffset);
-    assert(nullptr == *aEntry || IsInvalidItem(*aEntry) || 
(*aEntry)->IsVoidItem() || 0 != (*aEntry)->Which());
+    assert(nullptr == *aEntry || IsInvalidItem(*aEntry) || 
(*aEntry)->isVoidItem() || 0 != (*aEntry)->Which());
 
     if (nullptr == *aEntry)
         // no entry, done
@@ -399,7 +433,7 @@ SfxItemState SfxItemSet::GetItemState_ForOffset( sal_uInt16 
nOffset, const SfxPo
         // Different ones are present
         return SfxItemState::DONTCARE;
 
-    if (pCandidate->IsVoidItem())
+    if (pCandidate->isVoidItem())
         // Item is Disabled
         return SfxItemState::DISABLED;
 
@@ -864,7 +898,7 @@ const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool 
bSrchInParent) const
             }
 #ifdef DBG_UTIL
             const SfxPoolItem *pItem = *aFoundOne;
-            if ( pItem->IsVoidItem() || !pItem->Which() )
+            if ( pItem->isVoidItem() || !pItem->Which() )
                 SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item");
 #endif
             return **aFoundOne;
diff --git a/svl/source/items/poolitem.cxx b/svl/source/items/poolitem.cxx
index 9a45e8803448..a4f02d19b4e3 100644
--- a/svl/source/items/poolitem.cxx
+++ b/svl/source/items/poolitem.cxx
@@ -471,7 +471,13 @@ size_t getUsedSfxPoolItemCount() { return 
nUsedSfxPoolItemCount; }
 SfxPoolItem::SfxPoolItem(sal_uInt16 const nWhich)
     : m_nRefCount(0)
     , m_nWhich(nWhich)
-    , m_nKind(SfxItemKind::NONE)
+    , m_bIsVoidItem(false)
+    , m_bDeleteOnIdle(false)
+    , m_bStaticDefault(false)
+    , m_bPoolDefault(false)
+#ifdef DBG_UTIL
+    , m_bDeleted(false)
+#endif
 {
 #ifdef DBG_UTIL
     nAllocatedSfxPoolItemCount++;
@@ -484,6 +490,7 @@ SfxPoolItem::~SfxPoolItem()
 {
 #ifdef DBG_UTIL
     nAllocatedSfxPoolItemCount--;
+    m_bDeleted = true;
 #endif
     assert((m_nRefCount == 0 || m_nRefCount > SFX_ITEMS_MAXREF) && "destroying 
item in use");
 }
@@ -574,8 +581,6 @@ std::unique_ptr<SfxPoolItem> 
SfxPoolItem::CloneSetWhich(sal_uInt16 nNewWhich) co
     return pItem;
 }
 
-bool SfxPoolItem::IsVoidItem() const { return false; }
-
 void SfxPoolItem::ScaleMetrics(tools::Long /*lMult*/, tools::Long /*lDiv*/) {}
 
 bool SfxPoolItem::HasMetrics() const { return false; }
diff --git a/svl/source/items/voiditem.cxx b/svl/source/items/voiditem.cxx
index 3afa64de5332..6977c28553d3 100644
--- a/svl/source/items/voiditem.cxx
+++ b/svl/source/items/voiditem.cxx
@@ -25,6 +25,19 @@ SfxPoolItem* SfxVoidItem::CreateDefault() { return new 
SfxVoidItem(0); }
 SfxVoidItem::SfxVoidItem(sal_uInt16 which)
     : SfxPoolItem(which)
 {
+    setVoidItem();
+}
+
+SfxVoidItem::SfxVoidItem(const SfxVoidItem& rCopy)
+    : SfxPoolItem(rCopy.Which())
+{
+    setVoidItem();
+}
+
+SfxVoidItem::SfxVoidItem(SfxVoidItem&& rOrig)
+    : SfxPoolItem(rOrig)
+{
+    setVoidItem();
 }
 
 bool SfxVoidItem::operator==(const SfxPoolItem& rCmp) const
@@ -52,8 +65,6 @@ void SfxVoidItem::dumpAsXml(xmlTextWriterPtr pWriter) const
 
 SfxVoidItem* SfxVoidItem::Clone(SfxItemPool*) const { return new 
SfxVoidItem(*this); }
 
-bool SfxVoidItem::IsVoidItem() const { return true; }
-
 SfxVoidItem::~SfxVoidItem() {}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/stbctrls/zoomsliderctrl.cxx 
b/svx/source/stbctrls/zoomsliderctrl.cxx
index 215c0556fc87..475f1da245bf 100644
--- a/svx/source/stbctrls/zoomsliderctrl.cxx
+++ b/svx/source/stbctrls/zoomsliderctrl.cxx
@@ -162,7 +162,7 @@ SvxZoomSliderControl::~SvxZoomSliderControl()
 
 void SvxZoomSliderControl::StateChangedAtStatusBarControl( sal_uInt16 
/*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
 {
-    if ( (SfxItemState::DEFAULT != eState) || pState->IsVoidItem() )
+    if (SfxItemState::DEFAULT != eState || SfxItemState::DISABLED == eState)
     {
         GetStatusBar().SetItemText( GetId(), "" );
         mxImpl->mbValuesSet   = false;
diff --git a/sw/source/uibase/docvw/romenu.cxx 
b/sw/source/uibase/docvw/romenu.cxx
index 02b4b1ebe7d9..05d352f181c3 100644
--- a/sw/source/uibase/docvw/romenu.cxx
+++ b/sw/source/uibase/docvw/romenu.cxx
@@ -60,7 +60,7 @@ void SwReadOnlyPopup::Check( sal_uInt16 nMID, sal_uInt16 
nSID, SfxDispatcher con
         m_xMenu->EnableItem(nMID);
         if (_pItem)
         {
-            m_xMenu->CheckItem(nMID, !_pItem->IsVoidItem() &&
+            m_xMenu->CheckItem(nMID, !_pItem->isVoidItem() &&
                             dynamic_cast< const SfxBoolItem *>( _pItem.get() ) 
!=  nullptr &&
                             
static_cast<SfxBoolItem*>(_pItem.get())->GetValue());
             //remove full screen entry when not in full screen mode
diff --git a/sw/source/uibase/utlui/bookctrl.cxx 
b/sw/source/uibase/utlui/bookctrl.cxx
index f7460b15d3e7..e79821022abc 100644
--- a/sw/source/uibase/utlui/bookctrl.cxx
+++ b/sw/source/uibase/utlui/bookctrl.cxx
@@ -48,7 +48,7 @@ SwBookmarkControl::~SwBookmarkControl()
 void SwBookmarkControl::StateChangedAtStatusBarControl(
     sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
 {
-    if( eState != SfxItemState::DEFAULT || pState->IsVoidItem() )
+    if (eState != SfxItemState::DEFAULT || SfxItemState::DISABLED == eState)
     {
         GetStatusBar().SetItemText(GetId(), OUString());
         GetStatusBar().SetQuickHelpText(GetId(), OUString());
diff --git a/sw/source/uibase/utlui/viewlayoutctrl.cxx 
b/sw/source/uibase/utlui/viewlayoutctrl.cxx
index 453dcd91a2eb..89dcc30175c2 100644
--- a/sw/source/uibase/utlui/viewlayoutctrl.cxx
+++ b/sw/source/uibase/utlui/viewlayoutctrl.cxx
@@ -63,7 +63,7 @@ SwViewLayoutControl::~SwViewLayoutControl()
 
 void SwViewLayoutControl::StateChangedAtStatusBarControl( sal_uInt16 /*nSID*/, 
SfxItemState eState, const SfxPoolItem* pState )
 {
-    if ( SfxItemState::DEFAULT != eState || pState->IsVoidItem() )
+    if (SfxItemState::DEFAULT != eState || SfxItemState::DISABLED == eState)
     {
         GetStatusBar().SetItemText( GetId(), OUString() );
         mpImpl->mnState = 4; //tdf#148441 switch off, if disabled
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 020a1315ea89..19b8cd52b7e7 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -77,6 +77,7 @@
 
 #ifdef DBG_UTIL
 #include <svl/poolitem.hxx>
+#include <svl/itemset.hxx>
 #endif
 
 #include <cassert>
@@ -193,6 +194,10 @@ Application::~Application()
     // would show in dramatically higher numbers then immediately
     SAL_WARN("vcl", "ITEM: " << getAllocatedSfxPoolItemCount() << " 
SfxPoolItems still allocated at shutdown");
     SAL_WARN("vcl", "ITEM: " << getUsedSfxPoolItemCount() << " SfxPoolItems 
were incarnated during office usage");
+
+    // Same mechanism for SfxItemSet(s)
+    SAL_WARN("vcl", "ITEM: " << getAllocatedSfxItemSetCount() << " SfxItemSets 
still allocated at shutdown");
+    SAL_WARN("vcl", "ITEM: " << getUsedSfxItemSetCount() << " SfxItemSets were 
incarnated during office usage");
 #endif
 }
 

Reply via email to