new loplugin:inlinefields

look for fields which can be declared inline in the parent class.

start with some likely candidates in svx

Change-Id: I56cdca273272b72bb728ed2e3f5e1e976f8c7c32
Reviewed-on: https://gerrit.libreoffice.org/36262
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/compilerplugins/clang/inlinefields.cxx b/compilerplugins/clang/inlinefields.cxx
new file mode 100644
index 0000000..e663c11
--- /dev/null
+++ b/compilerplugins/clang/inlinefields.cxx
@@ -0,0 +1,247 @@
/* -*- 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/.
 */

#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <set>
#include "plugin.hxx"
#include "compat.hxx"

/**
if a field is
- a pointer
- only assigned to in the constructor via a new expression
- unconditionally deleted in the destructor
then it can probably just be allocated inline in the parent object

TODO check for cases where the pointer is passed by non-const reference

Be warned that it produces around 5G of log file.

The process goes something like this:
  $ make check
  $ make FORCE_COMPILE_ALL=1 COMPILER_PLUGIN_TOOL='inlinefields' check
  $ ./compilerplugins/clang/inlinefields.py

and then
  $ for dir in *; do make FORCE_COMPILE_ALL=1 UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='inlinefieldsremove' $dir; done
to auto-remove the method declarations

Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around
to get it to work :-)

*/

namespace {

struct MyFieldInfo
{
    std::string parentClass;
    std::string fieldName;
    std::string sourceLocation;
};
bool operator < (const MyFieldInfo &lhs, const MyFieldInfo &rhs)
{
    return std::tie(lhs.parentClass, lhs.fieldName)
         < std::tie(rhs.parentClass, rhs.fieldName);
}


// try to limit the voluminous output a little
static std::set<MyFieldInfo> excludedSet;
static std::set<MyFieldInfo> definitionSet;
static std::set<MyFieldInfo> deletedInDestructorSet;
static std::set<MyFieldInfo> newedInConstructorSet;

class InlineFields:
    public RecursiveASTVisitor<InlineFields>, public loplugin::Plugin
{
public:
    explicit InlineFields(InstantiationData const & data): Plugin(data) {}

    virtual void run() override
    {
        TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());

        // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes
        // writing to the same logfile
        std::string output;
        for (const MyFieldInfo & s : definitionSet)
            output += "definition:\t" + s.parentClass + "\t" + s.fieldName + "\t" + s.sourceLocation + "\n";
        for (const MyFieldInfo & s : excludedSet)
            output += "excluded:\t" + s.parentClass + "\t" + s.fieldName + "\n";
        for (const MyFieldInfo & s : deletedInDestructorSet)
            output += "deletedInDestructor:\t" + s.parentClass + "\t" + s.fieldName + "\n";
        for (const MyFieldInfo & s : newedInConstructorSet)
            output += "newedInConstructor:\t" + s.parentClass + "\t" + s.fieldName + "\n";
        ofstream myfile;
        myfile.open( SRCDIR "/loplugin.inlinefields.log", ios::app | ios::out);
        myfile << output;
        myfile.close();
    }

    bool shouldVisitTemplateInstantiations () const { return true; }
    bool shouldVisitImplicitCode() const { return true; }

    bool VisitFieldDecl( const FieldDecl* );
    bool VisitCXXConstructorDecl( const CXXConstructorDecl* );
    bool VisitCXXDeleteExpr( const CXXDeleteExpr* );
    bool VisitBinAssign( const BinaryOperator* );
private:
    MyFieldInfo niceName(const FieldDecl*);
    void checkTouched(const FieldDecl* fieldDecl, const Expr* memberExpr);
};

MyFieldInfo InlineFields::niceName(const FieldDecl* fieldDecl)
{
    MyFieldInfo aInfo;

    const RecordDecl* recordDecl = fieldDecl->getParent();

    if (const CXXRecordDecl* cxxRecordDecl = dyn_cast<CXXRecordDecl>(recordDecl))
    {
        if (cxxRecordDecl->getTemplateInstantiationPattern())
            cxxRecordDecl = cxxRecordDecl->getTemplateInstantiationPattern();
        aInfo.parentClass = cxxRecordDecl->getQualifiedNameAsString();
    }
    else
        aInfo.parentClass = recordDecl->getQualifiedNameAsString();

    aInfo.fieldName = fieldDecl->getNameAsString();

    SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( fieldDecl->getLocation() );
    StringRef name = compiler.getSourceManager().getFilename(expansionLoc);
    aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc));
    normalizeDotDotInFilePath(aInfo.sourceLocation);

    return aInfo;
}

bool InlineFields::VisitFieldDecl( const FieldDecl* fieldDecl )
{
    fieldDecl = fieldDecl->getCanonicalDecl();
    if (ignoreLocation( fieldDecl )) {
        return true;
    }
    // ignore stuff that forms part of the stable URE interface
    if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) {
        return true;
    }
    QualType type = fieldDecl->getType();
    if (!type->isPointerType())
        return true;
    definitionSet.insert(niceName(fieldDecl));
    return true;
}

bool InlineFields::VisitCXXConstructorDecl( const CXXConstructorDecl* decl )
{
    if( ignoreLocation( decl ) )
        return true;
    if (decl->isCopyOrMoveConstructor())
        return true;
    for(auto it = decl->init_begin(); it != decl->init_end(); ++it)
    {
        const CXXCtorInitializer* init = *it;
        const FieldDecl* fieldDecl = init->getMember();
        if( !fieldDecl || !fieldDecl->getType()->isPointerType() )
            continue;
        auto e = init->getInit();
        if (auto parentListExpr = dyn_cast<ParenListExpr>(e))
            e = parentListExpr->getExpr(0);
        e = e->IgnoreParenImpCasts();
        if( isa<CXXNewExpr>(e) )
            newedInConstructorSet.insert(niceName(fieldDecl));
        else if( isa<CXXNullPtrLiteralExpr>(e) || isa<GNUNullExpr>(e))
            ; // ignore
        else
            excludedSet.insert(niceName(fieldDecl));
    }
    return true;
}

static bool isSameParent(const CXXMethodDecl* cxxMethodDecl, const FieldDecl* fieldDecl)
{
    return cxxMethodDecl->getParent() == dyn_cast<CXXRecordDecl>(fieldDecl->getParent());
}

bool InlineFields::VisitBinAssign(const BinaryOperator * binaryOp)
{
    if( ignoreLocation( binaryOp ) )
        return true;
    auto memberExpr = dyn_cast<MemberExpr>(binaryOp->getLHS());
    if (!memberExpr)
        return true;
    auto fieldDecl = dyn_cast<FieldDecl>(memberExpr->getMemberDecl());
    if (!fieldDecl || !fieldDecl->getType()->isPointerType()) {
        return true;
    }
    const FunctionDecl* parentFunction = parentFunctionDecl(binaryOp);
    if (!parentFunction) {
        return true;
    }
    // if the field is being assigned from outside it's own constructor or destructor, exclude
    auto constructorDecl = dyn_cast<CXXConstructorDecl>(parentFunction);
    if (constructorDecl && isSameParent(constructorDecl, fieldDecl)) {
        if( isa<CXXNewExpr>(binaryOp->getRHS()) )
            newedInConstructorSet.insert(niceName(fieldDecl));
        else {
            excludedSet.insert(niceName(fieldDecl));
            std::cout << "assign in constructor:" << std::endl;
            binaryOp->getRHS()->dump();
        }
        return true;
    }
    auto destructorDecl = dyn_cast<CXXDestructorDecl>(parentFunction);
    if (destructorDecl && isSameParent(destructorDecl, fieldDecl)) {
        auto e = binaryOp->getRHS()->IgnoreParenImpCasts();
        if( !isa<CXXNullPtrLiteralExpr>(e) && !isa<GNUNullExpr>(e)) {
            excludedSet.insert(niceName(fieldDecl));
            std::cout << "assign in destructor:" << std::endl;
            e->dump();
        }
        return true;
    }
    excludedSet.insert(niceName(fieldDecl));
    return true;
}

bool InlineFields::VisitCXXDeleteExpr(const CXXDeleteExpr * deleteExpr)
{
    if( ignoreLocation( deleteExpr ) )
        return true;
    auto memberExpr = dyn_cast<MemberExpr>(deleteExpr->getArgument()->IgnoreParenImpCasts());
    if (!memberExpr)
        return true;
    auto fieldDecl = dyn_cast<FieldDecl>(memberExpr->getMemberDecl());
    if (!fieldDecl || !fieldDecl->getType()->isPointerType()) {
        return true;
    }
    // TODO for some reason, this part is not working properly, it doesn't find the parent
    // function for delete statements properly
    const FunctionDecl* parentFunction = parentFunctionDecl(deleteExpr);
    if (!parentFunction) {
        return true;
    }
    auto destructorDecl = dyn_cast<CXXDestructorDecl>(parentFunction);
    if (destructorDecl && isSameParent(destructorDecl, fieldDecl)) {
        deletedInDestructorSet.insert(niceName(fieldDecl));
        return true;
    }
    excludedSet.insert(niceName(fieldDecl));
    return true;
}

loplugin::Plugin::Registration< InlineFields > X("inlinefields", false);

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/inlinefields.py b/compilerplugins/clang/inlinefields.py
new file mode 100755
index 0000000..2605fd7
--- /dev/null
+++ b/compilerplugins/clang/inlinefields.py
@@ -0,0 +1,81 @@
#!/usr/bin/python

import sys
import re
import io

definitionToSourceLocationMap = dict() # dict of tuple(parentClass, fieldName) to sourceLocation
definitionSet = set()
excludedSet = set()
deletedInDestructorSet = set()
newedInConstructorSet = set();

# clang does not always use exactly the same numbers in the type-parameter vars it generates
# so I need to substitute them to ensure we can match correctly.
normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+")
def normalizeTypeParams( line ):
    return normalizeTypeParamsRegex.sub("type-parameter-?-?", line)

# reading as binary (since we known it is pure ascii) is much faster than reading as unicode
with io.open("loplugin.inlinefields.log", "rb", buffering=1024*1024) as txt:
    for line in txt:
        tokens = line.strip().split("\t")
        if tokens[0] == "definition:":
            parentClass = normalizeTypeParams(tokens[1])
            fieldName = normalizeTypeParams(tokens[2])
            sourceLocation = tokens[3]
            fieldInfo = (parentClass, fieldName)
            definitionSet.add(fieldInfo)
            definitionToSourceLocationMap[fieldInfo] = sourceLocation
        elif tokens[0] == "excluded:":
            parentClass = normalizeTypeParams(tokens[1])
            fieldName = normalizeTypeParams(tokens[2])
            fieldInfo = (parentClass, fieldName)
            excludedSet.add(fieldInfo)
        elif tokens[0] == "deletedInDestructor:":
            parentClass = normalizeTypeParams(tokens[1])
            fieldName = normalizeTypeParams(tokens[2])
            fieldInfo = (parentClass, fieldName)
            deletedInDestructorSet.add(fieldInfo)
        elif tokens[0] == "newedInConstructor:":
            parentClass = normalizeTypeParams(tokens[1])
            fieldName = normalizeTypeParams(tokens[2])
            fieldInfo = (parentClass, fieldName)
            newedInConstructorSet.add(fieldInfo)
        else:
            print( "unknown line: " + line)

# Invert the definitionToSourceLocationMap
# If we see more than one method at the same sourceLocation, it's being autogenerated as part of a template
# and we should just ignore it
sourceLocationToDefinitionMap = {}
for k, v in definitionToSourceLocationMap.iteritems():
    sourceLocationToDefinitionMap[v] = sourceLocationToDefinitionMap.get(v, [])
    sourceLocationToDefinitionMap[v].append(k)
for k, definitions in sourceLocationToDefinitionMap.iteritems():
    if len(definitions) > 1:
        for d in definitions:
            definitionSet.remove(d)

tmp1list = list()
for d in definitionSet:
# TODO see comment in InlineFields::VisitCXXDeleteExpr
#    if d in excludedSet or d not in deletedInDestructorSet or d not in newedInConstructorSet:
    if d in excludedSet or d not in newedInConstructorSet:
        continue
    srcLoc = definitionToSourceLocationMap[d];
    tmp1list.append((d[0] + " " + d[1], srcLoc))

# sort results by filename:lineno
def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
    return [int(text) if text.isdigit() else text.lower()
            for text in re.split(_nsre, s)]
tmp1list.sort(key=lambda v: natural_sort_key(v[1]))

# print out the results
with open("loplugin.inlinefields.report", "wt") as f:
    for v in tmp1list:
        f.write(v[1] + "\n")
        f.write("    " + v[0] + "\n")


diff --git a/include/svx/nbdtmg.hxx b/include/svx/nbdtmg.hxx
index 52285b1..aeb4ae6 100644
--- a/include/svx/nbdtmg.hxx
+++ b/include/svx/nbdtmg.hxx
@@ -180,8 +180,8 @@ class SVX_DLLPUBLIC NumberingTypeMgr: public NBOTypeMgrBase
    private:
        NumberingTypeMgr(const NumberingTypeMgr&) = delete;
    public:
        NumberSettingsArr_Impl*     pNumberSettingsArr;
        NumberSettingsArr_Impl*     pDefaultNumberSettingsArr;
        NumberSettingsArr_Impl      maNumberSettingsArr;
        NumberSettingsArr_Impl      maDefaultNumberSettingsArr;
    public:
        NumberingTypeMgr();
        virtual ~NumberingTypeMgr() override;
diff --git a/svx/source/accessibility/svxpixelctlaccessiblecontext.cxx b/svx/source/accessibility/svxpixelctlaccessiblecontext.cxx
index c93a675..31f509a 100644
--- a/svx/source/accessibility/svxpixelctlaccessiblecontext.cxx
+++ b/svx/source/accessibility/svxpixelctlaccessiblecontext.cxx
@@ -530,7 +530,7 @@ SvxPixelCtlAccessibleChild::SvxPixelCtlAccessibleChild(
    mrParentWindow( rWindow ),
    mxParent(rxParent),
    m_bPixelColorOrBG(bPixelColorOrBG),
    mpBoundingBox( new tools::Rectangle( rBoundingBox ) ),
    maBoundingBox( rBoundingBox ),
    mnIndexInParent( nIndexInParent ),
    mnClientId( 0 )
{
@@ -771,8 +771,6 @@ void SAL_CALL SvxPixelCtlAccessibleChild::disposing()
        }

        mxParent.clear();

        delete mpBoundingBox;
    }
}

@@ -794,10 +792,10 @@ tools::Rectangle SvxPixelCtlAccessibleChild::GetBoundingBoxOnScreen()

tools::Rectangle const & SvxPixelCtlAccessibleChild::GetBoundingBox()
{
    // no guard necessary, because no one changes mpBoundingBox after creating it
    // no guard necessary, because no one changes maBoundingBox after creating it
    ThrowExceptionIfNotAlive();

    return *mpBoundingBox;
    return maBoundingBox;
}

OUString SvxPixelCtlAccessibleChild::GetName()
diff --git a/svx/source/accessibility/svxrectctaccessiblecontext.cxx b/svx/source/accessibility/svxrectctaccessiblecontext.cxx
index 2f47403..0b09193 100644
--- a/svx/source/accessibility/svxrectctaccessiblecontext.cxx
+++ b/svx/source/accessibility/svxrectctaccessiblecontext.cxx
@@ -660,7 +660,7 @@ SvxRectCtlChildAccessibleContext::SvxRectCtlChildAccessibleContext(
    msDescription( rDescription ),
    msName( rName ),
    mxParent(rxParent),
    mpBoundingBox( new tools::Rectangle( rBoundingBox ) ),
    maBoundingBox( rBoundingBox ),
    mrParentWindow( rParentWindow ),
    mnClientId( 0 ),
    mnIndexInParent( nIndexInParent ),
@@ -986,8 +986,6 @@ void SAL_CALL SvxRectCtlChildAccessibleContext::disposing()
        }

        mxParent.clear();

        delete mpBoundingBox;
    }
}

@@ -1009,10 +1007,10 @@ tools::Rectangle SvxRectCtlChildAccessibleContext::GetBoundingBoxOnScreen()

tools::Rectangle const & SvxRectCtlChildAccessibleContext::GetBoundingBox()
{
    // no guard necessary, because no one changes mpBoundingBox after creating it
    // no guard necessary, because no one changes maBoundingBox after creating it
    ThrowExceptionIfNotAlive();

    return *mpBoundingBox;
    return maBoundingBox;
}

void SvxRectCtlChildAccessibleContext::setStateChecked( bool bChecked )
diff --git a/svx/source/form/formcontroller.cxx b/svx/source/form/formcontroller.cxx
index bd28d36..55aeb92 100644
--- a/svx/source/form/formcontroller.cxx
+++ b/svx/source/form/formcontroller.cxx
@@ -540,7 +540,6 @@ FormController::FormController(const Reference< css::uno::XComponentContext > & 
                  ,m_aRowSetApproveListeners(m_aMutex)
                  ,m_aParameterListeners(m_aMutex)
                  ,m_aFilterListeners(m_aMutex)
                  ,m_pControlBorderManager( new ::svxform::ControlBorderManager )
                  ,m_xFormOperations()
                  ,m_aMode( OUString( "DataMode"  ) )
                  ,m_aLoadEvent( LINK( this, FormController, OnLoad ) )
@@ -610,9 +609,6 @@ FormController::~FormController()
        m_xAggregate->setDelegator( nullptr );
        m_xAggregate.clear();
    }

    DELETEZ( m_pControlBorderManager );

}


@@ -1164,7 +1160,7 @@ void FormController::disposing()
    removeBoundFieldListener();
    stopFiltering();

    m_pControlBorderManager->restoreAll();
    m_aControlBorderManager.restoreAll();

    m_aFilterRows.clear();

@@ -1284,13 +1280,13 @@ void SAL_CALL FormController::propertyChange(const PropertyChangeEvent& evt)
            bool bEnable = lcl_shouldUseDynamicControlBorder( evt.Source, evt.NewValue );
            if ( bEnable )
            {
                m_pControlBorderManager->enableDynamicBorderColor();
                m_aControlBorderManager.enableDynamicBorderColor();
                if ( m_xActiveControl.is() )
                    m_pControlBorderManager->focusGained( m_xActiveControl.get() );
                    m_aControlBorderManager.focusGained( m_xActiveControl.get() );
            }
            else
            {
                m_pControlBorderManager->disableDynamicBorderColor();
                m_aControlBorderManager.disableDynamicBorderColor();
            }
        }
    }
@@ -1621,7 +1617,7 @@ void FormController::focusGained(const FocusEvent& e)
    ::osl::ClearableMutexGuard aGuard( m_aMutex );
    impl_checkDisposed_throw();

    m_pControlBorderManager->focusGained( e.Source );
    m_aControlBorderManager.focusGained( e.Source );

    Reference< XControl >  xControl(e.Source, UNO_QUERY);
    if (m_bDBConnection)
@@ -1772,7 +1768,7 @@ void FormController::focusLost(const FocusEvent& e)
{
    OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );

    m_pControlBorderManager->focusLost( e.Source );
    m_aControlBorderManager.focusLost( e.Source );

    Reference< XControl >  xControl(e.Source, UNO_QUERY);
    Reference< XWindowPeer >  xNext(e.NextFocus, UNO_QUERY);
@@ -1799,13 +1795,13 @@ void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ 

void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent )
{
    m_pControlBorderManager->mouseEntered( _rEvent.Source );
    m_aControlBorderManager.mouseEntered( _rEvent.Source );
}


void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent )
{
    m_pControlBorderManager->mouseExited( _rEvent.Source );
    m_aControlBorderManager.mouseExited( _rEvent.Source );
}


@@ -1817,7 +1813,7 @@ void SAL_CALL FormController::componentValidityChanged( const EventObject& _rSou
    OSL_ENSURE( xControl.is() && xValidatable.is(), "FormController::componentValidityChanged: huh?" );

    if ( xControl.is() && xValidatable.is() )
        m_pControlBorderManager->validityChanged( xControl, xValidatable );
        m_aControlBorderManager.validityChanged( xControl, xValidatable );
}


@@ -1913,17 +1909,17 @@ void FormController::setModel(const Reference< XTabControllerModel > & Model)
                bool bEnableDynamicControlBorder = lcl_shouldUseDynamicControlBorder(
                    xModelProps.get(), xModelProps->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER ) );
                if ( bEnableDynamicControlBorder )
                    m_pControlBorderManager->enableDynamicBorderColor();
                    m_aControlBorderManager.enableDynamicBorderColor();
                else
                    m_pControlBorderManager->disableDynamicBorderColor();
                    m_aControlBorderManager.disableDynamicBorderColor();

                sal_Int32 nColor = 0;
                if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS ) >>= nColor )
                    m_pControlBorderManager->setStatusColor( ControlStatus::Focused, nColor );
                    m_aControlBorderManager.setStatusColor( ControlStatus::Focused, nColor );
                if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE ) >>= nColor )
                    m_pControlBorderManager->setStatusColor( ControlStatus::MouseHover, nColor );
                    m_aControlBorderManager.setStatusColor( ControlStatus::MouseHover, nColor );
                if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID ) >>= nColor )
                    m_pControlBorderManager->setStatusColor( ControlStatus::Invalid, nColor );
                    m_aControlBorderManager.setStatusColor( ControlStatus::Invalid, nColor );
            }
        }
    }
@@ -2436,7 +2432,7 @@ void FormController::implControlInserted( const Reference< XControl>& _rxControl
        if ( xValidatable.is() )
        {
            xValidatable->addFormComponentValidityListener( this );
            m_pControlBorderManager->validityChanged( _rxControl, xValidatable );
            m_aControlBorderManager.validityChanged( _rxControl, xValidatable );
        }
    }

diff --git a/svx/source/inc/formcontroller.hxx b/svx/source/inc/formcontroller.hxx
index 5ee3257..7fe54a1 100644
--- a/svx/source/inc/formcontroller.hxx
+++ b/svx/source/inc/formcontroller.hxx
@@ -166,8 +166,8 @@ namespace svxform
        Idle                        m_aTabActivationIdle;
        Timer                       m_aFeatureInvalidationTimer;

        ::svxform::ControlBorderManager*
                                    m_pControlBorderManager;
        ::svxform::ControlBorderManager
                                    m_aControlBorderManager;

        css::uno::Reference< css::form::runtime::XFormOperations >
                                    m_xFormOperations;
diff --git a/svx/source/inc/svxpixelctlaccessiblecontext.hxx b/svx/source/inc/svxpixelctlaccessiblecontext.hxx
index 827fab9..6188017 100644
--- a/svx/source/inc/svxpixelctlaccessiblecontext.hxx
+++ b/svx/source/inc/svxpixelctlaccessiblecontext.hxx
@@ -69,7 +69,7 @@ class SvxPixelCtlAccessibleChild :
    SvxPixelCtl& mrParentWindow;
    css::uno::Reference< css::accessibility::XAccessible > mxParent;
    bool m_bPixelColorOrBG;//Pixel Color Or BackGround Color
    tools::Rectangle*  mpBoundingBox;
    tools::Rectangle  maBoundingBox;
    /// index of child in parent
    long                                mnIndexInParent;
public:
diff --git a/svx/source/inc/svxrectctaccessiblecontext.hxx b/svx/source/inc/svxrectctaccessiblecontext.hxx
index 1a71e78..5cfe6f8 100644
--- a/svx/source/inc/svxrectctaccessiblecontext.hxx
+++ b/svx/source/inc/svxrectctaccessiblecontext.hxx
@@ -45,6 +45,7 @@
#include <comphelper/servicehelper.hxx>
#include <svx/rectenum.hxx>
#include <vcl/vclptr.hxx>
#include <tools/gen.hxx>

namespace com { namespace sun { namespace star { namespace awt {
    struct Point;
@@ -437,7 +438,7 @@ private:
                                        mxParent;

    /// Bounding box
    tools::Rectangle*                          mpBoundingBox;
    tools::Rectangle                         maBoundingBox;

    /// window of parent
    const vcl::Window&                       mrParentWindow;
diff --git a/svx/source/sidebar/nbdtmg.cxx b/svx/source/sidebar/nbdtmg.cxx
index 6f9ef28..1e9f1b1 100644
--- a/svx/source/sidebar/nbdtmg.cxx
+++ b/svx/source/sidebar/nbdtmg.cxx
@@ -426,20 +426,14 @@ bool BulletsTypeMgr::IsCustomized(sal_uInt16 nIndex)
// Numbering Type lib
NumberingTypeMgr::NumberingTypeMgr()
    : NBOTypeMgrBase()
    , pNumberSettingsArr (new NumberSettingsArr_Impl)
{
    Init();
    pDefaultNumberSettingsArr = pNumberSettingsArr;
    pNumberSettingsArr = new NumberSettingsArr_Impl;
    //Initial the first time to store the default value. Then do it again for customized value
    Init();
    maDefaultNumberSettingsArr = maNumberSettingsArr;
    ImplLoad("standard.syb");
}

NumberingTypeMgr::~NumberingTypeMgr()
{
    delete pNumberSettingsArr;
    delete pDefaultNumberSettingsArr;
}

class theNumberingTypeMgr : public rtl::Static<NumberingTypeMgr, theNumberingTypeMgr> {};
@@ -472,7 +466,7 @@ void NumberingTypeMgr::Init()
            pNumEntry->pNumSetting = pNew;
            if ( i < 8 )
                pNumEntry->sDescription = SVX_RESSTR( RID_SVXSTR_SINGLENUM_DESCRIPTIONS + i );
            pNumberSettingsArr->push_back(std::shared_ptr<NumberSettings_Impl>(pNumEntry));
            maNumberSettingsArr.push_back(std::shared_ptr<NumberSettings_Impl>(pNumEntry));
        }
    }
    catch(Exception&)
@@ -497,10 +491,10 @@ sal_uInt16 NumberingTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 m
    OUString sLclSuffix = aFmt.GetSuffix();
    sal_Int16 eNumType = aFmt.GetNumberingType();

    sal_uInt16 nCount = pNumberSettingsArr->size();
    sal_uInt16 nCount = maNumberSettingsArr.size();
    for(sal_uInt16 i = nFromIndex; i < nCount; ++i)
    {
        NumberSettings_Impl* _pSet = (*pNumberSettingsArr)[i].get();
        NumberSettings_Impl* _pSet = maNumberSettingsArr[i].get();
        sal_Int16 eNType = _pSet->pNumSetting->nNumberType;
        OUString sLocalPrefix = _pSet->pNumSetting->sPrefix;
        OUString sLocalSuffix = _pSet->pNumSetting->sSuffix;
@@ -526,11 +520,11 @@ void NumberingTypeMgr::RelplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_
    SvxNumberFormat aFmt(aNum.GetLevel(nActLv));
    SvxNumType eNumType = aFmt.GetNumberingType();

    sal_uInt16 nCount = pNumberSettingsArr->size();
    sal_uInt16 nCount = maNumberSettingsArr.size();
    if ( nIndex >= nCount )
        return;

    NumberSettings_Impl* _pSet = (*pNumberSettingsArr)[nIndex].get();
    NumberSettings_Impl* _pSet = maNumberSettingsArr[nIndex].get();

    _pSet->pNumSetting->sPrefix = aFmt.GetPrefix();
    _pSet->pNumSetting->sSuffix = aFmt.GetSuffix();
@@ -555,10 +549,10 @@ void NumberingTypeMgr::RelplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_

void NumberingTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool isDefault, bool isResetSize)
{
    if(pNumberSettingsArr->size() <= nIndex)
    if(maNumberSettingsArr.size() <= nIndex)
        return;
    NumberSettingsArr_Impl*     pCurrentNumberSettingsArr=pNumberSettingsArr;
    if (isDefault) pCurrentNumberSettingsArr=pDefaultNumberSettingsArr;
    NumberSettingsArr_Impl*     pCurrentNumberSettingsArr = &maNumberSettingsArr;
    if (isDefault) pCurrentNumberSettingsArr = &maDefaultNumberSettingsArr;
    NumberSettings_Impl* _pSet = (*pCurrentNumberSettingsArr)[nIndex].get();
    SvxNumType eNewType = _pSet->pNumSetting->nNumberType;

@@ -586,13 +580,13 @@ OUString NumberingTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault)
{
    OUString sRet;
    sal_uInt16 nLength = 0;
    nLength = pNumberSettingsArr->size();
    nLength = maNumberSettingsArr.size();

    if ( nIndex >= nLength )
        return sRet;
    else
        sRet = (*pNumberSettingsArr)[nIndex]->sDescription;
    if (isDefault) sRet = (*pDefaultNumberSettingsArr)[nIndex]->sDescription;
        sRet = maNumberSettingsArr[nIndex]->sDescription;
    if (isDefault) sRet = maDefaultNumberSettingsArr[nIndex]->sDescription;

    return sRet;
}
@@ -601,12 +595,12 @@ bool NumberingTypeMgr::IsCustomized(sal_uInt16 nIndex)
{
    bool bRet = false;
    sal_uInt16 nLength = 0;
    nLength = pNumberSettingsArr->size();
    nLength = maNumberSettingsArr.size();

    if ( nIndex >= nLength )
        bRet = false;
    else
        bRet = (*pNumberSettingsArr)[nIndex]->bIsCustomized;
        bRet = maNumberSettingsArr[nIndex]->bIsCustomized;

    return bRet;
}