do not call GetFormatTable() from GetNonThreadedContext() (tdf#121949)

ScDocument dtor calls ClearLookupCaches(), which calls GetNonThreadedContext().
But ScDocument instances used for copy&paste GetFormatTable() fails
on null mxPoolHelper, because ScDocument ctor doesn't set it in such a case.
So set up the pointer in ScInterpreterContext on demand only if actually
needed.

Change-Id: If3811da5bb00a2d7d404c089ee1bf46037a2cddb
Reviewed-on: https://gerrit.libreoffice.org/68350
Tested-by: Jenkins
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
(cherry picked from commit b5c3f38cb8d4121e3303be362e0757d3d3431059)
Reviewed-on: https://gerrit.libreoffice.org/68539
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx
index 39b99e6..d25b842 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -201,6 +201,8 @@ public:
                    .Class("ScDocument").GlobalNamespace()) // not owning
                || name == "s_pLOKWindowsMap" // LOK only, guarded by assert, and LOK never tries to perform a VCL cleanup
                || name == "gStaticManager" // vcl/source/graphic/Manager.cxx - stores non-owning pointers
                || name == "aThreadedInterpreterPool"    // ScInterpreterContext(Pool), not owning
                || name == "aNonThreadedInterpreterPool" // ScInterpreterContext(Pool), not owning
               ) // these variables appear unproblematic
            {
                return true;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6a584b4..3fbe9cd 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -582,8 +582,7 @@ public:

    ScInterpreterContext& GetNonThreadedContext() const
    {
        // GetFormatTable() asserts that we are not in a threaded calculation
        maInterpreterContext.mpFormatter = GetFormatTable();
        assert(!IsThreadedGroupCalcInProgress());
        return maInterpreterContext;
    }
    // Uses thread_local.
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index e6a33de..176cfe12 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -809,7 +809,7 @@ public:
            SvNumberFormatter* pFormatter, SvNumFormatType & rCurFmtType );

    /// Calc's threaded group calculation is in progress.
    static bool bThreadedGroupCalcInProgress;
    SC_DLLPUBLIC static bool bThreadedGroupCalcInProgress;
};

// maybe move to dbdata.hxx (?):
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 2f3e330..9fb2bc3 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -37,7 +37,6 @@ class ScInterpreterContextPool;
struct ScInterpreterContext
{
    const ScDocument* mpDoc;
    SvNumberFormatter* mpFormatter;
    size_t mnTokenCachePos;
    std::vector<formula::FormulaToken*> maTokens;
    std::vector<DelayedSetNumberFormat> maDelayedSetNumberFormat;
@@ -48,10 +47,10 @@ struct ScInterpreterContext

    ScInterpreterContext(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
        : mpDoc(&rDoc)
        , mpFormatter(pFormatter)
        , mnTokenCachePos(0)
        , maTokens(TOKEN_CACHE_SIZE, nullptr)
        , mScLookupCache(nullptr)
        , mpFormatter(pFormatter)
    {
    }

@@ -59,7 +58,12 @@ struct ScInterpreterContext

    ~ScInterpreterContext();

    SvNumberFormatter* GetFormatTable() const { return mpFormatter; }
    SvNumberFormatter* GetFormatTable() const
    {
        if (mpFormatter == nullptr)
            const_cast<ScInterpreterContext*>(this)->initFormatTable();
        return mpFormatter;
    }

private:
    friend class ScInterpreterContextPool;
@@ -67,6 +71,8 @@ private:
    void SetDocAndFormatter(const ScDocument& rDoc, SvNumberFormatter* pFormatter);
    void Cleanup();
    void ClearLookupCache();
    void initFormatTable();
    SvNumberFormatter* mpFormatter;
};

class ScThreadedInterpreterContextGetterGuard;
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 7ffd5df..f4c43af 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -2409,7 +2409,7 @@ public:
        {
            sal_uInt32 nNumFmt = pContext ? mrTab.GetNumberFormat(*pContext, ScAddress(nCol, nRow, mrTab.GetTab())) :
                mrTab.GetNumberFormat(nCol, nRow);
            SvNumberFormatter* pFormatter = pContext ? pContext->mpFormatter : mrDoc.GetFormatTable();
            SvNumberFormatter* pFormatter = pContext ? pContext->GetFormatTable() : mrDoc.GetFormatTable();
            const SvNumberformat* pEntry = pFormatter->GetEntry(nNumFmt);
            if (pEntry)
            {
@@ -2483,7 +2483,7 @@ public:
                sal_uInt32 nFormat = pContext ? mrTab.GetNumberFormat( *pContext, ScAddress(static_cast<SCCOL>(rEntry.nField), nRow, mrTab.GetTab()) ) :
                    mrTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
                OUString aStr;
                SvNumberFormatter* pFormatter = pContext ? pContext->mpFormatter : mrDoc.GetFormatTable();
                SvNumberFormatter* pFormatter = pContext ? pContext->GetFormatTable() : mrDoc.GetFormatTable();
                ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, &mrDoc);
                return compareByStringComparator(rEntry, rItem, nullptr, &aStr);
            }
diff --git a/sc/source/core/tool/interpretercontext.cxx b/sc/source/core/tool/interpretercontext.cxx
index bc67afc..b997eff 100644
--- a/sc/source/core/tool/interpretercontext.cxx
+++ b/sc/source/core/tool/interpretercontext.cxx
@@ -18,6 +18,8 @@
 */

#include <interpretercontext.hxx>

#include <document.hxx>
#include <formula/token.hxx>
#include <lookupcache.hxx>
#include <algorithm>
@@ -47,6 +49,11 @@ void ScInterpreterContext::SetDocAndFormatter(const ScDocument& rDoc, SvNumberFo
    mpFormatter = pFormatter;
}

void ScInterpreterContext::initFormatTable()
{
    mpFormatter = mpDoc->GetFormatTable(); // will assert if not main thread
}

void ScInterpreterContext::Cleanup()
{
    // Do not disturb mScLookupCache