[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 45 commits - avmedia/source basic/qa basic/source bin/lo-all-static-libs canvas/source chart2/qa comphelper/source compilerplugins/clang configmgr/source configure.ac connectivity/source cppuhelper/source cui/uiconfig dbaccess/source desktop/source dtrans/source editeng/source embeddedobj/source embedserv/source extensions/source filter/source fpicker/source framework/source helpcompiler/inc helpcompiler/source helpcontent2 idlc/source include/comphelper include/editeng include/o3tl include/sal include/sfx2 include/svl include/unotools include/vbahelper include/vcl ios/CustomTarget_iOS.mk ios/LibreOfficeKit jvmfwk/plugins mysqlc/source offapi/com officecfg/registry oox/source reportdesign/source sal/osl sal/qa sc/qa sc/source sfx2/sdi sfx2/source shell/source solenv/CompilerTest_compilerplugins_clang.mk solenv/gbuild svl/source svtools/source svx/sdi sw/inc sw/qa sw/source test/source tools/source unotools/source unoxml/sourc e vbahelper/source vcl/inc vcl/opengl vcl/osx vcl/source vcl/unx vcl/win winaccessibility/source writerfilter/source xmlsecurity/inc xmlsecurity/source

Jan-Marek Glogowski glogow at fbihome.de
Fri Oct 6 11:15:34 UTC 2017


Rebased ref, commits from common ancestor:
commit e729d5350fad2c3255be6efecafbd82db4fe9d4d
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 6 12:53:05 2017 +0200

    Process all pending events during Cppunit setUp
    
    Larger unit tests collect a lot of events, which are just processed
    on shutdown. But since the Scheduler is just an unsorted linked
    list, processing these in order is O(n2) for lookup, which really
    adds up, e.g. sw_ooxmlexport8 has 35047 tasks on shutdown.
    
    So this just processes all pending events before running each unit
    test.
    
    Change-Id: Icf12146015afc17a1f52f79c18f248b72650ad46

diff --git a/test/source/bootstrapfixture.cxx b/test/source/bootstrapfixture.cxx
index 415292bd2a26..a195db529d71 100644
--- a/test/source/bootstrapfixture.cxx
+++ b/test/source/bootstrapfixture.cxx
@@ -31,6 +31,7 @@
 #include <unotools/syslocaleoptions.hxx>
 #include <osl/file.hxx>
 #include <unotools/tempfile.hxx>
+#include <vcl/scheduler.hxx>
 
 #include <isheadless.hxx>
 
@@ -104,6 +105,10 @@ void test::BootstrapFixture::setUp()
     test::BootstrapFixtureBase::setUp();
 
     test_init_impl(m_bAssertOnDialog, m_bNeedUCB, m_xSFactory.get());
+
+#if OSL_DEBUG_LEVEL > 0
+    Scheduler::ProcessEventsToIdle();
+#endif
 }
 
 test::BootstrapFixture::~BootstrapFixture()
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 92db1e23563a..7e908e6e1f06 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -96,7 +96,6 @@ void Scheduler::ImplDeInitScheduler()
 
     SchedulerGuard aSchedulerGuard;
 
-#if OSL_DEBUG_LEVEL > 0
     {
         ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData;
         sal_uInt32 nTasks = 0;
@@ -105,9 +104,11 @@ void Scheduler::ImplDeInitScheduler()
             ++nTasks;
             pSchedulerData = pSchedulerData->mpNext;
         }
-        SAL_INFO( "vcl.schedule.deinit", "DeInit the scheduler - tasks: " << nTasks );
+        SAL_WARN_IF( 0 != nTasks, "vcl.schedule.deinit",
+                     "DeInit the scheduler - pending tasks: " << nTasks );
     }
 
+#if OSL_DEBUG_LEVEL > 0
     // clean up all the sfx::SfxItemDisruptor_Impl Idles
     ProcessEventsToIdle();
 #endif
commit a31c05e52bdb04d7b56a18e1638080b8e73f63e7
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Thu Oct 5 18:19:32 2017 +0200

    KDE update system loop integration
    
    This updates the system loop integration to be on par with the
    other backends. This includes:
    
    1. Process LO user events before other LO events
    2. Correctly handle elapsed QTimer events
    3. Don't wait-yield in the main thread from a non-main thread
    
    Change-Id: Ia17be032ae39dc4c7bfa44cadd22d85a1b9c4fbd

diff --git a/vcl/inc/unx/gendisp.hxx b/vcl/inc/unx/gendisp.hxx
index 5c8f5113c300..2d5bc12fcadf 100644
--- a/vcl/inc/unx/gendisp.hxx
+++ b/vcl/inc/unx/gendisp.hxx
@@ -47,7 +47,7 @@ public:
 
     void SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent = SalEvent::UserEvent );
     void CancelInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent );
-    bool DispatchInternalEvent();
+    bool DispatchInternalEvent( bool bHandleAllCurrentEvent = false );
 
     bool     MouseCaptured( const SalFrame *pFrameData ) const
                         { return m_pCapture == pFrameData; }
diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx
index 8f96e03630b0..54799149e25c 100644
--- a/vcl/inc/unx/saldisp.hxx
+++ b/vcl/inc/unx/saldisp.hxx
@@ -179,7 +179,7 @@ public:
     virtual void    StartTimer( sal_uLong nMS );
     virtual void    StopTimer();
 
-    bool            CheckTimeout( bool bExecuteTimers = true );
+    virtual bool    CheckTimeout( bool bExecuteTimers = true );
 
     SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod; }
     Display*             GetDisplay() const { return m_pDisplay; }
diff --git a/vcl/source/app/salusereventlist.cxx b/vcl/source/app/salusereventlist.cxx
index 6384d8805be4..8f9d76ed313f 100644
--- a/vcl/source/app/salusereventlist.cxx
+++ b/vcl/source/app/salusereventlist.cxx
@@ -51,6 +51,7 @@ bool SalUserEventList::DispatchUserEvents( bool bHandleAllCurrentEvents )
 
     {
         osl::MutexGuard aGuard( m_aUserEventsMutex );
+        assert( m_aProcessingUserEvents.empty() );
         if( ! m_aUserEvents.empty() )
         {
             if( bHandleAllCurrentEvents )
diff --git a/vcl/unx/generic/app/gendisp.cxx b/vcl/unx/generic/app/gendisp.cxx
index 1be8606602e0..c83283a7b0e0 100644
--- a/vcl/unx/generic/app/gendisp.cxx
+++ b/vcl/unx/generic/app/gendisp.cxx
@@ -47,9 +47,9 @@ void SalGenericDisplay::emitDisplayChanged()
         pAnyFrame->CallCallback( SalEvent::DisplayChanged, nullptr );
 }
 
-bool SalGenericDisplay::DispatchInternalEvent()
+bool SalGenericDisplay::DispatchInternalEvent( bool bHandleAllCurrentEvent )
 {
-    return DispatchUserEvents( false );
+    return DispatchUserEvents( bHandleAllCurrentEvent );
 }
 
 void SalGenericDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent )
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index abd29a78c077..0d30e1d17a99 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -147,7 +147,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType)
 
     if( (nType & VclInputFlags::TIMER) && (mpXLib && mpXLib->CheckTimeout(false)) )
         bRet = true;
-    else if (XPending(pDisplay) )
+
+    if( !bRet && XPending(pDisplay) )
     {
         PredicateReturn aInput;
         XEvent          aEvent;
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx
index 8a2422a3918d..14a753e1c0a1 100644
--- a/vcl/unx/kde4/KDESalDisplay.cxx
+++ b/vcl/unx/kde4/KDESalDisplay.cxx
@@ -47,9 +47,6 @@ SalKDEDisplay::~SalKDEDisplay()
 
 void SalKDEDisplay::Yield()
 {
-    if( DispatchInternalEvent() )
-        return;
-
     // Prevent blocking from Drag'n'Drop events, which may have already have processed the event
     if (XEventsQueued( pDisp_, QueuedAfterReading ) == 0)
         return;
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index f047ed9fce65..43e055a2c0bb 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -53,6 +53,7 @@ KDEXLib::KDEXLib() :
     m_nFakeCmdLineArgs( 0 ),
     m_isGlibEventLoopType(false), m_allowKdeDialogs(false),
     m_timerEventId( -1 ), m_postUserEventId( -1 )
+    , m_bTimedOut( false )
 {
     m_timerEventId = QEvent::registerEventType();
     m_postUserEventId = QEvent::registerEventType();
@@ -269,22 +270,24 @@ void KDEXLib::socketNotifierActivated( int fd )
 
 bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
 {
+    bool bWasEvent = false;
     if( !m_isGlibEventLoopType )
     {
-        bool wasEvent = false;
         if( qApp->thread() == QThread::currentThread())
         {
             // even if we use the LO event loop, still process Qt's events,
             // otherwise they can remain unhandled for quite a long while
-            wasEvent = processYield( false, bHandleAllCurrentEvents );
+            bWasEvent = processYield( false, bHandleAllCurrentEvents );
         }
-        return SalXLib::Yield(bWait, bHandleAllCurrentEvents) || wasEvent;
+        return SalXLib::Yield(bWait, bHandleAllCurrentEvents) || bWasEvent;
     }
     // if we are the main thread (which is where the event processing is done),
     // good, just do it
     if( qApp->thread() == QThread::currentThread())
     {
-        return processYield( bWait, bHandleAllCurrentEvents );
+        bWasEvent = processYield( bWait, bHandleAllCurrentEvents );
+        if ( bWasEvent )
+            m_aWaitingYieldCond.set();
     }
     else
     {
@@ -292,23 +295,40 @@ bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
         // release the yield lock to prevent deadlock with the main thread
         // (it's ok to release it here, since even normal processYield() would
         // temporarily do it while checking for new events)
-        SolarMutexReleaser aReleaser;
-        return Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents );
+        {
+            SolarMutexReleaser aReleaser;
+            bWasEvent = Q_EMIT processYieldSignal( false, bHandleAllCurrentEvents );
+        }
+        if ( !bWasEvent && bWait )
+        {
+            m_aWaitingYieldCond.reset();
+            SolarMutexReleaser aReleaser;
+            m_aWaitingYieldCond.wait();
+            bWasEvent = true;
+        }
     }
+    return bWasEvent;
 }
 
-/**
- * Quoting the Qt docs: [QAbstractEventDispatcher::processEvents] processes
- * pending events that match flags until there are no more events to process.
- */
-bool KDEXLib::processYield( bool bWait, bool )
+bool KDEXLib::processYield( bool bWait, bool bHandleAllCurrentEvents )
 {
-    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread());
     bool wasEvent = false;
-    if ( bWait )
+    if ( m_isGlibEventLoopType )
+    {
+        wasEvent = SalKDEDisplay::self()->DispatchInternalEvent( bHandleAllCurrentEvents );
+        if ( !bHandleAllCurrentEvents && wasEvent )
+            return true;
+    }
+
+    /**
+     * Quoting the Qt docs: [QAbstractEventDispatcher::processEvents] processes
+     * pending events that match flags until there are no more events to process.
+     */
+    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread());
+    if ( bWait && !wasEvent )
         wasEvent = dispatcher->processEvents( QEventLoop::WaitForMoreEvents );
     else
-        wasEvent = dispatcher->processEvents( QEventLoop::AllEvents );
+        wasEvent = dispatcher->processEvents( QEventLoop::AllEvents ) || wasEvent;
     return wasEvent;
 }
 
@@ -336,18 +356,28 @@ void KDEXLib::StopTimer()
     timeoutTimer.stop();
 }
 
+bool KDEXLib::CheckTimeout( bool bExecuteTimers )
+{
+    if( !m_isGlibEventLoopType )
+        return SalXLib::CheckTimeout( bExecuteTimers );
+    assert( !bExecuteTimers );
+    return m_bTimedOut;
+}
+
 void KDEXLib::timeoutActivated()
 {
     // don't potentially wait in timeout, as QTimer is non-recursive
+    m_bTimedOut = true;
     QApplication::postEvent(this, new QEvent(QEvent::Type( m_timerEventId )));
 }
 
 void KDEXLib::customEvent(QEvent* e)
 {
     if( e->type() == m_timerEventId )
+    {
+        m_bTimedOut = false;
         X11SalData::Timeout();
-    else if( e->type() == m_postUserEventId )
-        SalKDEDisplay::self()->DispatchInternalEvent();
+    }
 }
 
 void KDEXLib::Wakeup()
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 4c06104b4c59..452aae8b3286 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -30,13 +30,14 @@
 #include <QtCore/QTimer>
 
 #include <unx/salinst.h>
+#include <osl/conditn.hxx>
 
 class VCLKDEApplication;
 
 class KDEXLib : public QObject, public SalXLib
 {
     Q_OBJECT
-    private:
+
         bool m_bStartupDone;
         std::unique_ptr<VCLKDEApplication> m_pApplication;
         std::unique_ptr<char*[]> m_pFreeCmdLineArgs;
@@ -56,23 +57,24 @@ class KDEXLib : public QObject, public SalXLib
         bool m_allowKdeDialogs;
         int m_timerEventId;
         int m_postUserEventId;
+    osl::Condition m_aWaitingYieldCond;
+    bool m_bTimedOut;
 
-    private:
-        void setupEventLoop();
+    void setupEventLoop();
 
-    private Q_SLOTS:
+private Q_SLOTS:
         void socketNotifierActivated( int fd );
         void timeoutActivated();
         void startTimeoutTimer();
-        static bool processYield( bool bWait, bool bHandleAllCurrentEvents );
+        bool processYield( bool bWait, bool bHandleAllCurrentEvents );
 
-    Q_SIGNALS:
+Q_SIGNALS:
         void startTimeoutTimerSignal();
         bool processYieldSignal( bool bWait, bool bHandleAllCurrentEvents );
         css::uno::Reference< css::ui::dialogs::XFilePicker2 >
             createFilePickerSignal( const css::uno::Reference< css::uno::XComponentContext >& );
 
-    public:
+public:
         KDEXLib();
         virtual ~KDEXLib() override;
 
@@ -82,6 +84,7 @@ class KDEXLib : public QObject, public SalXLib
         virtual void Remove( int fd ) override;
         virtual void StartTimer( sal_uLong nMS ) override;
         virtual void StopTimer() override;
+        virtual bool CheckTimeout( bool bExecuteTimers = true ) override;
         virtual void Wakeup() override;
         void TriggerUserEventProcessing();
 
@@ -90,7 +93,7 @@ class KDEXLib : public QObject, public SalXLib
 
         virtual void customEvent(QEvent* e) override;
 
-    public Q_SLOTS:
+public Q_SLOTS:
         css::uno::Reference< css::ui::dialogs::XFilePicker2 >
             createFilePicker( const css::uno::Reference< css::uno::XComponentContext >& );
 };
commit 32dfb35a57892b5f0f37cb54bd51a33fe048da8f
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 6 11:00:19 2017 +0200

    Don't schedule the Idle job for busy documents
    
    This refactors DocumentTimerManager to export the busy status
    independent of the Idle function. This way it can be ignored in
    the Scheduler while the document is busy,
    
    Change-Id: Icec2075d3338ad8dd4440678eb0570d7fe887778

diff --git a/sw/inc/IDocumentTimerAccess.hxx b/sw/inc/IDocumentTimerAccess.hxx
index 717728f83c99..6efe1a114963 100644
--- a/sw/inc/IDocumentTimerAccess.hxx
+++ b/sw/inc/IDocumentTimerAccess.hxx
@@ -55,6 +55,11 @@ public:
     */
     virtual void StartBackgroundJobs() = 0;
 
+    /**
+     * Is the document ready to be processed?
+     */
+    virtual bool IsDocIdle() const = 0;
+
 protected:
     virtual ~IDocumentTimerAccess() {};
 };
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index b12d2f8d821b..7476a3665f20 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -223,9 +223,6 @@ namespace sfx2 {
 
 void SetAllScriptItem( SfxItemSet& rSet, const SfxPoolItem& rItem );
 
-// global function to start grammar checking in the document
-void StartGrammarChecking( SwDoc &rDoc );
-
 using SwRubyList = std::vector<std::unique_ptr<SwRubyListEntry>>;
 
 // Represents the model of a Writer document.
@@ -1630,6 +1627,12 @@ public:
                       rTable.end());
     }
 
+    /**
+     * @param bSkipStart don't actually start the jobs, just check
+     * @returns true if new background checking jobs were started
+     */
+    bool StartGrammarChecking( bool bSkipStart = false );
+
 private:
     // Copies master header to left / first one, if necessary - used by ChgPageDesc().
     void CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHead, SwPageDesc &pDesc, bool bLeft, bool bFirst);
diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx
index ec4874ea9ecc..5429c6edbda6 100644
--- a/sw/source/core/doc/DocumentTimerManager.cxx
+++ b/sw/source/core/doc/DocumentTimerManager.cxx
@@ -80,27 +80,16 @@ void DocumentTimerManager::StartBackgroundJobs()
         maDocIdle.Start();
 }
 
-IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
+DocumentTimerManager::IdleJob DocumentTimerManager::GetNextIdleJob() const
 {
-#ifdef TIMELOG
-    static ::rtl::Logfile* pModLogFile = 0;
-    if( !pModLogFile )
-        pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
-#endif
-
     SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
     if( pTmpRoot &&
         !SfxProgress::GetActiveProgress( m_rDoc.GetDocShell() ) )
     {
         SwViewShell* pShell(m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell());
         for(SwViewShell& rSh : pShell->GetRingContainer())
-        {
             if( rSh.ActionPend() )
-            {
-                pIdle->Start();
-                return;
-            }
-        }
+                return IdleJob::Busy;
 
         if( pTmpRoot->IsNeedGrammarCheck() )
         {
@@ -109,59 +98,93 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
             SvtLinguConfig().GetProperty( OUString(
                         UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
 
-            if (bIsOnlineSpell && bIsAutoGrammar)
-                StartGrammarChecking( m_rDoc );
+            if( bIsOnlineSpell && bIsAutoGrammar && m_rDoc.StartGrammarChecking( true ) )
+                return IdleJob::Grammar;
         }
-        std::set<SwRootFrame*> aAllLayouts = m_rDoc.GetAllLayouts();
-        std::set<SwRootFrame*>::iterator pLayIter = aAllLayouts.begin();
-        for ( ;pLayIter != aAllLayouts.end();++pLayIter )
+
+        for ( auto pLayout : m_rDoc.GetAllLayouts() )
         {
-            if ((*pLayIter)->IsIdleFormat())
-            {
-                (*pLayIter)->GetCurrShell()->LayoutIdle();
-                // Defer the remaining work.
-                pIdle->Start();
-                return;
-            }
+            if( pLayout->IsIdleFormat() )
+                return IdleJob::Layout;
         }
 
         SwFieldUpdateFlags nFieldUpdFlag = m_rDoc.GetDocumentSettingManager().getFieldUpdateFlags(true);
         if( ( AUTOUPD_FIELD_ONLY == nFieldUpdFlag
-                    || AUTOUPD_FIELD_AND_CHARTS == nFieldUpdFlag ) &&
-                m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsFieldsDirty()
-                // If we switch the field name the Fields are not updated.
-                // So the "background update" should always be carried out
-                /* && !pStartSh->GetViewOptions()->IsFieldName()*/ )
+                    || AUTOUPD_FIELD_AND_CHARTS == nFieldUpdFlag )
+                && m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsFieldsDirty() )
         {
-            if ( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields() ||
-                      m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+            if( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields()
+                    || m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+                return IdleJob::Busy;
+            return IdleJob::Fields;
+        }
+    }
+
+    return IdleJob::None;
+}
+
+IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
+{
+#ifdef TIMELOG
+    static ::rtl::Logfile* pModLogFile = 0;
+    if( !pModLogFile )
+        pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
+#endif
+
+    IdleJob eJob = GetNextIdleJob();
+
+    switch ( eJob )
+    {
+    case IdleJob::Grammar:
+        m_rDoc.StartGrammarChecking();
+        break;
+
+    case IdleJob::Layout:
+        for ( auto pLayout : m_rDoc.GetAllLayouts() )
+            if( pLayout->IsIdleFormat() )
             {
-                pIdle->Start();
-                return;
+                pLayout->GetCurrShell()->LayoutIdle();
+                break;
             }
+         break;
 
-            //  Action brackets!
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( true );
+    case IdleJob::Fields:
+    {
+        SwViewShell* pShell( m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell() );
+        SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
 
-            pTmpRoot->StartAllAction();
+        //  Action brackets!
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( true );
 
-            // no jump on update of fields #i85168#
-            const bool bOldLockView = pShell->IsViewLocked();
-            pShell->LockView( true );
+        pTmpRoot->StartAllAction();
 
-            m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter )->ModifyNotification( nullptr, nullptr );    // ChapterField
-            m_rDoc.getIDocumentFieldsAccess().UpdateExpFields( nullptr, false );      // Updates ExpressionFields
-            m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);                // Tables
-            m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();                // References
+        // no jump on update of fields #i85168#
+        const bool bOldLockView = pShell->IsViewLocked();
+        pShell->LockView( true );
 
-            pTmpRoot->EndAllAction();
+        m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter )->ModifyNotification( nullptr, nullptr );  // ChapterField
+        m_rDoc.getIDocumentFieldsAccess().UpdateExpFields( nullptr, false );  // Updates ExpressionFields
+        m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);  // Tables
+        m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();  // References
 
-            pShell->LockView( bOldLockView );
+        pTmpRoot->EndAllAction();
 
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( false );
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty( false );
-        }
+        pShell->LockView( bOldLockView );
+
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( false );
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty( false );
+        break;
     }
+
+    case IdleJob::Busy:
+        break;
+    case IdleJob::None:
+        break;
+    }
+
+    if ( IdleJob::None != eJob )
+        pIdle->Start();
+
 #ifdef TIMELOG
     if( pModLogFile && 1 != (long)pModLogFile )
         delete pModLogFile, static_cast<long&>(pModLogFile) = 1;
diff --git a/sw/source/core/doc/SwDocIdle.cxx b/sw/source/core/doc/SwDocIdle.cxx
index 9461807943d8..5987274a6b3d 100644
--- a/sw/source/core/doc/SwDocIdle.cxx
+++ b/sw/source/core/doc/SwDocIdle.cxx
@@ -24,6 +24,7 @@
 #include <vcl/scheduler.hxx>
 
 #include "SwDocIdle.hxx"
+#include "IDocumentTimerAccess.hxx"
 
 namespace sw
 {
@@ -31,12 +32,17 @@ namespace sw
 sal_uInt64 SwDocIdle::UpdateMinPeriod( sal_uInt64 /* nMinPeriod */, sal_uInt64 /* nTimeNow */ ) const
 {
     bool bReadyForSchedule = true;
+
     SwView* pView = m_rDoc.GetDocShell() ? m_rDoc.GetDocShell()->GetView() : nullptr;
     if( pView )
     {
         SwWrtShell& rWrtShell = pView->GetWrtShell();
         bReadyForSchedule = rWrtShell.GetViewOptions()->IsIdle();
     }
+
+    if( bReadyForSchedule && !m_rDoc.getIDocumentTimerAccess().IsDocIdle() )
+        bReadyForSchedule = false;
+
     return bReadyForSchedule
         ? Scheduler::ImmediateTimeoutMs : Scheduler::InfiniteTimeoutMs;
 }
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 883fcbac9047..9e2a82d3083c 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -141,11 +141,12 @@ using namespace ::com::sun::star::document;
     return m_xGCIterator;
 }
 
-void StartGrammarChecking( SwDoc &rDoc )
+bool SwDoc::StartGrammarChecking( bool bSkipStart )
 {
     // check for a visible view
     bool bVisible = false;
-    const SwDocShell *pDocShell = rDoc.GetDocShell();
+    bool bStarted = false;
+    const SwDocShell *pDocShell = GetDocShell();
     SfxViewFrame     *pFrame = SfxViewFrame::GetFirst( pDocShell, false );
     while (pFrame && !bVisible)
     {
@@ -160,17 +161,23 @@ void StartGrammarChecking( SwDoc &rDoc )
     //!! a uno reference to them)
     if (bVisible)
     {
-        uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( rDoc.GetGCIterator() );
+        uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( GetGCIterator() );
         if ( xGCIterator.is() )
         {
-            uno::Reference< lang::XComponent >  xDoc( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
+            uno::Reference< lang::XComponent >  xDoc( GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
             uno::Reference< text::XFlatParagraphIteratorProvider >  xFPIP( xDoc, uno::UNO_QUERY );
 
             // start automatic background checking if not active already
             if ( xFPIP.is() && !xGCIterator->isProofreading( xDoc ) )
-                xGCIterator->startProofreading( xDoc, xFPIP );
+            {
+                bStarted = true;
+                if ( !bSkipStart )
+                    xGCIterator->startProofreading( xDoc, xFPIP );
+            }
         }
     }
+
+    return bStarted;
 }
 
 /*
diff --git a/sw/source/core/inc/DocumentTimerManager.hxx b/sw/source/core/inc/DocumentTimerManager.hxx
index 698762ab087e..d8c1a76b2a14 100644
--- a/sw/source/core/inc/DocumentTimerManager.hxx
+++ b/sw/source/core/inc/DocumentTimerManager.hxx
@@ -34,8 +34,17 @@ namespace sw
 class DocumentTimerManager : public IDocumentTimerAccess
 {
 public:
+    enum class IdleJob
+    {
+        None, ///< document has no idle jobs to do
+        Busy, ///< document is busy and idle jobs are postponed
+        Grammar,
+        Layout,
+        Fields,
+    };
 
     DocumentTimerManager( SwDoc& i_rSwdoc );
+    virtual ~DocumentTimerManager() override;
 
     void StartIdling() override;
 
@@ -47,15 +56,16 @@ public:
 
     void StartBackgroundJobs() override;
 
-    DECL_LINK( DoIdleJobs, Timer *, void );
-
-    virtual ~DocumentTimerManager() override;
+    bool IsDocIdle() const override;
 
 private:
-
     DocumentTimerManager(DocumentTimerManager const&) = delete;
     DocumentTimerManager& operator=(DocumentTimerManager const&) = delete;
 
+    DECL_LINK( DoIdleJobs, Timer *, void );
+
+    IdleJob GetNextIdleJob() const;
+
     SwDoc& m_rDoc;
 
     bool mbStartIdleTimer; //< idle timer mode start/stop
@@ -63,6 +73,11 @@ private:
     SwDocIdle maDocIdle;
 };
 
+inline bool DocumentTimerManager::IsDocIdle() const
+{
+    return( GetNextIdleJob() != IdleJob::Busy );
+}
+
 }
 
 #endif
diff --git a/sw/source/uibase/uiview/view0.cxx b/sw/source/uibase/uiview/view0.cxx
index 8f859fafd6c2..491017981728 100644
--- a/sw/source/uibase/uiview/view0.cxx
+++ b/sw/source/uibase/uiview/view0.cxx
@@ -524,7 +524,7 @@ void SwView::ExecViewOptions(SfxRequest &rReq)
                 aCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bIsAutoGrammar;
 
                 if (pDoc && bIsAutoGrammar)
-                    StartGrammarChecking( *pDoc );
+                    pDoc->StartGrammarChecking();
             }
         }
         break;
commit ce40eb9db992472565e893bb6260bd7cf9ce89a6
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Sep 29 22:24:15 2017 +0200

    WIP Fix unprocessed shutdown events
    
    DO NOT MERGE!
    
    This is just a test patch, since I can't reproduce the
    Jenkins failures locally. It's not "make check" tested,
    just "make vcl".
    
    This fixes multiple problems, which I missed.
    
    We're not interested in WM_TIMER events, but in active
    SAL_MSG_TIMER_CALLBACK, which is indicated by PollForMessage().
    
    This includes a revert of "tdf#38915: don't wait on message queue
    if application already has quit.", which is commited as
    f054b9187155bc32b7d06808aea87127cb0a3a4f.
    
    We can't ignore the wait flag, just because the application will
    quit, as we have to deliver the expected event announced by
    pTimer->PollForMessage().
    
    And we don't try to "clean" the message queue, as invalid events
    are simply identified by there version ID.
    
    On Mac we can probably drop the workaround. We can't wait for a
    timer event in a redirected dispatch_async, for whatever reason.
    
    Change-Id: If806d41c6fcfce10b0c4c7fdcf1df5df6ac16a1d

diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index 5ad6a1718f19..532765e050f0 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -34,7 +34,7 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent
 
     void ImplStart( sal_uIntPtr nMS );
     void ImplStop();
-    void ImplEmitTimerCallback();
+    void ImplHandleTimerEvent( WPARAM aWPARAM );
 
 public:
     WinSalTimer();
@@ -43,16 +43,9 @@ public:
     virtual void Start(sal_uIntPtr nMS) override;
     virtual void Stop() override;
 
-    inline bool IsValidWPARAM( WPARAM wParam ) const;
-
     inline bool PollForMessage() const;
 };
 
-inline bool WinSalTimer::IsValidWPARAM( WPARAM aWPARAM ) const
-{
-    return IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) );
-}
-
 inline bool WinSalTimer::PollForMessage() const
 {
     return m_bPollForMessage;
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index d475f30275b0..0334087f57cf 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -570,10 +570,10 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
         // handle available events
         NSEvent* pEvent = nil;
         NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
+        AquaSalInstance *pInst = GetSalData()->mpInstance;
         do
         {
             SolarMutexReleaser aReleaser;
-
 SAL_WNODEPRECATED_DECLARATIONS_PUSH
     // 'NSAnyEventMask' is deprecated: first deprecated in macOS 10.12
             pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask
@@ -591,6 +591,8 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
 
             [NSApp updateWindows];
 
+            if ( AquaSalInstance::AnyInput( VclInputFlags::TIMER ) && !pInst->mbNoYieldLock && !bHadEvent )
+                continue;
             if ( !bHandleAllCurrentEvents || !pEvent || now < [pEvent timestamp] )
                 break;
         }
@@ -618,7 +620,7 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         }
 
         // collect update rectangles
-        for( auto pSalFrame : GetSalData()->mpInstance->getFrames() )
+        for( auto pSalFrame : pInst->getFrames() )
         {
             AquaSalFrame* pFrame = static_cast<AquaSalFrame*>( pSalFrame );
             if( pFrame->mbShown && ! pFrame->maInvalidRect.IsEmpty() )
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 877fdfae85b5..e6336fbedd6e 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -44,30 +44,8 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
                                subtype: nEventId
                                data1: nUserData
                                data2: 0];
-    assert( pEvent );
     if ( nil == pEvent )
-        return;
-    if ( NO == bAtStart )
-    {
-        // nextEventMatchingMask has to run in the main thread!
-        assert([NSThread isMainThread]);
-
-        // Posting an event to the end of an empty queue fails,
-        // so we peek the queue and post to the start, if empty.
-        // Some Qt bugs even indicate nextEvent without dequeue
-        // sometimes blocks, so we dequeue and re-add the event.
-SAL_WNODEPRECATED_DECLARATIONS_PUSH
-// 'NSAnyEventMask' is deprecated: first deprecated in macOS 10.12
-        NSEvent* pPeekEvent = [NSApp nextEventMatchingMask: NSAnyEventMask
-SAL_WNODEPRECATED_DECLARATIONS_POP
-                               untilDate: nil
-                               inMode: NSDefaultRunLoopMode
-                               dequeue: YES];
-        if ( nil == pPeekEvent )
-            bAtStart = YES;
-        else
-            [NSApp postEvent: pPeekEvent atStart: YES];
-    }
+        std::abort();
     [NSApp postEvent: pEvent atStart: bAtStart];
 }
 
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 5c1b1bc8f5f4..92db1e23563a 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -171,7 +171,7 @@ void Scheduler::ImplDeInitScheduler()
     SAL_INFO( "vcl.schedule.deinit", "DeInit the scheduler - finished" );
     SAL_WARN_IF( 0 != nActiveTasks, "vcl.schedule.deinit", "DeInit active tasks: "
         << nActiveTasks << " (ignored: " << nIgnoredTasks << ")" );
-//    assert( nIgnoredTasks == nActiveTasks );
+    assert( nIgnoredTasks == nActiveTasks );
 #endif
 
     rSchedCtx.mpFirstSchedulerData = nullptr;
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index a0a323b2d037..1eb8b4a04bfb 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -514,8 +514,7 @@ static bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
     if ( bHandleAllCurrentEvents )
         nLastTicks = nCurTicks;
 
-    // Also check that we don't wait when application already has quit
-    if ( bWait && !bWasMsg && !pSVData->maAppData.mbAppQuit )
+    if ( bWait && !bWasMsg )
     {
         if ( GetMessageW( &aMsg, nullptr, 0, 0 ) )
         {
@@ -540,8 +539,6 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
     SolarMutexReleaser aReleaser;
     if ( !IsMainThread() )
     {
-        // If you change the SendMessageW function, you might need to update
-        // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
         bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
                                  (WPARAM) false, (LPARAM) bHandleAllCurrentEvents );
         if ( !bDidWork && bWait )
@@ -659,17 +656,7 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
         {
             WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
-            MSG aMsg;
-            bool bValidMSG = pTimer->IsValidWPARAM( wParam );
-            // PM_QS_POSTMESSAGE is needed, so we don't process the SendMessage from DoYield!
-            while ( PeekMessageW(&aMsg, pInst->mhComWnd, SAL_MSG_TIMER_CALLBACK,
-                                 SAL_MSG_TIMER_CALLBACK, PM_REMOVE | PM_NOYIELD | PM_QS_POSTMESSAGE) )
-            {
-                assert( !bValidMSG && "Unexpected non-last valid message" );
-                bValidMSG = pTimer->IsValidWPARAM( aMsg.wParam );
-            }
-            if ( bValidMSG )
-                pTimer->ImplEmitTimerCallback();
+            pTimer->ImplHandleTimerEvent( wParam );
             break;
         }
     }
@@ -700,6 +687,13 @@ bool WinSalInstance::AnyInput( VclInputFlags nType )
 {
     MSG aMsg;
 
+    if ( nType & VclInputFlags::TIMER )
+    {
+        const WinSalTimer* pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
+        if ( pTimer && pTimer->PollForMessage() )
+            return true;
+    }
+
     if ( (nType & VCL_INPUT_ANY) == VCL_INPUT_ANY )
     {
         // revert bugfix for #108919# which never reported timeouts when called from the timer handler
@@ -756,15 +750,6 @@ bool WinSalInstance::AnyInput( VclInputFlags nType )
                 return true;
         }
 
-        if ( nType & VclInputFlags::TIMER )
-        {
-            // Test for timer input
-            if ( PeekMessageW( &aMsg, nullptr, WM_TIMER, WM_TIMER,
-                                  PM_NOREMOVE | PM_NOYIELD ) )
-                return true;
-
-        }
-
         if ( nType & VclInputFlags::OTHER )
         {
             // Test for any input
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 93b93fbb832f..8354886fbcd6 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -50,12 +50,6 @@ void WinSalTimer::ImplStop()
     // Keep both after DeleteTimerQueueTimer, because they are set in SalTimerProc
     InvalidateEvent();
     m_bPollForMessage = false;
-
-    // remove as many pending SAL_MSG_TIMER_CALLBACK messages as possible
-    // PM_QS_POSTMESSAGE is needed, so we don't process the SendMessage from DoYield!
-    MSG aMsg;
-    while ( PeekMessageW(&aMsg, pInst->mhComWnd, SAL_MSG_TIMER_CALLBACK,
-                         SAL_MSG_TIMER_CALLBACK, PM_REMOVE | PM_NOYIELD | PM_QS_POSTMESSAGE) );
 }
 
 void WinSalTimer::ImplStart( sal_uLong nMS )
@@ -75,9 +69,7 @@ void WinSalTimer::ImplStart( sal_uLong nMS )
     // probably WT_EXECUTEONLYONCE is not needed, but it enforces Period
     // to be 0 and should not hurt; also see
     // https://www.microsoft.com/msj/0499/pooling/pooling.aspx
-    CreateTimerQueueTimer(&m_nTimerId, nullptr, SalTimerProc,
-                          reinterpret_cast<void*>(
-                              sal_IntPtr(GetNextEventVersion())),
+    CreateTimerQueueTimer(&m_nTimerId, nullptr, SalTimerProc, this,
                           nMS, 0, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
 }
 
@@ -126,12 +118,11 @@ void CALLBACK SalTimerProc(PVOID data, BOOLEAN)
 {
     __try
     {
-        // always post message when the timer fires, we will remove the ones
-        // that happened during execution of the callback later directly from
-        // the message queue
-        BOOL const ret = PostMessageW(GetSalData()->mpInstance->mhComWnd,
-                                      SAL_MSG_TIMER_CALLBACK,
-                                      reinterpret_cast<WPARAM>(data), 0);
+        WinSalTimer *pTimer = reinterpret_cast<WinSalTimer*>( data );
+        pTimer->m_bPollForMessage = true;
+        BOOL const ret = PostMessageW(
+            GetSalData()->mpInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK,
+            static_cast<WPARAM>(pTimer->GetNextEventVersion()), 0 );
 #if OSL_DEBUG_LEVEL > 0
         if (0 == ret) // SEH prevents using SAL_WARN here?
             fputs("ERROR: PostMessage() failed!\n", stderr);
@@ -142,8 +133,12 @@ void CALLBACK SalTimerProc(PVOID data, BOOLEAN)
     }
 }
 
-void WinSalTimer::ImplEmitTimerCallback()
+void WinSalTimer::ImplHandleTimerEvent( WPARAM aWPARAM )
 {
+    assert( aWPARAM <= SAL_MAX_INT32 );
+    if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) )
+        return;
+
     // Test for MouseLeave
     SalTestMouseLeave();
 
commit 62fc21675ccbfa5dcadbb2407729b804aac75ae2
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Oct 6 09:32:23 2017 +0100

    coverity#1418961 Uninitialized scalar field
    
    Change-Id: I84692e07f3887c8440df535c2c0c1191cd2773be
    Reviewed-on: https://gerrit.libreoffice.org/43188
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index e8f11d4b0c9b..0f227b18ef5f 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -230,6 +230,8 @@ ScTabView::ScTabView( vcl::Window* pParent, ScDocShell& rDocSh, ScTabViewShell*
     mfPendingTabBarWidth( -1.0 ),
     mnLOKStartHeaderRow( std::numeric_limits<SCROW>::min() ),
     mnLOKEndHeaderRow( std::numeric_limits<SCROW>::min() ),
+    mnLOKStartHeaderCol( std::numeric_limits<SCCOL>::min() ),
+    mnLOKEndHeaderCol( std::numeric_limits<SCCOL>::min() ),
     bMinimized( false ),
     bInUpdateHeader( false ),
     bInActivatePart( false ),
commit aacf28c8ab48ca969308a2fb1bdff32e159228db
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Fri Oct 6 12:04:39 2017 +0200

    Revert "remove handing of deprecated Storage path option"
    
    This reverts commit b71fdc67ed1efd421b9b1c747708958e8e09f73c.
    
    since Jochen indicates that there is a bug in it
    
    Change-Id: I786a7885a308cb43b99d9930ed385a75bbcd9495
    Reviewed-on: https://gerrit.libreoffice.org/43192
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/include/unotools/pathoptions.hxx b/include/unotools/pathoptions.hxx
index 99791e5cc0fc..37e172632298 100644
--- a/include/unotools/pathoptions.hxx
+++ b/include/unotools/pathoptions.hxx
@@ -56,6 +56,7 @@ public:
         PATH_MODULE,
         PATH_PALETTE,
         PATH_PLUGIN,
+        PATH_STORAGE,
         PATH_TEMP,
         PATH_TEMPLATE,
         PATH_USERCONFIG,
@@ -87,6 +88,7 @@ public:
     const OUString& GetModulePath() const;
     const OUString& GetPalettePath() const;
     const OUString& GetPluginPath() const;
+    const OUString& GetStoragePath() const;
     const OUString& GetTempPath() const;
     const OUString& GetTemplatePath() const;
     const OUString& GetUserConfigPath() const;
@@ -112,6 +114,7 @@ public:
     void            SetModulePath( const OUString& rPath );
     void            SetPalettePath( const OUString& rPath );
     void            SetPluginPath( const OUString& rPath );
+    void            SetStoragePath( const OUString& rPath );
     void            SetTempPath( const OUString& rPath );
     void            SetTemplatePath( const OUString& rPath );
     void            SetUserConfigPath( const OUString& rPath );
diff --git a/sfx2/source/appl/appcfg.cxx b/sfx2/source/appl/appcfg.cxx
index 27ec3ad2f1df..7153cf17b4d1 100644
--- a/sfx2/source/appl/appcfg.cxx
+++ b/sfx2/source/appl/appcfg.cxx
@@ -433,6 +433,7 @@ void SfxApplication::GetOptions( SfxItemSet& rSet )
                             case SvtPathOptions::PATH_MODULE:       osl::FileBase::getFileURLFromSystemPath( aPathCfg.GetModulePath(), aValue ); break;
                             case SvtPathOptions::PATH_PALETTE:      aValue = aPathCfg.GetPalettePath(); break;
                             case SvtPathOptions::PATH_PLUGIN:       osl::FileBase::getFileURLFromSystemPath( aPathCfg.GetPluginPath(), aValue ); break;
+                            case SvtPathOptions::PATH_STORAGE:      osl::FileBase::getFileURLFromSystemPath( aPathCfg.GetStoragePath(), aValue ); break;
                             case SvtPathOptions::PATH_TEMP:         aValue = aPathCfg.GetTempPath(); break;
                             case SvtPathOptions::PATH_TEMPLATE:     aValue = aPathCfg.GetTemplatePath(); break;
                             case SvtPathOptions::PATH_USERCONFIG:   aValue = aPathCfg.GetUserConfigPath(); break;
@@ -790,6 +791,14 @@ void SfxApplication::SetOptions(const SfxItemSet &rSet)
                         break;
                     }
 
+                    case SvtPathOptions::PATH_STORAGE:
+                    {
+                        OUString aTmp;
+                        if( osl::FileBase::getSystemPathFromFileURL( sValue, aTmp ) == osl::FileBase::E_None )
+                            aPathOptions.SetStoragePath( aTmp );
+                        break;
+                    }
+
                     case SvtPathOptions::PATH_TEMP:         aPathOptions.SetTempPath( sValue );break;
                     case SvtPathOptions::PATH_TEMPLATE:     aPathOptions.SetTemplatePath( sValue );break;
                     case SvtPathOptions::PATH_USERCONFIG:   aPathOptions.SetUserConfigPath( sValue );break;
diff --git a/svtools/source/misc/templatefoldercache.cxx b/svtools/source/misc/templatefoldercache.cxx
index ab3db5afa563..f83e11dcdf0a 100644
--- a/svtools/source/misc/templatefoldercache.cxx
+++ b/svtools/source/misc/templatefoldercache.cxx
@@ -691,20 +691,20 @@ namespace svt
         // close any old stream instance
         closeCacheStream( );
 
-        // get the temp directory
-        OUString sTempURL = implParseSmart( SvtPathOptions().GetTempPath() );
-        INetURLObject aTempURL( sTempURL );
-        if ( INetProtocol::NotValid == aTempURL.GetProtocol() )
+        // get the storage directory
+        OUString sStorageURL = implParseSmart( SvtPathOptions().GetStoragePath() );
+        INetURLObject aStorageURL( sStorageURL );
+        if ( INetProtocol::NotValid == aStorageURL.GetProtocol() )
         {
-            OSL_FAIL( "TemplateFolderCacheImpl::openCacheStream: invalid temp path!" );
+            OSL_FAIL( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" );
             return false;
         }
 
         // append our name
-        aTempURL.Append( ".templdir.cache" );
+        aStorageURL.Append( ".templdir.cache" );
 
         // open the stream
-        m_pCacheStream = UcbStreamHelper::CreateStream( aTempURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ),
+        m_pCacheStream = UcbStreamHelper::CreateStream( aStorageURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ),
             _bForRead ? StreamMode::READ | StreamMode::NOCREATE : StreamMode::WRITE | StreamMode::TRUNC );
         DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" );
         if ( m_pCacheStream && m_pCacheStream->GetErrorCode() )
diff --git a/unotools/source/config/pathoptions.cxx b/unotools/source/config/pathoptions.cxx
index d68d4da44c5b..998ff53d0072 100644
--- a/unotools/source/config/pathoptions.cxx
+++ b/unotools/source/config/pathoptions.cxx
@@ -112,6 +112,7 @@ class SvtPathOptions_Impl
         const OUString& GetModulePath() { return GetPath( SvtPathOptions::PATH_MODULE ); }
         const OUString& GetPalettePath() { return GetPath( SvtPathOptions::PATH_PALETTE ); }
         const OUString& GetPluginPath() { return GetPath( SvtPathOptions::PATH_PLUGIN ); }
+        const OUString& GetStoragePath() { return GetPath( SvtPathOptions::PATH_STORAGE ); }
         const OUString& GetTempPath() { return GetPath( SvtPathOptions::PATH_TEMP ); }
         const OUString& GetTemplatePath() { return GetPath( SvtPathOptions::PATH_TEMPLATE ); }
         const OUString& GetUserConfigPath() { return GetPath( SvtPathOptions::PATH_USERCONFIG ); }
@@ -139,6 +140,7 @@ class SvtPathOptions_Impl
         void            SetModulePath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_MODULE, rPath ); }
         void            SetPalettePath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_PALETTE, rPath ); }
         void            SetPluginPath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_PLUGIN, rPath ); }
+        void            SetStoragePath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_STORAGE, rPath ); }
         void            SetTempPath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_TEMP, rPath ); }
         void            SetTemplatePath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_TEMPLATE, rPath ); }
         void            SetUserConfigPath( const OUString& rPath ) { SetPath( SvtPathOptions::PATH_USERCONFIG, rPath ); }
@@ -184,6 +186,7 @@ static const PropertyStruct aPropNames[] =
     { "Module",         SvtPathOptions::PATH_MODULE         },
     { "Palette",        SvtPathOptions::PATH_PALETTE        },
     { "Plugin",         SvtPathOptions::PATH_PLUGIN         },
+    { "Storage",        SvtPathOptions::PATH_STORAGE        },
     { "Temp",           SvtPathOptions::PATH_TEMP           },
     { "Template",       SvtPathOptions::PATH_TEMPLATE       },
     { "UserConfig",     SvtPathOptions::PATH_USERCONFIG     },
@@ -223,7 +226,8 @@ const OUString& SvtPathOptions_Impl::GetPath( SvtPathOptions::Paths ePath )
             ePath == SvtPathOptions::PATH_FILTER    ||
             ePath == SvtPathOptions::PATH_HELP      ||
             ePath == SvtPathOptions::PATH_MODULE    ||
-            ePath == SvtPathOptions::PATH_PLUGIN
+            ePath == SvtPathOptions::PATH_PLUGIN    ||
+            ePath == SvtPathOptions::PATH_STORAGE
           )
         {
             // These office paths have to be converted to system pates
@@ -274,6 +278,7 @@ void SvtPathOptions_Impl::SetPath( SvtPathOptions::Paths ePath, const OUString&
             case SvtPathOptions::PATH_HELP:
             case SvtPathOptions::PATH_MODULE:
             case SvtPathOptions::PATH_PLUGIN:
+            case SvtPathOptions::PATH_STORAGE:
             {
                 // These office paths have to be convert back to UCB-URL's
                 osl::FileBase::getFileURLFromSystemPath( rNewPath, aResult );
@@ -545,6 +550,11 @@ const OUString& SvtPathOptions::GetPluginPath() const
     return pImpl->GetPluginPath();
 }
 
+const OUString& SvtPathOptions::GetStoragePath() const
+{
+    return pImpl->GetStoragePath();
+}
+
 const OUString& SvtPathOptions::GetTempPath() const
 {
     return pImpl->GetTempPath();
@@ -655,6 +665,11 @@ void SvtPathOptions::SetPluginPath( const OUString& rPath )
     pImpl->SetPluginPath( rPath );
 }
 
+void SvtPathOptions::SetStoragePath( const OUString& rPath )
+{
+    pImpl->SetStoragePath( rPath );
+}
+
 void SvtPathOptions::SetTempPath( const OUString& rPath )
 {
     pImpl->SetTempPath( rPath );
@@ -753,6 +768,7 @@ bool SvtPathOptions::SearchFile( OUString& rIniFile, Paths ePath )
                 case PATH_MODULE:       aPath = GetModulePath();        break;
                 case PATH_PALETTE:      aPath = GetPalettePath();       break;
                 case PATH_PLUGIN:       aPath = GetPluginPath();        break;
+                case PATH_STORAGE:      aPath = GetStoragePath();       break;
                 case PATH_TEMP:         aPath = GetTempPath();          break;
                 case PATH_TEMPLATE:     aPath = GetTemplatePath();      break;
                 case PATH_WORK:         aPath = GetWorkPath();          break;
commit 05400958b0a06812fb38cf7644f30eebe2ab3768
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Fri Oct 6 12:52:05 2017 +0200

    disable constparams loplugin
    
    increases compile time too much, I will run this by hand periodically
    
    Change-Id: I118567ef294847ff609d4de771d998ce3b57161b

diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx
index 5ce9df2e5e2c..87a00ec488c3 100644
--- a/compilerplugins/clang/constparams.cxx
+++ b/compilerplugins/clang/constparams.cxx
@@ -571,7 +571,7 @@ bool ConstParams::isPointerOrReferenceToConst(const QualType& qt) {
     return false;
 }
 
-loplugin::Plugin::Registration< ConstParams > X("constparams", true);
+loplugin::Plugin::Registration< ConstParams > X("constparams", false);
 
 }
 
commit 38ccea5588f3c72ab0d76ef13e1371a414207700
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Fri Oct 6 10:44:29 2017 +0200

    Improve performance of loplugin:flatten
    
    ...by avoiding calls to parentStmt.
    
    Change-Id: I4f3d66a0529e9c3abf5c963bcf70db7a2afa1bf9

diff --git a/compilerplugins/clang/flatten.cxx b/compilerplugins/clang/flatten.cxx
index 7fa408ea1731..ce16bc2384ee 100644
--- a/compilerplugins/clang/flatten.cxx
+++ b/compilerplugins/clang/flatten.cxx
@@ -7,12 +7,13 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include "plugin.hxx"
 #include <cassert>
 #include <string>
 #include <iostream>
 #include <fstream>
 #include <set>
-#include "plugin.hxx"
+#include <stack>
 
 /**
   Look for places where we can flatten the control flow in a method by returning early.
@@ -30,7 +31,9 @@ public:
         TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
     }
 
+    bool TraverseIfStmt(IfStmt *);
     bool TraverseCXXCatchStmt(CXXCatchStmt * );
+    bool TraverseCompoundStmt(CompoundStmt *);
     bool VisitIfStmt(IfStmt const * );
 private:
     bool rewrite1(IfStmt const * );
@@ -40,8 +43,8 @@ private:
     std::string getSourceAsString(SourceRange range);
     std::string invertCondition(Expr const * condExpr, SourceRange conditionRange);
     bool checkOverlap(SourceRange);
-    bool lastStmtInParent(Stmt const * stmt);
 
+    std::stack<bool> mLastStmtInParentStack;
     std::vector<std::pair<char const *, char const *>> mvModifiedRanges;
 };
 
@@ -72,23 +75,30 @@ static bool containsVarDecl(Stmt const * stmt)
     return declStmt && isa<VarDecl>(*declStmt->decl_begin());
 }
 
-bool Flatten::lastStmtInParent(Stmt const * stmt)
+bool Flatten::TraverseCXXCatchStmt(CXXCatchStmt* )
 {
-    auto parent = parentStmt(stmt);
-    if (!parent) {
-        return true;
-    }
-    auto parentCompound = dyn_cast<CompoundStmt>(parent);
-    if (!parentCompound) {
+    // ignore stuff inside catch statements, where doing a "if...else..throw" is more natural
+    return true;
+}
+
+bool Flatten::TraverseIfStmt(IfStmt * ifStmt)
+{
+    // ignore if we are part of an if/then/else/if chain
+    if (ifStmt->getElse() && isa<IfStmt>(ifStmt->getElse()))
         return true;
-    }
-    return parentCompound->body_back() == stmt;
+    return RecursiveASTVisitor<Flatten>::TraverseIfStmt(ifStmt);
 }
 
-bool Flatten::TraverseCXXCatchStmt(CXXCatchStmt* )
+bool Flatten::TraverseCompoundStmt(CompoundStmt * compoundStmt)
 {
-    // ignore stuff inside catch statements, where doing a "if...else..throw" is more natural
-    return true;
+    // if the "if" statement is not the last statement in its block, and it contains
+    // var decls in its then block, we cannot de-indent the then block without
+    // extending the lifetime of some variables, which may be problematic
+    // ignore if we are part of an if/then/else/if chain
+    mLastStmtInParentStack.push(compoundStmt->size() > 0 && isa<IfStmt>(*compoundStmt->body_back()));
+    bool rv = RecursiveASTVisitor<Flatten>::TraverseCompoundStmt(compoundStmt);
+    mLastStmtInParentStack.pop();
+    return rv;
 }
 
 bool Flatten::VisitIfStmt(IfStmt const * ifStmt)
@@ -99,15 +109,6 @@ bool Flatten::VisitIfStmt(IfStmt const * ifStmt)
     if (!ifStmt->getElse())
         return true;
 
-    // ignore if/then/else/if chains for now
-    if (isa<IfStmt>(ifStmt->getElse()))
-        return true;
-
-    // ignore if we are part of an if/then/else/if chain
-    auto parentIfStmt = dyn_cast<IfStmt>(parentStmt(ifStmt));
-    if (parentIfStmt && parentIfStmt->getElse() == ifStmt)
-        return true;
-
     if (containsPreprocessingConditionalInclusion(ifStmt->getSourceRange())) {
         return true;
     }
@@ -118,10 +119,10 @@ bool Flatten::VisitIfStmt(IfStmt const * ifStmt)
         // if both the "if" and the "else" contain throws, no improvement
         if (containsSingleThrowExpr(ifStmt->getThen()))
             return true;
-        // if the "if" statement is not the last statement in it's block, and it contains
-        // var decls in it's then block, we cannot de-indent the then block without
+        // if the "if" statement is not the last statement in its block, and it contains
+        // var decls in its then block, we cannot de-indent the then block without
         // extending the lifetime of some variables, which may be problematic
-        if (!lastStmtInParent(ifStmt) && containsVarDecl(ifStmt->getThen()))
+        if (!mLastStmtInParentStack.top() || containsVarDecl(ifStmt->getThen()))
             return true;
 
         if (!rewrite1(ifStmt))
@@ -147,7 +148,7 @@ bool Flatten::VisitIfStmt(IfStmt const * ifStmt)
         // if the "if" statement is not the last statement in it's block, and it contains
         // var decls in it's else block, we cannot de-indent the else block without
         // extending the lifetime of some variables, which may be problematic
-        if (!lastStmtInParent(ifStmt) && containsVarDecl(ifStmt->getElse()))
+        if (!mLastStmtInParentStack.top() || containsVarDecl(ifStmt->getElse()))
             return true;
 
         if (!rewrite2(ifStmt))
diff --git a/compilerplugins/clang/test/flatten.cxx b/compilerplugins/clang/test/flatten.cxx
index a901d273b9a1..dcc7cb3b81c9 100644
--- a/compilerplugins/clang/test/flatten.cxx
+++ b/compilerplugins/clang/test/flatten.cxx
@@ -15,10 +15,16 @@ class Class {};
 
 void top1() {
     if (foo() == 1) { // expected-note {{if condition here [loplugin:flatten]}}
+        foo();
+    } else {
+        throw std::exception(); // expected-error {{unconditional throw in else branch, rather invert the condition, throw early, and flatten the normal case [loplugin:flatten]}}
+    }
+    // no warning expected
+    if (foo() == 1) {
         Class aClass;
         (void)aClass;
     } else {
-        throw std::exception(); // expected-error {{unconditional throw in else branch, rather invert the condition, throw early, and flatten the normal case [loplugin:flatten]}}
+        throw std::exception();
     }
 }
 
@@ -26,6 +32,12 @@ void top2() {
     if (foo() == 2) {
         throw std::exception(); // expected-error {{unconditional throw in then branch, just flatten the else [loplugin:flatten]}}
     } else {
+        foo();
+    }
+    // no warning expected
+    if (foo() == 2) {
+        throw std::exception();
+    } else {
         Class aClass;
         (void)aClass;
     }
@@ -77,4 +89,19 @@ int main() {
     }
 }
 
+void top6() {
+    // no warning expected
+    if (foo() == 2) {
+        Class aClass;
+        (void)aClass;
+    } else if (foo() == 2) {
+        Class aClass;
+        (void)aClass;
+    } else {
+        throw std::exception();
+    }
+    int x = 1;
+    (void)x;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
commit b86722d7470d00290ec4b3d5e0e8c65861570268
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Oct 6 09:36:48 2017 +0100

    coverity#1418965 Uninitialized scalar field
    
    and
    
    coverity#1418963 Uninitialized scalar field
    
    Change-Id: I16bd91d2dfe2a1ae3f4697b5ff67acf6b6a5ba1c
    Reviewed-on: https://gerrit.libreoffice.org/43189
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index d6160853b2c1..e8f11d4b0c9b 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2343,6 +2343,10 @@ public:
     BoundsProvider(ScDocument* pD, SCTAB nT)
         : pDoc(pD)
         , nTab(nT)
+        , nFirstIndex(-1)
+        , nSecondIndex(-1)
+        , nFirstPositionPx(-1)
+        , nSecondPositionPx(-1)
     {}
 
     void GetStartIndexAndPosition(index_type& nIndex, long& nPosition) const
commit 01e14d9d0bfabad8a75217712b430cf678de01a9
Author: jan Iversen <jani at libreoffice.org>
Date:   Fri Oct 6 12:21:35 2017 +0200

    iOS, undo patch for libxslt
    
    there is a new macro so that the patch is no longer needed
    
    Change-Id: I6a2c63566052def1d1d1ea2eb7cc8005453b01d1

diff --git a/external/libxslt/UnpackedTarball_libxslt.mk b/external/libxslt/UnpackedTarball_libxslt.mk
index 27be0ca3dccb..eae318ef74b9 100644
--- a/external/libxslt/UnpackedTarball_libxslt.mk
+++ b/external/libxslt/UnpackedTarball_libxslt.mk
@@ -19,7 +19,6 @@ $(eval $(call gb_UnpackedTarball_add_patches,libxslt,\
 	external/libxslt/libxslt-msvc.patch.2 \
 	external/libxslt/libxslt-1.1.26-memdump.patch \
 	external/libxslt/rpath.patch.0 \
-	external/libxslt/iOS.patch.0 \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/external/libxslt/iOS.patch.0 b/external/libxslt/iOS.patch.0
deleted file mode 100644
index ffd4a39a815a..000000000000
--- a/external/libxslt/iOS.patch.0
+++ /dev/null
@@ -1,20 +0,0 @@
---- config.sub
-+++ config.sub
-@@ -253,7 +253,7 @@
- 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- 	| am33_2.0 \
- 	| arc | arceb \
--	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
-+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] | arm64 \
- 	| avr | avr32 \
- 	| be32 | be64 \
- 	| bfin \
-@@ -374,7 +374,7 @@
- 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
--	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
-+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* | arm64-* \
- 	| avr-* | avr32-* \
- 	| be32-* | be64-* \
- 	| bfin-* | bs2000-* \
commit ecc3d43d2feb4ec09a3f797a4eb6d2eb25e5ee7f
Author: Maxim Monastirsky <momonasmon at gmail.com>
Date:   Fri Oct 6 00:28:08 2017 +0300

    Related: tdf#107569 Remove useless slots
    
    With the current implementation of MenuBarManager, there is
    no need to have sdi slots for menu items with submenus, and
    moreover they have no effect at all.
    
    Note that SID_PICKLIST was also (mis)used as an argument
    to avoid adding a document to the recent list (which isn't
    related to its mapping to .uno:PickList). But there seem to
    be only read attempts, nothing actually sets it, so I think
    this usage can be removed too. (For information, at least in
    OOo 1.0.3 sources, there were 2 places where it was used as
    an argument for SID_SAVEASDOC, although it was not present
    there in the SID_SAVEASDOC def. in sfx.sdi.)
    
    Change-Id: I18b0afe106f858406e13188bbc004ac99a3a0246
    Reviewed-on: https://gerrit.libreoffice.org/43184
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Maxim Monastirsky <momonasmon at gmail.com>

diff --git a/dbaccess/source/ui/tabledesign/TableController.cxx b/dbaccess/source/ui/tabledesign/TableController.cxx
index bfb16297c65c..c0d9ccbc4187 100644
--- a/dbaccess/source/ui/tabledesign/TableController.cxx
+++ b/dbaccess/source/ui/tabledesign/TableController.cxx
@@ -606,7 +606,6 @@ void OTableController::describeSupportedFeatures()
     implDescribeSupportedFeature( ".uno:Redo",          ID_BROWSER_REDO,        CommandGroup::EDIT );
     implDescribeSupportedFeature( ".uno:Save",          ID_BROWSER_SAVEDOC,     CommandGroup::EDIT );
     implDescribeSupportedFeature( ".uno:Undo",          ID_BROWSER_UNDO,        CommandGroup::EDIT );
-    implDescribeSupportedFeature( ".uno:HelpMenu",      SID_HELPMENU,           CommandGroup::APPLICATION );
     implDescribeSupportedFeature( ".uno:NewDoc",        SID_NEWDOC,             CommandGroup::DOCUMENT );
     implDescribeSupportedFeature( ".uno:SaveAs",        ID_BROWSER_SAVEASDOC,   CommandGroup::DOCUMENT );
     implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN,        CommandGroup::APPLICATION );
diff --git a/framework/source/fwe/classes/addonmenu.cxx b/framework/source/fwe/classes/addonmenu.cxx
index 90914fe2a44c..a044870378a8 100644
--- a/framework/source/fwe/classes/addonmenu.cxx
+++ b/framework/source/fwe/classes/addonmenu.cxx
@@ -38,10 +38,6 @@ using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::frame;
 using namespace ::com::sun::star::beans;
 
-// Please look at sfx2/inc/sfxsids.hrc the values are defined there. Due to build dependencies
-// we cannot include the header file.
-const sal_uInt16 SID_HELPMENU            = (SID_SFX_START + 410);
-
 namespace framework
 {
 
@@ -101,13 +97,10 @@ void AddonMenuManager::MergeAddonHelpMenu( const Reference< XFrame >& rFrame,
 {
     if ( pMergeMenuBar )
     {
-        PopupMenu* pHelpMenu = pMergeMenuBar->GetPopupMenu( SID_HELPMENU );
-        if ( !pHelpMenu )
-        {
-            sal_uInt16 nId = FindMenuId(pMergeMenuBar, ".uno:HelpMenu");
-            if ( nId != USHRT_MAX )
-                pHelpMenu = pMergeMenuBar->GetPopupMenu( nId );
-        }
+        PopupMenu* pHelpMenu(nullptr);
+        sal_uInt16 nId = FindMenuId(pMergeMenuBar, ".uno:HelpMenu");
+        if ( nId != USHRT_MAX )
+            pHelpMenu = pMergeMenuBar->GetPopupMenu( nId );
 
         if ( pHelpMenu )
         {
@@ -118,7 +111,7 @@ void AddonMenuManager::MergeAddonHelpMenu( const Reference< XFrame >& rFrame,
             AddonsOptions aOptions;
 
             // try to detect the about menu item with the command URL
-            sal_uInt16 nId = FindMenuId(pHelpMenu, ".uno:About");
+            nId = FindMenuId(pHelpMenu, ".uno:About");
             sal_uInt16 nInsPos = pHelpMenu->GetItemPos( nId );
 
             const Sequence< Sequence< PropertyValue > >& rAddonHelpMenuEntries = aOptions.GetAddonsHelpMenu();
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index 91baa6c56606..aa63549deaca 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -81,7 +81,7 @@
 #define SID_HELPTIPS                        (SID_SFX_START + 404)
 #define SID_EMOJI_CONTROL                   (SID_SFX_START + 405)
 #define SID_CHARMAP_CONTROL                 (SID_SFX_START + 406)
-#define SID_HELPMENU                        (SID_SFX_START + 410)
+// free                                     (SID_SFX_START + 410)
 #define SID_SEND_FEEDBACK                   (SID_SFX_START + 421)
 #define SID_Q_AND_A                         (SID_SFX_START + 422)
 #define SID_DOCUMENTATION                   (SID_SFX_START + 423)
@@ -119,7 +119,7 @@
 #define SID_FILE_FILTEROPTIONS              (SID_SFX_START + 527)
 #define SID_RELOAD                          (SID_SFX_START + 508)
 #define SID_PRINTDOCDIRECT                  (SID_SFX_START + 509)
-#define SID_PICKLIST                        (SID_SFX_START + 510)
+// free                                     (SID_SFX_START + 510)
 #define SID_DOC_SERVICE                     (SID_SFX_START + 511)
 #define SID_PLUGIN_MODE                     (SID_SFX_START + 827)
 #define SID_EXPORTDOC                       (SID_SFX_START + 829)
@@ -353,7 +353,7 @@
 
 // default-ids for windows
 
-#define SID_MDIWINDOWLIST                   (SID_SFX_START + 610)
+// free                                     (SID_SFX_START + 610)
 #define SID_NEWWINDOW                       (SID_SFX_START + 620)
 #define SID_CLOSEWIN                        (SID_SFX_START + 621)
 #define SID_VIEWSHELL                       (SID_SFX_START + 623)
diff --git a/reportdesign/source/ui/report/ReportController.cxx b/reportdesign/source/ui/report/ReportController.cxx
index e102bcd00160..26d6b738249b 100644
--- a/reportdesign/source/ui/report/ReportController.cxx
+++ b/reportdesign/source/ui/report/ReportController.cxx
@@ -1848,7 +1848,6 @@ void OReportController::describeSupportedFeatures()
     implDescribeSupportedFeature( ".uno:GreatestHeight",            SID_OBJECT_GREATESTHEIGHT,      CommandGroup::FORMAT );
     implDescribeSupportedFeature( ".uno:Distribution",              SID_DISTRIBUTION,               CommandGroup::FORMAT );
 
-    implDescribeSupportedFeature( ".uno:HelpMenu",                  SID_HELPMENU,                   CommandGroup::APPLICATION );
     implDescribeSupportedFeature( ".uno:ExportTo",                  SID_EXPORTDOC,                  CommandGroup::APPLICATION );
     implDescribeSupportedFeature( ".uno:ExportToPDF",               SID_EXPORTDOCASPDF,             CommandGroup::APPLICATION );
     implDescribeSupportedFeature( ".uno:PrintPreview",              SID_PRINTPREVIEW,               CommandGroup::APPLICATION );
diff --git a/sfx2/sdi/appslots.sdi b/sfx2/sdi/appslots.sdi
index 5f228a2ff137..da6d084403fe 100644
--- a/sfx2/sdi/appslots.sdi
+++ b/sfx2/sdi/appslots.sdi
@@ -21,15 +21,6 @@ interface Application
     SID_AUTOPILOTMENU // ole(no) api(final/play/rec)
     [
     ]
-    SID_HELPMENU // ole(no) api(no)
-    [
-    ]
-    SID_PICKLIST // ole(no) api(no)
-    [
-    ]
-    SID_MDIWINDOWLIST // ole(no) api(no)
-    [
-    ]
     SID_ABOUT // ole(no) api(final/play/rec)
     [
         ExecMethod = MiscExec_Impl ;
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index bb32b9745c71..26265ed57bbf 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -1834,24 +1834,6 @@ SfxVoidItem HelpIndex SID_HELPINDEX
 ]
 
 
-SfxVoidItem HelpMenu SID_HELPMENU
-()
-[
-    AutoUpdate = FALSE,
-    FastCall = FALSE,
-    ReadOnlyDoc = TRUE,
-    Toggle = FALSE,
-    Container = FALSE,
-    RecordAbsolute = FALSE,
-    RecordPerSet;
-
-    AccelConfig = FALSE,
-    MenuConfig = TRUE,
-    ToolBoxConfig = FALSE,
-    GroupId = SfxGroupId::Application;
-]
-
-
 SfxBoolItem HelpTip SID_HELPTIPS
 
 [
@@ -3127,24 +3109,6 @@ SfxStringItem DocPath SID_DOCPATH
 ]
 
 
-SfxVoidItem PickList SID_PICKLIST
-()
-[
-    AutoUpdate = FALSE,
-    FastCall = FALSE,
-    ReadOnlyDoc = TRUE,
-    Toggle = FALSE,
-    Container = TRUE,
-    RecordAbsolute = FALSE,
-    RecordPerSet;
-
-    AccelConfig = FALSE,
-        MenuConfig = FALSE,
-    ToolBoxConfig = FALSE,
-    GroupId = SfxGroupId::Application;
-]
-
-
 SfxVoidItem Print SID_PRINTDOC
 (SfxStringItem PrinterName SID_PRINTER_NAME,SfxStringItem FileName SID_FILE_NAME,SfxInt16Item Copies SID_PRINT_COPIES,SfxStringItem RangeText SID_PRINT_PAGES,SfxBoolItem Selection SID_SELECTION,SfxBoolItem Asynchron SID_ASYNCHRON,SfxBoolItem Collate SID_PRINT_COLLATE,SfxBoolItem Silent SID_SILENT)
 [
@@ -4617,24 +4581,6 @@ SfxBoolItem ViewDataSourceBrowser SID_VIEW_DATA_SOURCE_BROWSER
     GroupId = SfxGroupId::View;
 ]
 
-SfxVoidItem WindowList SID_MDIWINDOWLIST
-()
-[
-    AutoUpdate = FALSE,
-    FastCall = FALSE,
-    ReadOnlyDoc = TRUE,
-    Toggle = FALSE,
-    Container = TRUE,
-    RecordAbsolute = FALSE,
-    RecordPerSet;
-
-    AccelConfig = FALSE,
-    MenuConfig = FALSE,
-    ToolBoxConfig = FALSE,
-    GroupId = SfxGroupId::View;
-]
-
-
 SfxVoidItem ZoomMinus SID_ZOOM_IN
 ()
 [
diff --git a/sfx2/source/appl/sfxpicklist.cxx b/sfx2/source/appl/sfxpicklist.cxx
index 4509e7299c91..ab41cf07ffda 100644
--- a/sfx2/source/appl/sfxpicklist.cxx
+++ b/sfx2/source/appl/sfxpicklist.cxx
@@ -117,14 +117,10 @@ void SfxPickListImpl::AddDocumentToPickList( SfxObjectShell* pDocSh )
     if ( aURL.GetProtocol() == INetProtocol::VndSunStarHelp )
         return;
 
+    // add no document that forbids this
     if ( !pMed->IsUpdatePickList() )
         return;
 
-    // add no document that forbids this (for example Message-Body)
-    const SfxBoolItem* pPicklistItem = SfxItemSet::GetItem<SfxBoolItem>(pMed->GetItemSet(), SID_PICKLIST, false);
-    if ( pPicklistItem && !pPicklistItem->GetValue() )
-        return;
-
     // ignore hidden documents
     if ( !SfxViewFrame::GetFirst( pDocSh ) )
         return;
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 18ec45205a50..2a757e4b4512 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -817,12 +817,6 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
     // Prevent entry in the Pick-lists
     if ( rReq.IsAPI() )
         GetMedium()->SetUpdatePickList( false );
-    else if ( rReq.GetArgs() )
-    {
-        const SfxBoolItem* pPicklistItem = rReq.GetArgs()->GetItem<SfxBoolItem>(SID_PICKLIST, false);
-        if ( pPicklistItem )
-            GetMedium()->SetUpdatePickList( pPicklistItem->GetValue() );
-    }
 
     // Ignore()-branches have already returned
     rReq.Done();
commit f1ad49892d983e67244b9d65033dcecda6c28e19
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Oct 6 09:19:04 2017 +0200

    xmlsecurity: last 2 params of setSAXChainConnector() is always nullptr
    
    So remove them.
    
    Change-Id: Iec2430af6634608bdc8c4beff6078ccceb7a2391
    Reviewed-on: https://gerrit.libreoffice.org/43182
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx
index 5e8cdb6ccfe7..3abd31d9d75d 100644
--- a/xmlsecurity/inc/xsecctl.hxx
+++ b/xmlsecurity/inc/xsecctl.hxx
@@ -339,10 +339,7 @@ public:
         const css::uno::Reference<
             css::xml::crypto::XXMLSecurityContext >& xSecurityContext );
 
-    void setSAXChainConnector(
-        const css::uno::Reference< css::lang::XInitialization >& xInitialization,
-        const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler,
-        const css::uno::Reference< css::xml::crypto::sax::XElementStackKeeper >& xElementStackKeeper);
+    void setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization);
 
     void clearSAXChainConnector();
     void endMission();
diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx
index 616ffcfb2ae4..767c55fe1e87 100644
--- a/xmlsecurity/source/helper/xsecctl.cxx
+++ b/xmlsecurity/source/helper/xsecctl.cxx
@@ -474,10 +474,7 @@ void XSecController::startMission(
     m_bVerifyCurrentSignature = false;
 }
 
-void XSecController::setSAXChainConnector(
-    const cssu::Reference< cssl::XInitialization >& xInitialization,
-    const cssu::Reference< cssxs::XDocumentHandler >& xDocumentHandler,
-    const cssu::Reference< cssxc::sax::XElementStackKeeper >& xElementStackKeeper)
+void XSecController::setSAXChainConnector(const cssu::Reference< cssl::XInitialization >& xInitialization)
 /****** XSecController/setSAXChainConnector ***********************************
  *
  *   NAME
@@ -485,21 +482,16 @@ void XSecController::setSAXChainConnector(
  *  collaborate with the SAXEventKeeper on the SAX chain.
  *
  *   SYNOPSIS
- *  setSAXChainConnector( xInitialization,
- *                        xDocumentHandler,
- *                        xElementStackKeeper );
+ *  setSAXChainConnector(xInitialization);
  *
  *   INPUTS
  *  xInitialization     - the previous node on the SAX chain
- *  xDocumentHandler    - the next node on the SAX chain
- *  xElementStackKeeper - the ElementStackKeeper component which reserves
- *                        missed key SAX events for the SAXEventKeeper
  ******************************************************************************/
 {
     m_bIsPreviousNodeInitializable = true;
     m_xPreviousNodeOnSAXChain = xInitialization;
-    m_xNextNodeOnSAXChain = xDocumentHandler;
-    m_xElementStackKeeper = xElementStackKeeper;
+    m_xNextNodeOnSAXChain.clear();
+    m_xElementStackKeeper.clear();
 
     initializeSAXChain( );
 }
diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx
index 3ec123bc4029..b4f8158b7c6c 100644
--- a/xmlsecurity/source/helper/xsecverify.cxx
+++ b/xmlsecurity/source/helper/xsecverify.cxx
@@ -466,7 +466,7 @@ cssu::Reference< cssxs::XDocumentHandler > const & XSecController::createSignatu
         m_xSecParser = new XSecParser(rXMLSignatureHelper, this);
     cssu::Reference< cssl::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY);
 
-    setSAXChainConnector(xInitialization, nullptr, nullptr);
+    setSAXChainConnector(xInitialization);
 
     return m_xSecParser;
 }
commit b94eb50b2e28604b1b9b363dc5f0b1c04490addf
Author: Andras Timar <andras.timar at collabora.com>
Date:   Fri Oct 6 10:41:25 2017 +0200

    Updated core
    Project: help  0f0c9fd543e5ceb5ae6d0a823997bd009b549753
    
    remove empty strings (helpex warned)
    
    Change-Id: I96a78fe8bf7f98b9728ddeeb4fa8b2ec622ab276

diff --git a/helpcontent2 b/helpcontent2
index 62a89b1d32a3..0f0c9fd543e5 160000
--- a/helpcontent2
+++ b/helpcontent2
@@ -1 +1 @@
-Subproject commit 62a89b1d32a3b230f3094075002cf2162934e4f4
+Subproject commit 0f0c9fd543e5ceb5ae6d0a823997bd009b549753
commit 061321bbb54adf9b0df102cdfd7f956f97dcb6b9
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Oct 6 09:19:16 2017 +0100

    coverity#1418966 static_cast should be sufficient
    
    Change-Id: Ieae8695cb36b1779f1b8437bddb887cd24d621e8

diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index 38509814f5b0..736722387122 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -427,7 +427,7 @@ void Control::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
         {
             if (pWindow->ImplIsFloatingWindow())
             {
-                dynamic_cast<FloatingWindow*>(pWindow)->LogicInvalidate(nullptr);
+                static_cast<FloatingWindow*>(pWindow)->LogicInvalidate(nullptr);
                 return;
             }
 
commit 7af521827e62aec9a695dce944d350fae7625b19
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Fri Oct 6 09:31:05 2017 +0200

    use rtl::Reference in mysqlc
    
    instead of manual ref-counting
    
    Change-Id: I7b7c350613976463620a54757add6061cf383a4c
    Reviewed-on: https://gerrit.libreoffice.org/43183
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/mysqlc/source/mysqlc_connection.cxx b/mysqlc/source/mysqlc_connection.cxx
index 1618bdcd85da..f44fca89e205 100644
--- a/mysqlc/source/mysqlc_connection.cxx
+++ b/mysqlc/source/mysqlc_connection.cxx
@@ -65,10 +65,9 @@ OConnection::OConnection(MysqlCDriver& _rDriver, sql::Driver * _cppDriver)
     :OMetaConnection_BASE(m_aMutex)
     ,OSubComponent<OConnection, OConnection_BASE>(static_cast<cppu::OWeakObject*>(&_rDriver), this)
     ,m_xMetaData(nullptr)
-    ,m_rDriver(_rDriver)
+    ,m_xDriver(&_rDriver)
     ,cppDriver(_cppDriver)
 {
-    m_rDriver.acquire();
 }
 
 OConnection::~OConnection()
@@ -76,7 +75,6 @@ OConnection::~OConnection()
     if (!isClosed()) {
         close();
     }
-    m_rDriver.release();
 }
 
 void SAL_CALL OConnection::release()
@@ -536,7 +534,7 @@ rtl::OUString OConnection::transFormPreparedStatement(const rtl::OUString& _sSQL
             Reference< XConnection> xCon = this;
             aArgs[0] <<= NamedValue(rtl::OUString("ActiveConnection"), makeAny(xCon));
 
-            m_xParameterSubstitution.set(m_rDriver.getFactory()->createInstanceWithArguments("org.openoffice.comp.helper.ParameterSubstitution",aArgs),UNO_QUERY);
+            m_xParameterSubstitution.set(m_xDriver->getFactory()->createInstanceWithArguments("org.openoffice.comp.helper.ParameterSubstitution",aArgs),UNO_QUERY);
         } catch(const Exception&) {}
     }
     if ( m_xParameterSubstitution.is() ) {
diff --git a/mysqlc/source/mysqlc_connection.hxx b/mysqlc/source/mysqlc_connection.hxx
index 5e62eff048d0..4ef6bb044a45 100644
--- a/mysqlc/source/mysqlc_connection.hxx
+++ b/mysqlc/source/mysqlc_connection.hxx
@@ -41,6 +41,7 @@
 #include <cppuhelper/compbase3.hxx>
 #include <cppuhelper/weakref.hxx>
 #include <rtl/string.hxx>
+#include <rtl/ref.hxx>
 
 #include <map>
 
@@ -104,7 +105,7 @@ namespace connectivity
                                             // of all the Statement objects
                                             // for this Connection
 
-            MysqlCDriver&   m_rDriver;      // Pointer to the owning driver object
+            rtl::Reference<MysqlCDriver> m_xDriver; // Pointer to the owning driver object
             sql::Driver*    cppDriver;
 
         public:
@@ -185,7 +186,7 @@ namespace connectivity
             const ConnectionSettings& getConnectionSettings() const { return m_settings; }
             rtl::OUString transFormPreparedStatement(const rtl::OUString& _sSQL);
 
-            const MysqlCDriver&  getDriver()         const { return m_rDriver;}
+            const MysqlCDriver&  getDriver()         const { return *m_xDriver.get();}
 
         }; /* OConnection */
         // TODO: Not used.
diff --git a/mysqlc/source/mysqlc_preparedstatement.cxx b/mysqlc/source/mysqlc_preparedstatement.cxx
index 84d353ef5873..ec5b6f68bdb0 100644
--- a/mysqlc/source/mysqlc_preparedstatement.cxx
+++ b/mysqlc/source/mysqlc_preparedstatement.cxx
@@ -75,13 +75,12 @@ sal_Bool OPreparedStatement::supportsService(rtl::OUString const & ServiceName)
 OPreparedStatement::OPreparedStatement(OConnection* _pConnection, sql::PreparedStatement * _cppPrepStmt)
     :OCommonStatement(_pConnection, _cppPrepStmt)
 {
-    m_pConnection = _pConnection;
-    m_pConnection->acquire();
+    m_xConnection = _pConnection;
 
     try {
         m_paramCount = static_cast<sql::PreparedStatement *>(cppStatement)->getParameterMetaData()->getParameterCount();
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -130,7 +129,7 @@ Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData()
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::getMetaData", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return m_xMetaData;
 }
@@ -161,7 +160,7 @@ sal_Bool SAL_CALL OPreparedStatement::execute()
     try {
         success = static_cast<sql::PreparedStatement *>(cppStatement)->execute();
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return success;
 }
@@ -175,7 +174,7 @@ sal_Int32 SAL_CALL OPreparedStatement::executeUpdate()
     try {
         affectedRows = static_cast<sql::PreparedStatement *>(cppStatement)->executeUpdate();
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return affectedRows;
 }
@@ -187,12 +186,12 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 parameter, const rtl::OUSt
     checkParameterIndex(parameter);
 
     try {
-        std::string stringie(rtl::OUStringToOString(x, m_pConnection->getConnectionEncoding()).getStr());
+        std::string stringie(rtl::OUStringToOString(x, m_xConnection->getConnectionEncoding()).getStr());
         static_cast<sql::PreparedStatement *>(cppStatement)->setString(parameter, stringie);
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::clearParameters", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -201,7 +200,7 @@ Reference< XConnection > SAL_CALL OPreparedStatement::getConnection()
     MutexGuard aGuard(m_aMutex);
     checkDisposed(OPreparedStatement::rBHelper.bDisposed);
 
-    return m_pConnection;
+    return m_xConnection.get();
 }
 
 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery()
@@ -214,7 +213,7 @@ Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery()
         sql::ResultSet * res = static_cast<sql::PreparedStatement *>(cppStatement)->executeQuery();
         xResultSet = new OResultSet(this, res, getOwnConnection()->getConnectionEncoding());
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return xResultSet;
 }
@@ -230,7 +229,7 @@ void SAL_CALL OPreparedStatement::setBoolean(sal_Int32 parameter, sal_Bool x)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setBoolean", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -245,7 +244,7 @@ void SAL_CALL OPreparedStatement::setByte(sal_Int32 parameter, sal_Int8 x)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setByte", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -268,7 +267,7 @@ void SAL_CALL OPreparedStatement::setDate(sal_Int32 parameter, const Date& aData
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setDate", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -291,7 +290,7 @@ void SAL_CALL OPreparedStatement::setTime(sal_Int32 parameter, const Time& aVal)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setTime", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -322,7 +321,7 @@ void SAL_CALL OPreparedStatement::setTimestamp(sal_Int32 parameter, const DateTi
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setTimestamp", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -337,7 +336,7 @@ void SAL_CALL OPreparedStatement::setDouble(sal_Int32 parameter, double x)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setDouble", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -352,7 +351,7 @@ void SAL_CALL OPreparedStatement::setFloat(sal_Int32 parameter, float x)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setFloat", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -367,7 +366,7 @@ void SAL_CALL OPreparedStatement::setInt(sal_Int32 parameter, sal_Int32 x)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setInt", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -382,7 +381,7 @@ void SAL_CALL OPreparedStatement::setLong(sal_Int32 parameter, sal_Int64 aVal)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setLong", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -397,7 +396,7 @@ void SAL_CALL OPreparedStatement::setNull(sal_Int32 parameter, sal_Int32 sqlType
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setNull", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -635,7 +634,7 @@ void SAL_CALL OPreparedStatement::setShort(sal_Int32 parameter, sal_Int16 x)
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setShort", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -651,7 +650,7 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 parameter, const Sequence<
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setBytes", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
@@ -687,7 +686,7 @@ void SAL_CALL OPreparedStatement::clearParameters()
     } catch (const sql::MethodNotImplementedException &) {
         mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::clearParameters", *this);
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
 }
 
diff --git a/mysqlc/source/mysqlc_statement.cxx b/mysqlc/source/mysqlc_statement.cxx
index 96ab88de79ee..0448ac5dcabc 100644
--- a/mysqlc/source/mysqlc_statement.cxx
+++ b/mysqlc/source/mysqlc_statement.cxx
@@ -56,10 +56,9 @@ OCommonStatement::OCommonStatement(OConnection* _pConnection, sql::Statement *_c
     :OCommonStatement_IBase(m_aMutex)
     ,OPropertySetHelper(OCommonStatement_IBase::rBHelper)
     ,OStatement_CBase( static_cast<cppu::OWeakObject*>(_pConnection), this )
-    ,m_pConnection(_pConnection)
+    ,m_xConnection(_pConnection)
     ,cppStatement(_cppStatement)
 {
-    m_pConnection->acquire();
 }
 
 OCommonStatement::~OCommonStatement()
@@ -79,10 +78,7 @@ void OCommonStatement::disposing()
 
     disposeResultSet();
 
-    if (m_pConnection) {
-        m_pConnection->release();
-        m_pConnection = nullptr;
-    }
+    m_xConnection.clear();
     delete cppStatement;
 
     dispose_ChildImpl();
@@ -136,13 +132,13 @@ sal_Bool SAL_CALL OCommonStatement::execute(const rtl::OUString& sql)
 {
     MutexGuard aGuard(m_aMutex);
     checkDisposed(rBHelper.bDisposed);
-    const rtl::OUString sSqlStatement = m_pConnection->transFormPreparedStatement( sql );
+    const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement( sql );
 
     bool success = false;
     try {
-        success = cppStatement->execute(rtl::OUStringToOString(sSqlStatement, m_pConnection->getConnectionSettings().encoding).getStr());
+        success = cppStatement->execute(rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionSettings().encoding).getStr());
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return success;
 }
@@ -151,15 +147,15 @@ Reference< XResultSet > SAL_CALL OCommonStatement::executeQuery(const rtl::OUStr
 {
     MutexGuard aGuard(m_aMutex);
     checkDisposed(rBHelper.bDisposed);
-    const rtl::OUString sSqlStatement = m_pConnection->transFormPreparedStatement(sql);
+    const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement(sql);
 
     Reference< XResultSet > xResultSet;
     try {
-        std::unique_ptr< sql::ResultSet > rset(cppStatement->executeQuery(rtl::OUStringToOString(sSqlStatement, m_pConnection->getConnectionEncoding()).getStr()));
-        xResultSet = new OResultSet(this, rset.get(), m_pConnection->getConnectionEncoding());
+        std::unique_ptr< sql::ResultSet > rset(cppStatement->executeQuery(rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionEncoding()).getStr()));
+        xResultSet = new OResultSet(this, rset.get(), m_xConnection->getConnectionEncoding());
         rset.release();
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return xResultSet;
 }
@@ -170,7 +166,7 @@ Reference< XConnection > SAL_CALL OCommonStatement::getConnection()
     checkDisposed(rBHelper.bDisposed);
 
     // just return our connection here
-    return m_pConnection;
+    return m_xConnection.get();
 }
 
 sal_Int32 SAL_CALL OCommonStatement::getUpdateCount()
@@ -206,13 +202,13 @@ sal_Int32 SAL_CALL OCommonStatement::executeUpdate(const rtl::OUString& sql)
 {
     MutexGuard aGuard(m_aMutex);
     checkDisposed(rBHelper.bDisposed);
-    const rtl::OUString sSqlStatement = m_pConnection->transFormPreparedStatement(sql);
+    const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement(sql);
 
     sal_Int32 affectedRows = 0;
     try {
-        affectedRows = cppStatement->executeUpdate(rtl::OUStringToOString(sSqlStatement, m_pConnection->getConnectionEncoding()).getStr());
+        affectedRows = cppStatement->executeUpdate(rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionEncoding()).getStr());
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return affectedRows;
 }
@@ -225,10 +221,10 @@ Reference< XResultSet > SAL_CALL OCommonStatement::getResultSet()
     Reference< XResultSet > xResultSet;
     try {
         std::unique_ptr< sql::ResultSet > rset(cppStatement->getResultSet());
-        xResultSet = new OResultSet(this, rset.get(), m_pConnection->getConnectionEncoding());
+        xResultSet = new OResultSet(this, rset.get(), m_xConnection->getConnectionEncoding());
         rset.release();
     } catch (const sql::SQLException &e) {
-        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
+        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding());
     }
     return xResultSet;
 }
diff --git a/mysqlc/source/mysqlc_statement.hxx b/mysqlc/source/mysqlc_statement.hxx
index 61d69e824dd7..4a9e754ce175 100644
--- a/mysqlc/source/mysqlc_statement.hxx
+++ b/mysqlc/source/mysqlc_statement.hxx
@@ -34,6 +34,7 @@
 
 #include <cppconn/statement.h>
 #include <cppuhelper/compbase5.hxx>
+#include <rtl/ref.hxx>
 
 namespace connectivity
 {
@@ -70,7 +71,7 @@ namespace connectivity
             SQLWarning m_aLastWarning;
 
         protected:
-            OConnection*            m_pConnection;  // The owning Connection object
+            rtl::Reference<OConnection> m_xConnection;  // The owning Connection object
 
             sql::Statement          *cppStatement;
 
@@ -142,7 +143,7 @@ namespace connectivity
             sal_Bool SAL_CALL getMoreResults() SAL_OVERRIDE;
 
             // other methods
-            OConnection* getOwnConnection() const { return m_pConnection;}
+            OConnection* getOwnConnection() const { return m_xConnection.get();}
 
         private:
             using ::cppu::OPropertySetHelper::getFastPropertyValue;
commit 4fc52078f6afa4368b2f4de3cd700e474b7a417f
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Oct 6 08:55:26 2017 +0200

    Improve performance of loplugin:commaoperator
    
    ...by avoiding calls to parentStmt, thereby also improving the precision of
    exactly which comma operators to ignore (which turned up a handful more finds).
    Also added tests.
    
    Change-Id: Ie74f824fd7f54131aab09b59086452fb4f3ff827
    Reviewed-on: https://gerrit.libreoffice.org/43181
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/compilerplugins/clang/commaoperator.cxx b/compilerplugins/clang/commaoperator.cxx
index c4a61e772281..c9efc09092de 100644
--- a/compilerplugins/clang/commaoperator.cxx
+++ b/compilerplugins/clang/commaoperator.cxx
@@ -20,6 +20,13 @@ the comma operator is best used sparingly
 
 namespace {
 
+Stmt const * lookThroughExprWithCleanups(Stmt const * stmt) {
+    if (auto const e = dyn_cast_or_null<ExprWithCleanups>(stmt)) {
+        return e->getSubExpr();
+    }
+    return stmt;
+}
+
 class CommaOperator:
     public RecursiveASTVisitor<CommaOperator>, public loplugin::Plugin
 {
@@ -31,11 +38,49 @@ public:
         TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
     }
 
-    bool VisitBinaryOperator(const BinaryOperator* );
+    bool TraverseForStmt(ForStmt * stmt) {
+        auto const saved1 = ignore1_;
+        ignore1_ = lookThroughExprWithCleanups(stmt->getInit());
+        auto const saved2 = ignore2_;
+        ignore2_ = lookThroughExprWithCleanups(stmt->getInc());
+        auto const ret = RecursiveASTVisitor::TraverseForStmt(stmt);
+        ignore1_ = saved1;
+        ignore2_ = saved2;
+        return ret;
+    }
+
+    bool TraverseParenExpr(ParenExpr * expr) {
+        auto const saved1 = ignore1_;
+        ignore1_ = expr->getSubExpr();
+        auto const ret = RecursiveASTVisitor::TraverseParenExpr(expr);
+        ignore1_ = saved1;
+        return ret;
+    }
+
+    bool TraverseBinComma(BinaryOperator * expr) {
+        if (!WalkUpFromBinComma(expr)) {
+            return false;
+        }
+        auto const saved1 = ignore1_;
+        ignore1_ = expr->getLHS();
+        auto const ret = TraverseStmt(expr->getLHS())
+            && TraverseStmt(expr->getRHS());
+        ignore1_ = saved1;
+        return ret;
+    }
+
+    bool VisitBinComma(const BinaryOperator* );
+
+private:
+    Stmt const * ignore1_ = nullptr;
+    Stmt const * ignore2_ = nullptr;
 };
 
-bool CommaOperator::VisitBinaryOperator(const BinaryOperator* binaryOp)
+bool CommaOperator::VisitBinComma(const BinaryOperator* binaryOp)
 {
+    if (binaryOp == ignore1_ || binaryOp == ignore2_) {
+        return true;
+    }
     if (ignoreLocation(binaryOp)) {
         return true;
     }
@@ -54,28 +99,6 @@ bool CommaOperator::VisitBinaryOperator(const BinaryOperator* binaryOp)
     {
         return true;
     }
-    if (binaryOp->getOpcode() != BO_Comma) {
-        return true;
-    }
-    const Stmt* parent = parentStmt(binaryOp);
-    if (parent != nullptr) {
-        if (isa<ParenExpr>(parent)) {
-            return true;
-        }
-        if (isa<BinaryOperator>(parent)) {
-            return true;
-        }
-        if (isa<ForStmt>(parent)) {
-            return true;
-        }
-        if (isa<ExprWithCleanups>(parent)) {
-            const Stmt* parent2 = parentStmt(parent);
-            if (isa<ForStmt>(parent2)) {
-                return true;
-            }
-        }
-    }
-//    parent->dump();
     report(
         DiagnosticsEngine::Warning, "comma operator hides code",
         binaryOp->getOperatorLoc())
diff --git a/compilerplugins/clang/test/commaoperator.cxx b/compilerplugins/clang/test/commaoperator.cxx
new file mode 100644
index 000000000000..199dcf41c243
--- /dev/null
+++ b/compilerplugins/clang/test/commaoperator.cxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+bool f();
+
+struct S { ~S(); };
+
+int main() {
+    f(), f(), f(); // expected-error {{comma operator hides code [loplugin:commaoperator]}}
+    (f(), f());
+    for (
+        f(), f();
+        f(), f(); // expected-error {{comma operator hides code [loplugin:commaoperator]}}
+        f(), f())
+        f(), f(); // expected-error {{comma operator hides code [loplugin:commaoperator]}}
+    S s;
+    (s = S(), s = S(), s = S());
+    for (s = S(), f(); f(); s = S(), f()) {}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/solenv/CompilerTest_compilerplugins_clang.mk b/solenv/CompilerTest_compilerplugins_clang.mk
index 0a1fc0f2ebfe..26306dccc983 100644
--- a/solenv/CompilerTest_compilerplugins_clang.mk
+++ b/solenv/CompilerTest_compilerplugins_clang.mk
@@ -13,6 +13,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
     compilerplugins/clang/test/badstatics \
     compilerplugins/clang/test/blockblock \
     compilerplugins/clang/test/casttovoid \
+    compilerplugins/clang/test/commaoperator \
     compilerplugins/clang/test/constparams \

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list