[Libreoffice-commits] core.git: Branch 'private/jmux/qt5_fixes' - 21 commits - compilerplugins/clang connectivity/source dbaccess/source icon-themes/colibre icon-themes/colibre_svg officecfg/registry sc/inc sc/qa sc/source solenv/bin solenv/clang-format sw/source vcl/inc vcl/qa vcl/qt5 vcl/source vcl/unx

Jan-Marek Glogowski glogow at fbihome.de
Fri Jul 6 13:53:52 UTC 2018


Rebased ref, commits from common ancestor:
commit 6df705436a4c03e832c8c21b80796d10d33926e0
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Thu Jul 5 18:33:40 2018 +0200

    Qt5 rest
    
    Change-Id: I24b37228321ec38db704c32cd7e5164ad230b695

diff --git a/solenv/bin/create-tags b/solenv/bin/create-tags
index c9fd565b823f..6a6082e72fe8 100755
--- a/solenv/bin/create-tags
+++ b/solenv/bin/create-tags
@@ -11,6 +11,15 @@ ctags="ctags $@"
 saloptions="-ISAL_DELETED_FUNCTION -ISAL_OVERRIDE -ISAL_FINAL"
 omnicppoptions="--c++-kinds=+p --fields=+iaS --extra=+q"
 
+if [ "$1" = "-e" ]; then
+    tagfile="TAGS"
+else
+    tagfile="tags"
+fi
+
+tmpfile=$(mktemp)
+ctags="$ctags -f $tmpfile"
+
 $ctags -h "+.hdl.hrc" --langmap=c:+.hrc.src,c++:+.hdl $saloptions $omnicppoptions \
       --languages=-HTML,Java,JavaScript \
       --langdef=UNOIDL \
@@ -39,3 +48,5 @@ $ctags -h "+.hdl.hrc" --langmap=c:+.hrc.src,c++:+.hdl $saloptions $omnicppoption
       $w/UnoApiHeadersTarget/udkapi/normal \
       $w/UnoApiHeadersTarget/offapi/normal \
       $w/CustomTarget/officecfg/registry
+
+mv "$tmpfile" "$tagfile"
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 8070b7e2d6c0..5e21626cbaea 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -446,6 +446,8 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& /*rSalB
 
     assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth);
     assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
+
+    assert(false && "Qt5Graphics::drawBitmap");
 }
 
 void Qt5Graphics::drawMask(const SalTwoRect& rPosAry, const SalBitmap& /*rSalBitmap*/,
@@ -457,6 +459,8 @@ void Qt5Graphics::drawMask(const SalTwoRect& rPosAry, const SalBitmap& /*rSalBit
 
     assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth);
     assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
+
+    assert(false && "Qt5Graphics::drawMask");
 }
 
 std::shared_ptr<SalBitmap> Qt5Graphics::getBitmap(long nX, long nY, long nWidth, long nHeight)
@@ -494,6 +498,7 @@ void Qt5Graphics::invert(long nX, long nY, long nWidth, long nHeight, SalInvert
 
 void Qt5Graphics::invert(sal_uInt32 /*nPoints*/, const SalPoint* /*pPtAry*/, SalInvert /*nFlags*/)
 {
+    assert(false && "Qt5Graphics::invert 2");
 }
 
 bool Qt5Graphics::drawEPS(long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/,
diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index 37a0879b0044..be3495fb9f51 100644
--- a/vcl/qt5/Qt5Graphics_Text.cxx
+++ b/vcl/qt5/Qt5Graphics_Text.cxx
@@ -132,6 +132,7 @@ void Qt5Graphics::ClearDevFontCache() {}
 bool Qt5Graphics::AddTempDevFont(PhysicalFontCollection*, const OUString& /*rFileURL*/,
                                  const OUString& /*rFontName*/)
 {
+    assert(false && "Qt5Graphics::AddTempDevFont");
     return false;
 }
 
@@ -148,11 +149,15 @@ const void* Qt5Graphics::GetEmbedFontData(const PhysicalFontFace*, long* /*pData
     return nullptr;
 }
 
-void Qt5Graphics::FreeEmbedFontData(const void* /*pData*/, long /*nDataLen*/) {}
+void Qt5Graphics::FreeEmbedFontData(const void* /*pData*/, long /*nDataLen*/)
+{
+    assert(false && "Qt5Graphics::FreeEmbedFontData");
+}
 
 void Qt5Graphics::GetGlyphWidths(const PhysicalFontFace* /*pPFF*/, bool /*bVertical*/,
                                  std::vector<sal_Int32>& /*rWidths*/, Ucs2UIntMap& /*rUnicodeEnc*/)
 {
+    assert(false && "Qt5Graphics::GetGlyphWidths");
 }
 
 bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index 318b9ffe116a..a4413defde30 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -199,7 +199,7 @@ bool OutputDevice::GetFontFeatures(std::vector<vcl::font::Feature>& rFontFeature
 FontMetric OutputDevice::GetFontMetric() const
 {
     FontMetric aMetric;
-    if( mbNewFont && !ImplNewFont() )
+    if( !ImplNewFont() )
         return aMetric;
 
     LogicalFontInstance* pFontInstance = mpFontInstance.get();
@@ -262,10 +262,8 @@ bool OutputDevice::GetFontCharMap( FontCharMapRef& rxFontCharMap ) const
     if( !mpGraphics && !AcquireGraphics() )
         return false;
 
-    if( mbNewFont )
-        ImplNewFont();
-    if( mbInitFont )
-        InitFont();
+    ImplNewFont();
+    InitFont();
     if( !mpFontInstance )
         return false;
 
@@ -287,10 +285,8 @@ bool OutputDevice::GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities
     if( !mpGraphics && !AcquireGraphics() )
         return false;
 
-    if( mbNewFont )
-        ImplNewFont();
-    if( mbInitFont )
-        InitFont();
+    ImplNewFont();
+    InitFont();
     if( !mpFontInstance )
         return false;
 
@@ -995,28 +991,25 @@ void OutputDevice::ImplInitFontList() const
 
 void OutputDevice::InitFont() const
 {
-    DBG_TESTSOLARMUTEX();
-
-    if (!mpFontInstance)
+    if (!mpFontInstance || !mbInitFont)
         return;
 
-    if ( mbInitFont )
-    {
-        // decide if antialiasing is appropriate
-        bool bNonAntialiased(GetAntialiasing() & AntialiasingFlags::DisableText);
-        FontSelectPattern aPattern(mpFontInstance->GetFontSelectPattern());
-        if (!utl::ConfigManager::IsFuzzing())
-        {
-            const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
-            bNonAntialiased |= bool(rStyleSettings.GetDisplayOptions() & DisplayOptions::AADisable);
-            bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > aPattern.mnHeight);
-        }
-        aPattern.mbNonAntialiased = bNonAntialiased;
+    DBG_TESTSOLARMUTEX();
 
-        // select font in the device layers
-        mpGraphics->SetFont(&aPattern, 0);
-        mbInitFont = false;
+    // decide if antialiasing is appropriate
+    bool bNonAntialiased(GetAntialiasing() & AntialiasingFlags::DisableText);
+    FontSelectPattern aPattern(mpFontInstance->GetFontSelectPattern());
+    if (!utl::ConfigManager::IsFuzzing())
+    {
+        const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+        bNonAntialiased |= bool(rStyleSettings.GetDisplayOptions() & DisplayOptions::AADisable);
+        bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > aPattern.mnHeight);
     }
+    aPattern.mbNonAntialiased = bNonAntialiased;
+
+    // select font in the device layers
+    mpGraphics->SetFont(&aPattern, 0);
+    mbInitFont = false;
 }
 
 bool OutputDevice::ImplNewFont() const
@@ -1055,7 +1048,7 @@ bool OutputDevice::ImplNewFont() const
             aSize.setHeight( 1 );
         else
             aSize.setHeight( (12*mnDPIY)/72 );
-        fExactHeight =  static_cast<float>(aSize.Height());
+        fExactHeight = static_cast<float>(aSize.Height());
     }
 
     // select the default width only when logical width is zero
@@ -1076,8 +1069,9 @@ bool OutputDevice::ImplNewFont() const
         return false;
     }
 
-    // mark when lower layers need to get involved
     mbNewFont = false;
+
+    // mark when lower layers need to get involved
     if( bNewFontInstance )
         mbInitFont = true;
 
@@ -1120,14 +1114,13 @@ bool OutputDevice::ImplNewFont() const
     }
 
     // calculate text offset depending on TextAlignment
-    TextAlign eAlign = maFont.GetAlignment();
-    if ( eAlign == ALIGN_BASELINE )
+    switch (maFont.GetAlignment())
     {
+    case ALIGN_BASELINE:
         mnTextOffX = 0;
         mnTextOffY = 0;
-    }
-    else if ( eAlign == ALIGN_TOP )
-    {
+        break;
+    case ALIGN_TOP:
         mnTextOffX = 0;
         mnTextOffY = +pFontInstance->mxFontMetric->GetAscent() + mnEmphasisAscent;
         if ( pFontInstance->mnOrientation )
@@ -1135,9 +1128,8 @@ bool OutputDevice::ImplNewFont() const
             Point aOriginPt(0, 0);
             aOriginPt.RotateAround( mnTextOffX, mnTextOffY, pFontInstance->mnOrientation );
         }
-    }
-    else // eAlign == ALIGN_BOTTOM
-    {
+        break;
+    case ALIGN_BOTTOM:
         mnTextOffX = 0;
         mnTextOffY = -pFontInstance->mxFontMetric->GetDescent() + mnEmphasisDescent;
         if ( pFontInstance->mnOrientation )
@@ -1145,6 +1137,10 @@ bool OutputDevice::ImplNewFont() const
             Point aOriginPt(0, 0);
             aOriginPt.RotateAround( mnTextOffX, mnTextOffY, pFontInstance->mnOrientation );
         }
+        break;
+    case TextAlign_FORCE_EQUAL_SIZE:
+        assert( false && "TextAlign_FORCE_EQUAL_SIZE not implemented for new fonts" );
+        break;
     }
 
     mbTextLines     = ((maFont.GetUnderline() != LINESTYLE_NONE) && (maFont.GetUnderline() != LINESTYLE_DONTKNOW)) ||
@@ -1427,7 +1423,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
 
 long OutputDevice::GetMinKashida() const
 {
-    if( mbNewFont && !ImplNewFont() )
+    if( !ImplNewFont() )
         return 0;
 
     return ImplDevicePixelToLogicWidth( mpFontInstance->mxFontMetric->GetMinKashida() );
commit 7a71526a66890a5a51c891edfd84659943f381bc
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Thu Mar 1 14:57:58 2018 +0100

    WaE: -Wunused-variable
    
    Change-Id: I58f012ddc2c5030b0e3e215b9cab4e89abf06c2b

diff --git a/vcl/inc/unx/x11_cursors/null_curs.h b/vcl/inc/unx/x11_cursors/null_curs.h
index d74b462cba9b..ebeee4e6ffc5 100644
--- a/vcl/inc/unx/x11_cursors/null_curs.h
+++ b/vcl/inc/unx/x11_cursors/null_curs.h
@@ -20,6 +20,5 @@
 #define nullcurs_height 4
 #define nullcurs_x_hot 2
 #define nullcurs_y_hot 2
-static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/x11_cursors/null_mask.h b/vcl/inc/unx/x11_cursors/null_mask.h
index bc23e9c9729b..71f08a94afcf 100644
--- a/vcl/inc/unx/x11_cursors/null_mask.h
+++ b/vcl/inc/unx/x11_cursors/null_mask.h
@@ -18,6 +18,5 @@
  */
 #define nullmask_width 4
 #define nullmask_height 4
-static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/app/saldisp.cxx b/vcl/unx/generic/app/saldisp.cxx
index dff49c8e8b7c..ddce3f81da27 100644
--- a/vcl/unx/generic/app/saldisp.cxx
+++ b/vcl/unx/generic/app/saldisp.cxx
@@ -1494,6 +1494,9 @@ KeySym SalDisplay::GetKeySym( XKeyEvent        *pEvent,
 }
 
 // Pointer
+static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+
 #define MAKE_BITMAP( name ) \
     XCreateBitmapFromData( pDisp_, \
                            DefaultRootWindow( pDisp_ ), \
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index 7c9a3d1e0fbc..689fa071ce5b 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -245,6 +245,9 @@ GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
               &aBlack, &aWhite, nXHot, nYHot);
 }
 
+static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+
 #define MAKE_CURSOR( vcl_name, name ) \
     case vcl_name: \
         pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index fd5b47f0b626..024dac2a5014 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -213,7 +213,10 @@ GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
     return cursor;
 }
 
-#define MAKE_CURSOR( vcl_name, name ) \
+static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+
+#define MAKE_CURSOR( vcl_name, name )           \
     case vcl_name: \
         pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
                               name##curs_width, name##curs_height, \
commit 8981adda6a24a172245b8cd0dd60e31644e23c75
Author: Vikas <vikasmahato0 at gmail.com>
Date:   Tue Jul 3 17:05:36 2018 +0530

    Added aggregate functions for external data
    
    - Sum, which returns the sum of values in the column.
    - Average, which returns the average of values in the column.
    - Min, which returns the minimum of the values in the column.
    - Max, which returns the maximum of the values in the column.
    
    Change-Id: I196eb2d367d2f8c50ceec42735f6f56e2067e401
    Reviewed-on: https://gerrit.libreoffice.org/56862
    Tested-by: Jenkins
    Reviewed-by: Markus Mohrhard <markus.mohrhard at googlemail.com>

diff --git a/sc/qa/unit/datatransformation_test.cxx b/sc/qa/unit/datatransformation_test.cxx
index 8cec163eeb43..c011941a6cb7 100644
--- a/sc/qa/unit/datatransformation_test.cxx
+++ b/sc/qa/unit/datatransformation_test.cxx
@@ -35,6 +35,10 @@ public:
     void testTextToUpper();
     void testTextCapitalize();
     void testTextTrim();
+    void testAggregateSum();
+    void testAggregateAverage();
+    void testAggregateMin();
+    void testAggregateMax();
 
     CPPUNIT_TEST_SUITE(ScDataTransformationTest);
     CPPUNIT_TEST(testColumnRemove);
@@ -44,6 +48,10 @@ public:
     CPPUNIT_TEST(testTextToUpper);
     CPPUNIT_TEST(testTextCapitalize);
     CPPUNIT_TEST(testTextTrim);
+    CPPUNIT_TEST(testAggregateSum);
+    CPPUNIT_TEST(testAggregateAverage);
+    CPPUNIT_TEST(testAggregateMin);
+    CPPUNIT_TEST(testAggregateMax);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -193,6 +201,78 @@ void ScDataTransformationTest::testTextTrim()
     CPPUNIT_ASSERT_EQUAL(OUString("Paris"), m_pDoc->GetString(2, 2, 0));
 }
 
+void ScDataTransformationTest::testAggregateSum()
+{
+    m_pDoc->SetValue(2, 0, 0, 2034);
+    m_pDoc->SetValue(2, 1, 0, 2342);
+    m_pDoc->SetValue(2, 2, 0, 57452);
+
+    m_pDoc->SetValue(4, 0, 0, 4829.98);
+    m_pDoc->SetValue(4, 1, 0, 53781.3);
+    m_pDoc->SetValue(4, 2, 0, 9876.4);
+    m_pDoc->SetValue(4, 3, 0, 0);
+
+    sc::AggregateFunction aTransform({2, 4}, sc::AGGREGATE_FUNCTION::SUM);
+    aTransform.Transform(*m_pDoc);
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(61828, m_pDoc->GetValue(2, 4, 0), 1e-10);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(68487.68, m_pDoc->GetValue(4, 4, 0), 1e-10);
+}
+
+void ScDataTransformationTest::testAggregateAverage()
+{
+    m_pDoc->SetValue(2, 0, 0, 2034);
+    m_pDoc->SetValue(2, 1, 0, 2342);
+    m_pDoc->SetValue(2, 2, 0, 57453);
+
+    m_pDoc->SetValue(3, 0, 0, 4);
+    m_pDoc->SetValue(3, 1, 0, 4);
+    m_pDoc->SetValue(3, 2, 0, 4);
+
+    sc::AggregateFunction aTransform({2, 3}, sc::AGGREGATE_FUNCTION::AVERAGE);
+    aTransform.Transform(*m_pDoc);
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(20609.6666666667, m_pDoc->GetValue(2, 3, 0), 1e-10);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(3, 3, 0), 1e-10);
+}
+
+void ScDataTransformationTest::testAggregateMin()
+{
+    m_pDoc->SetValue(2, 0, 0, 2034);
+    m_pDoc->SetValue(2, 1, 0, 2342);
+    m_pDoc->SetValue(2, 2, 0, 57453);
+
+    m_pDoc->SetValue(3, 0, 0, 2034);
+    m_pDoc->SetValue(3, 1, 0, -2342);
+    m_pDoc->SetValue(3, 2, 0, 57453);
+
+    sc::AggregateFunction aTransform({2, 3}, sc::AGGREGATE_FUNCTION::MIN);
+    aTransform.Transform(*m_pDoc);
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(2034, m_pDoc->GetValue(2, 3, 0), 1e-10);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(-2342, m_pDoc->GetValue(3, 3, 0), 1e-10);
+}
+
+void ScDataTransformationTest::testAggregateMax()
+{
+    m_pDoc->SetValue(2, 0, 0, 2034);
+    m_pDoc->SetValue(2, 1, 0, 2342);
+    m_pDoc->SetValue(2, 2, 0, 57453);
+    m_pDoc->SetValue(2, 3, 0, -453);
+
+    m_pDoc->SetValue(3, 0, 0, 2034);
+    m_pDoc->SetValue(3, 1, 0, -2342);
+    m_pDoc->SetValue(3, 2, 0, -57453);
+    m_pDoc->SetValue(3, 3, 0, -453);
+
+    sc::AggregateFunction aTransform({2, 3}, sc::AGGREGATE_FUNCTION::MAX);
+    aTransform.Transform(*m_pDoc);
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(57453, m_pDoc->GetValue(2, 4, 0), 1e-10);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(2034, m_pDoc->GetValue(3, 4, 0), 1e-10);
+}
+
+
 ScDataTransformationTest::ScDataTransformationTest() :
     ScBootstrapFixture( "sc/qa/unit/data/dataprovider" ),
     m_pDoc(nullptr)
diff --git a/sc/source/ui/dataprovider/datatransformation.cxx b/sc/source/ui/dataprovider/datatransformation.cxx
index 84df313aacdc..fd779bf6587a 100644
--- a/sc/source/ui/dataprovider/datatransformation.cxx
+++ b/sc/source/ui/dataprovider/datatransformation.cxx
@@ -10,6 +10,7 @@
 #include <datatransformation.hxx>
 
 #include <document.hxx>
+#include <limits>
 
 namespace sc {
 
@@ -268,6 +269,103 @@ TransformationType TextTransformation::getTransformationType() const
     return TransformationType::TEXT_TRANSFORMATION;
 }
 
+AggregateFunction::AggregateFunction(const std::set<SCCOL>& rColumns, const AGGREGATE_FUNCTION rType):
+    maColumns(rColumns),
+    maType(rType)
+{
+}
+
+void AggregateFunction::Transform(ScDocument& rDoc) const
+{
+    SCROW nEndRow = 0;
+    for (auto& itr : maColumns)
+    {
+        nEndRow = getLastRow(rDoc, itr);
+    }
+
+    for (auto& rCol : maColumns)
+    {
+        switch (maType)
+        {
+            case AGGREGATE_FUNCTION::SUM:
+            {
+                double nSum = 0;
+                for (SCROW nRow = 0; nRow <= nEndRow; ++nRow)
+                {
+                    CellType eType;
+                    rDoc.GetCellType(rCol, nRow, 0, eType);
+                    if (eType == CELLTYPE_VALUE)
+                    {
+                        double nVal = rDoc.GetValue(rCol, nRow, 0);
+                        nSum += nVal;
+                    }
+                }
+                rDoc.SetValue(rCol, nEndRow + 1, 0, nSum);
+            }
+            break;
+            case AGGREGATE_FUNCTION::AVERAGE:
+            {
+                double nSum = 0;
+                for (SCROW nRow = 0; nRow <= nEndRow; ++nRow)
+                {
+                    CellType eType;
+                    rDoc.GetCellType(rCol, nRow, 0, eType);
+                    if (eType == CELLTYPE_VALUE)
+                    {
+                        double nVal = rDoc.GetValue(rCol, nRow, 0);
+                        nSum += nVal;
+                    }
+                }
+
+                double nAvg = nSum / (nEndRow + 1);
+                rDoc.SetValue(rCol, nEndRow + 1, 0, nAvg);
+            }
+            break;
+            case AGGREGATE_FUNCTION::MIN:
+            {
+                double nMin = std::numeric_limits<double>::max();
+                for (SCROW nRow = 0; nRow <= nEndRow; ++nRow)
+                {
+                    CellType eType;
+                    rDoc.GetCellType(rCol, nRow, 0, eType);
+                    if (eType == CELLTYPE_VALUE)
+                    {
+                        double nVal = rDoc.GetValue(rCol, nRow, 0);
+                        if(nVal < nMin)
+                            nMin = nVal;
+                    }
+                }
+                rDoc.SetValue(rCol, nEndRow + 1, 0, nMin);
+            }
+            break;
+            case AGGREGATE_FUNCTION::MAX:
+            {
+                double nMax = std::numeric_limits<double>::lowest();
+                for (SCROW nRow = 0; nRow <= nEndRow; ++nRow)
+                {
+                    CellType eType;
+                    rDoc.GetCellType(rCol, nRow, 0, eType);
+                    if (eType == CELLTYPE_VALUE)
+                    {
+                        double nVal = rDoc.GetValue(rCol, nRow, 0);
+                        if(nMax < nVal)
+                            nMax = nVal;
+                    }
+                }
+                rDoc.SetValue(rCol, nEndRow + 1, 0, nMax);
+            }
+            break;
+            default:
+            break;
+        }
+    }
+}
+
+TransformationType AggregateFunction::getTransformationType() const
+{
+    return TransformationType::AGGREGATE_FUNCTION;
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datatransformation.hxx b/sc/source/ui/inc/datatransformation.hxx
index 522c039851ae..305e35a3cd54 100644
--- a/sc/source/ui/inc/datatransformation.hxx
+++ b/sc/source/ui/inc/datatransformation.hxx
@@ -27,11 +27,14 @@ enum class TransformationType
     SPLIT_TRANSFORMATION,
     DELETE_TRANSFORMATION,
     SORT_TRANSFORMATION,
-    TEXT_TRANSFORMATION
+    TEXT_TRANSFORMATION,
+    AGGREGATE_FUNCTION
 };
 
 enum class TEXT_TRANSFORM_TYPE { TO_LOWER, TO_UPPER, CAPITALIZE, TRIM };
 
+enum class AGGREGATE_FUNCTION { SUM, AVERAGE, MIN, MAX };
+
 class SC_DLLPUBLIC DataTransformation
 {
 protected:
@@ -110,6 +113,17 @@ class SC_DLLPUBLIC TextTransformation : public DataTransformation
     virtual TransformationType getTransformationType() const override;
 };
 
+class SC_DLLPUBLIC AggregateFunction : public DataTransformation
+{
+    std::set<SCCOL> maColumns;
+    AGGREGATE_FUNCTION maType;
+
+    public:
+    AggregateFunction(const std::set<SCCOL>& rColumns, const AGGREGATE_FUNCTION rType);
+    virtual void Transform(ScDocument& rDoc) const override;
+    virtual TransformationType getTransformationType() const override;
+};
+
 }
 
 #endif
commit c3a732a11c320b98e31dad79f421d4d73f33a15b
Author: Xisco Fauli <xiscofauli at libreoffice.org>
Date:   Fri Jul 6 11:01:06 2018 +0200

    tdf#118547: Remove lock mark only if password is correct
    
    Change-Id: I9f5731dfaaf9b4cc67e600a8b1c01709e7c9ba99
    Reviewed-on: https://gerrit.libreoffice.org/57044
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 9e29d72da734..a4091418909d 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2557,10 +2557,11 @@ bool ScViewFunc::Unprotect( SCTAB nTab, const OUString& rPassword )
             pDocSh->GetUndoManager()->LeaveListAction();
     }
 
-    SetTabProtectionSymbol(nTab, false);
-
     if (bChanged)
+    {
+        SetTabProtectionSymbol(nTab, false);
         UpdateLayerLocks();     //! broadcast to all views
+    }
 
     return bChanged;
 }
commit ec68d58afd53ffd5f0f524503dec607e52385c72
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Jul 6 12:15:35 2018 +0200

    GetNextPos: deduplicate some nMovX code
    
    Change-Id: I9208e2e0a9eaa27a81ffe1dd7054dffc7ddd75f4
    Reviewed-on: https://gerrit.libreoffice.org/57050
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 24e8d62a9b77..f68e8fff8e66 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -1498,82 +1498,70 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY,
             const SCCOL nColCount = nEndCol - nStartCol + 1;
             std::unique_ptr<SCROW[]> pNextRows( new SCROW[nColCount]);
             const SCCOL nLastCol = aCol.size() - 1;
+            const bool bUp = (nMovX < 0);   // Moving left also means moving up in rows.
+            const SCROW nRowAdd = (bUp ? -1 : 1);
             sal_uInt16 nWrap = 0;
 
-            if ( nMovX > 0 )                            //  forward
+            for (SCCOL i = 0; i < nColCount; ++i)
+                pNextRows[i] = (i + nStartCol < nCol) ? (nRow + nRowAdd) : nRow;
+            do
             {
-                for (SCCOL i = 0; i < nColCount; ++i)
-                    pNextRows[i] = (i + nStartCol < nCol) ? (nRow+1) : nRow;
-                do
+                SCROW nNextRow = pNextRows[nCol - nStartCol] + nRowAdd;
+                if ( bMarked )
+                    nNextRow = rMark.GetNextMarked( nCol, nNextRow, bUp );
+                if ( bUnprotected )
+                    nNextRow = ( nCol <= nLastCol ) ? aCol[nCol].GetNextUnprotected( nNextRow, bUp ) :
+                        aDefaultColAttrArray.GetNextUnprotected( nNextRow, bUp );
+                pNextRows[nCol - nStartCol] = nNextRow;
+
+                if (bUp)
                 {
-                    SCROW nNextRow = pNextRows[nCol - nStartCol] + 1;
-                    if ( bMarked )
-                        nNextRow = rMark.GetNextMarked( nCol, nNextRow, false );
-                    if ( bUnprotected )
-                        nNextRow = ( nCol <= nLastCol ) ? aCol[nCol].GetNextUnprotected( nNextRow, false ) :
-                            aDefaultColAttrArray.GetNextUnprotected( nNextRow, false );
-                    pNextRows[nCol - nStartCol] = nNextRow;
-
-                    SCROW nMinRow = nEndRow + 1;
+                    SCROW nMaxRow = nStartRow - 1;
                     for (SCCOL i = 0; i < nColCount; ++i)
                     {
-                        if (pNextRows[i] < nMinRow)     // when two equal on the left
+                        if (pNextRows[i] >= nMaxRow)    // when two equal the right one
                         {
-                            nMinRow = pNextRows[i];
+                            nMaxRow = pNextRows[i];
                             nCol = i + nStartCol;
                         }
                     }
-                    nRow = nMinRow;
+                    nRow = nMaxRow;
 
-                    if ( nRow > nEndRow )
+                    if ( nRow < nStartRow )
                     {
                         if (++nWrap >= 2)
                             return;
-                        nCol = nStartCol;
-                        nRow = nStartRow;
+                        nCol = nEndCol;
+                        nRow = nEndRow;
                         for (SCCOL i = 0; i < nColCount; ++i)
-                            pNextRows[i] = nStartRow;   // do it all over again
+                            pNextRows[i] = nEndRow;     // do it all over again
                     }
                 }
-                while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
-            }
-            else                                        //  backwards
-            {
-                for (SCCOL i = 0; i < nColCount; ++i)
-                    pNextRows[i] = (i + nStartCol > nCol) ? (nRow-1) : nRow;
-                do
+                else
                 {
-                    SCROW nNextRow = pNextRows[nCol - nStartCol] - 1;
-                    if ( bMarked )
-                        nNextRow = rMark.GetNextMarked( nCol, nNextRow, true );
-                    if ( bUnprotected )
-                        nNextRow = ( nCol <= nLastCol ) ? aCol[nCol].GetNextUnprotected( nNextRow, true ) :
-                            aDefaultColAttrArray.GetNextUnprotected( nNextRow, true );
-                    pNextRows[nCol - nStartCol] = nNextRow;
-
-                    SCROW nMaxRow = nStartRow - 1;
+                    SCROW nMinRow = nEndRow + 1;
                     for (SCCOL i = 0; i < nColCount; ++i)
                     {
-                        if (pNextRows[i] >= nMaxRow)    // when two equal on the right
+                        if (pNextRows[i] < nMinRow)     // when two equal the left one
                         {
-                            nMaxRow = pNextRows[i];
+                            nMinRow = pNextRows[i];
                             nCol = i + nStartCol;
                         }
                     }
-                    nRow = nMaxRow;
+                    nRow = nMinRow;
 
-                    if ( nRow < nStartRow )
+                    if ( nRow > nEndRow )
                     {
                         if (++nWrap >= 2)
                             return;
-                        nCol = nEndCol;
-                        nRow = nEndRow;
+                        nCol = nStartCol;
+                        nRow = nStartRow;
                         for (SCCOL i = 0; i < nColCount; ++i)
-                            pNextRows[i] = nEndRow;     // do it all over again
+                            pNextRows[i] = nStartRow;   // do it all over again
                     }
                 }
-                while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
             }
+            while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
         }
     }
 
commit d778140cca4c1a0b63531f46ea6c5df716e47b98
Author: Henry Castro <hcastro at collabora.com>
Date:   Thu Jul 5 15:28:06 2018 -0400

    tdf#118540: LO6.1b2: DOCX crashes when properties...
    
    are opened in print preview mode
    
    Change-Id: Idc64d2b98dff157d28813dd3f90a276f8cacd11f
    Reviewed-on: https://gerrit.libreoffice.org/57024
    Tested-by: Jenkins
    Reviewed-by: Henry Castro <hcastro at collabora.com>

diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx
index ab4c22a5b718..7c210e6a468d 100644
--- a/sw/source/uibase/app/docsh2.cxx
+++ b/sw/source/uibase/app/docsh2.cxx
@@ -145,7 +145,9 @@ using namespace ::sfx2;
 // create DocInfo (virtual)
 VclPtr<SfxDocumentInfoDialog> SwDocShell::CreateDocumentInfoDialog(const SfxItemSet &rSet)
 {
-    VclPtr<SfxDocumentInfoDialog> pDlg = VclPtr<SfxDocumentInfoDialog>::Create(&GetView()->GetViewFrame()->GetWindow(), rSet);
+    SfxViewShell* pViewShell = GetView() ? GetView() : SfxViewShell::Current();
+    vcl::Window* pWindow = pViewShell ? &pViewShell->GetViewFrame()->GetWindow() : nullptr;
+    VclPtr<SfxDocumentInfoDialog> pDlg = VclPtr<SfxDocumentInfoDialog>::Create(pWindow, rSet);
     //only with statistics, when this document is being shown, not
     //from within the Doc-Manager
     SwDocShell* pDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current());
commit ff002524c12471668e63837a804b6006f9136a34
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Tue May 29 11:28:07 2018 +0200

    compilerplugins: try to make these work with icecream
    
    There are some problems here, this should fix one of them: the
    getFilename function returns "<stdin>" for spelling locations, because
    the input to clang is sort of preprocessed via -frewrite-includes if
    icecream is used and the file is built on a remote host (whereas it's
    apparently not preprocessed if the file is compiled locally by icecream).
    
    Using getPresumedLoc() uses the #line directives in the preprocessed
    input, which avoids the problem but is more expensive, so try to use it
    only when necessary.
    
    The getFileEntry(getMainFileID())->getName() pattern will also result
    in "<stdin>", but fortunately icecream passes -main-file-name,
    which oddly enough isn't used by the SourceManager's spelling locations,
    but is available separately via CodeGenOptions.
    
    This builds everything successfully with clang version 6.0.0:
    ICECC_PREFERRED_HOST=myremote make check gb_SUPPRESS_TESTS=t
    
    Change-Id: Ic121511683e5302d7b9d85186c8b9c4a5443fa1b
    Reviewed-on: https://gerrit.libreoffice.org/54993
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/compilerplugins/clang/automem.cxx b/compilerplugins/clang/automem.cxx
index 52bfdf43d6b3..4675c02325be 100644
--- a/compilerplugins/clang/automem.cxx
+++ b/compilerplugins/clang/automem.cxx
@@ -51,7 +51,7 @@ bool AutoMem::VisitCXXDeleteExpr(const CXXDeleteExpr* expr)
 {
     if (ignoreLocation( expr ))
         return true;
-    StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
     if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/salhelper/")
         || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/osl/")
         || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/salhelper/")
diff --git a/compilerplugins/clang/blockblock.cxx b/compilerplugins/clang/blockblock.cxx
index 065e4572e0e1..bdb7d1361410 100644
--- a/compilerplugins/clang/blockblock.cxx
+++ b/compilerplugins/clang/blockblock.cxx
@@ -28,8 +28,7 @@ public:
 
     virtual void run() override
     {
-        StringRef fn( compiler.getSourceManager().getFileEntryForID(
-                          compiler.getSourceManager().getMainFileID())->getName() );
+        StringRef fn(handler.getMainFileName());
         if (loplugin::isSamePathname(fn, SRCDIR "/sal/osl/unx/file_misc.cxx"))
              return;
 
diff --git a/compilerplugins/clang/checkunusedparams.cxx b/compilerplugins/clang/checkunusedparams.cxx
index 31dae1c66e61..84f05dca4dab 100644
--- a/compilerplugins/clang/checkunusedparams.cxx
+++ b/compilerplugins/clang/checkunusedparams.cxx
@@ -44,8 +44,7 @@ private:
 
 void CheckUnusedParams::run()
 {
-    StringRef fn( compiler.getSourceManager().getFileEntryForID(
-                      compiler.getSourceManager().getMainFileID())->getName() );
+    StringRef fn(handler.getMainFileName());
     if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/"))
          return;
     // Taking pointer to function
@@ -200,7 +199,7 @@ bool CheckUnusedParams::VisitFunctionDecl(FunctionDecl const * decl) {
         return true;
     if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(canon->getLocation())))
         return true;
-    StringRef fn = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(canon->getLocStart()));
+    StringRef fn = getFileNameOfSpellingLoc(compiler.getSourceManager().getSpellingLoc(canon->getLocStart()));
     // Some backwards compat magic.
     // TODO Can probably be removed, but need to do some checking
     if (loplugin::isSamePathname(fn, SRCDIR "/include/sax/fshelper.hxx"))
diff --git a/compilerplugins/clang/constantparam.cxx b/compilerplugins/clang/constantparam.cxx
index 3cbcbc8e4043..efff4ac896d5 100644
--- a/compilerplugins/clang/constantparam.cxx
+++ b/compilerplugins/clang/constantparam.cxx
@@ -62,8 +62,7 @@ public:
     virtual void run() override
     {
         // ignore some files that make clang crash inside EvaluateAsInt
-        std::string fn( compiler.getSourceManager().getFileEntryForID(
-                        compiler.getSourceManager().getMainFileID())->getName() );
+        std::string fn(handler.getMainFileName());
         loplugin::normalizeDotDotInFilePath(fn);
         if (loplugin::isSamePathname(fn, SRCDIR "/basegfx/source/matrix/b2dhommatrix.cxx")
             || loplugin::isSamePathname(fn, SRCDIR "/basegfx/source/matrix/b3dhommatrix.cxx"))
diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx
index 471da7367dc0..08e6aa2f1dc1 100644
--- a/compilerplugins/clang/constparams.cxx
+++ b/compilerplugins/clang/constparams.cxx
@@ -38,8 +38,7 @@ public:
     explicit ConstParams(loplugin::InstantiationData const & data): loplugin::FunctionAddress<ConstParams>(data) {}
 
     virtual void run() override {
-        std::string fn( compiler.getSourceManager().getFileEntryForID(
-                        compiler.getSourceManager().getMainFileID())->getName() );
+        std::string fn(handler.getMainFileName());
         loplugin::normalizeDotDotInFilePath(fn);
         if (startswith(fn, SRCDIR "/sal/")
             || fn == SRCDIR "/jurt/source/pipe/staticsalhack.cxx"
diff --git a/compilerplugins/clang/convertlong.cxx b/compilerplugins/clang/convertlong.cxx
index b706d7dffaa4..8038b8a6371b 100644
--- a/compilerplugins/clang/convertlong.cxx
+++ b/compilerplugins/clang/convertlong.cxx
@@ -35,9 +35,7 @@ public:
 
     virtual void run() override
     {
-        std::string fn(compiler.getSourceManager()
-                           .getFileEntryForID(compiler.getSourceManager().getMainFileID())
-                           ->getName());
+        std::string fn(handler.getMainFileName());
         loplugin::normalizeDotDotInFilePath(fn);
         // using sal_uIntPtr as in-between type when converting void* to rtl_TextEncoding
         if (fn == SRCDIR "/sal/osl/unx/thread.cxx")
@@ -74,7 +72,7 @@ bool ConvertLong::VisitVarDecl(VarDecl const* varDecl)
 {
     if (ignoreLocation(varDecl))
         return true;
-    StringRef fileName{ compiler.getSourceManager().getFilename(varDecl->getLocation()) };
+    StringRef fileName{ getFileNameOfSpellingLoc(varDecl->getLocation()) };
     if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/bigint.hxx"))
         return true;
     if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/solar.h"))
diff --git a/compilerplugins/clang/datamembershadow.cxx b/compilerplugins/clang/datamembershadow.cxx
index 6e71ce57a4e7..35c96c6f240f 100644
--- a/compilerplugins/clang/datamembershadow.cxx
+++ b/compilerplugins/clang/datamembershadow.cxx
@@ -44,8 +44,8 @@ bool DataMemberShadow::VisitFieldDecl(FieldDecl const * fieldDecl)
     if (ignoreLocation(fieldDecl)) {
         return true;
     }
-    StringRef aFileName = compiler.getSourceManager().getFilename(
-            compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(
+        compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocStart()));
 
     // FIXME complex stuff to fix later
 
diff --git a/compilerplugins/clang/dyncastvisibility.cxx b/compilerplugins/clang/dyncastvisibility.cxx
index afc500f61f61..6a1d84d91d3e 100644
--- a/compilerplugins/clang/dyncastvisibility.cxx
+++ b/compilerplugins/clang/dyncastvisibility.cxx
@@ -115,7 +115,7 @@ public:
             // at least some interesting cases (though it would still not be aggressive enough to
             // have found ff570b4b58dbf274d3094d21d974f18b613e9b4b "DocumentSettingsSerializer must
             // be SAL_DLLPUBLIC_RTTI for dynamic_cast"):
-            auto const file = compiler.getSourceManager().getFilename(
+            auto const file = getFileNameOfSpellingLoc(
                 compiler.getSourceManager().getSpellingLoc(rdd->getLocation()));
             if (loplugin::hasPathnamePrefix(file, SRCDIR "/include/")) {
                 std::size_t const n1 = std::strlen(SRCDIR "/include/");
@@ -127,10 +127,7 @@ public:
                 auto prefix = std::string(SRCDIR "/");
                 prefix += seg;
                 if (!loplugin::hasPathnamePrefix(
-                        (compiler.getSourceManager()
-                         .getFileEntryForID(compiler.getSourceManager().getMainFileID())
-                         ->getName()),
-                        prefix))
+                            handler.getMainFileName(), prefix))
                 {
                     report(
                         DiagnosticsEngine::Warning,
diff --git a/compilerplugins/clang/expressionalwayszero.cxx b/compilerplugins/clang/expressionalwayszero.cxx
index 6633f138cfb3..0f0eb7a541e6 100644
--- a/compilerplugins/clang/expressionalwayszero.cxx
+++ b/compilerplugins/clang/expressionalwayszero.cxx
@@ -35,8 +35,9 @@ public:
 
     virtual void run() override
     {
-        std::string fn( compiler.getSourceManager().getFileEntryForID(
-                        compiler.getSourceManager().getMainFileID())->getName() );
+        // don't use getMainFileID, it may return "<stdin>"
+        std::string fn(handler.getMainFileName());
+
         loplugin::normalizeDotDotInFilePath(fn);
         // encoding of constant value for binary file format
         if (startswith(fn, SRCDIR "/package/source/zipapi/ZipFile.cxx"))
diff --git a/compilerplugins/clang/externandnotdefined.cxx b/compilerplugins/clang/externandnotdefined.cxx
index df5455d0dddf..97dff5a8dfa3 100644
--- a/compilerplugins/clang/externandnotdefined.cxx
+++ b/compilerplugins/clang/externandnotdefined.cxx
@@ -57,7 +57,7 @@ bool ExternAndNotDefined::VisitFunctionDecl(const FunctionDecl * functionDecl) {
     {
         return true;
     }
-    StringRef fileName { compiler.getSourceManager().getFilename(functionDecl->getLocation()) };
+    StringRef fileName { getFileNameOfSpellingLoc(functionDecl->getLocation()) };
     // the filters use some kind of dynamic loading stunt
     if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/filter/qa/")) {
         return true;
diff --git a/compilerplugins/clang/fragiledestructor.cxx b/compilerplugins/clang/fragiledestructor.cxx
index f8a0ea50660c..d1bff95ddf72 100644
--- a/compilerplugins/clang/fragiledestructor.cxx
+++ b/compilerplugins/clang/fragiledestructor.cxx
@@ -47,7 +47,7 @@ bool FragileDestructor::TraverseCXXDestructorDecl(CXXDestructorDecl* pCXXDestruc
         return RecursiveASTVisitor::TraverseCXXDestructorDecl(pCXXDestructorDecl);
     }
     // ignore this for now, too tricky for me to work out
-    StringRef aFileName = compiler.getSourceManager().getFilename(
+    StringRef aFileName = getFileNameOfSpellingLoc(
             compiler.getSourceManager().getSpellingLoc(pCXXDestructorDecl->getLocStart()));
     if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/comphelper/")
         || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/cppuhelper/")
@@ -87,7 +87,8 @@ bool FragileDestructor::VisitCXXMemberCallExpr(const CXXMemberCallExpr* callExpr
         return true;
     }
     // e.g. osl/thread.hxx and cppuhelper/compbase.hxx
-    StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(methodDecl->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(
+        compiler.getSourceManager().getSpellingLoc(methodDecl->getLocStart()));
     if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/osl/")
         || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/comphelper/")
         || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/cppuhelper/"))
diff --git a/compilerplugins/clang/memoryvar.cxx b/compilerplugins/clang/memoryvar.cxx
index 17cb2701acd0..590af94b7c7a 100644
--- a/compilerplugins/clang/memoryvar.cxx
+++ b/compilerplugins/clang/memoryvar.cxx
@@ -50,7 +50,7 @@ private:
 StringRef MemoryVar::getFilename(SourceLocation loc)
 {
     SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc);
-    StringRef name { compiler.getSourceManager().getFilename(spellingLocation) };
+    StringRef name { getFileNameOfSpellingLoc(spellingLocation) };
     return name;
 }
 
diff --git a/compilerplugins/clang/nullptr.cxx b/compilerplugins/clang/nullptr.cxx
index bc1f7b505243..ccd5837b226f 100644
--- a/compilerplugins/clang/nullptr.cxx
+++ b/compilerplugins/clang/nullptr.cxx
@@ -233,7 +233,7 @@ bool Nullptr::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) {
 
 bool Nullptr::isInLokIncludeFile(SourceLocation spellingLocation) const {
     return loplugin::hasPathnamePrefix(
-        compiler.getSourceManager().getFilename(spellingLocation),
+        getFileNameOfSpellingLoc(spellingLocation),
         SRCDIR "/include/LibreOfficeKit/");
 }
 
diff --git a/compilerplugins/clang/oncevar.cxx b/compilerplugins/clang/oncevar.cxx
index a8a56f5a7e33..afb1b0fa85e9 100644
--- a/compilerplugins/clang/oncevar.cxx
+++ b/compilerplugins/clang/oncevar.cxx
@@ -83,8 +83,7 @@ public:
 
     virtual void run() override {
         // ignore some files with problematic macros
-        std::string fn( compiler.getSourceManager().getFileEntryForID(
-                        compiler.getSourceManager().getMainFileID())->getName() );
+        std::string fn(handler.getMainFileName());
         loplugin::normalizeDotDotInFilePath(fn);
         // platform-specific stuff
         if (fn == SRCDIR "/sal/osl/unx/thread.cxx"
diff --git a/compilerplugins/clang/overrideparam.cxx b/compilerplugins/clang/overrideparam.cxx
index 820127e1343d..10e664c75326 100644
--- a/compilerplugins/clang/overrideparam.cxx
+++ b/compilerplugins/clang/overrideparam.cxx
@@ -43,8 +43,7 @@ private:
 void OverrideParam::run()
 {
     /*
-    StringRef fn( compiler.getSourceManager().getFileEntryForID(
-                      compiler.getSourceManager().getMainFileID())->getName() );
+    StringRef fn(handler.getMainFileName());
     if (fn == SRCDIR "/include/svx/checklbx.hxx")
          return;
 */
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 56d40e337bf9..1348c3f0f00f 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -215,11 +215,37 @@ const FunctionDecl* Plugin::getParentFunctionDecl( const Stmt* stmt )
     return nullptr;
 }
 
+StringRef Plugin::getFileNameOfSpellingLoc(SourceLocation spellingLocation) const
+{
+    static enum { NOINIT, STDIN, GOOD } s_Mode(NOINIT);
+    if (s_Mode == GOOD)
+    {
+        return compiler.getSourceManager().getFilename(spellingLocation);
+    }
+    else if (s_Mode == STDIN
+             || !compiler.getSourceManager().isInMainFile(spellingLocation))
+    {
+        const char* bufferName = compiler.getSourceManager().getPresumedLoc(spellingLocation).getFilename();
+        return bufferName;
+    }
+    else
+    {
+        auto const fn(compiler.getSourceManager().getFilename(spellingLocation));
+        if (!fn.data()) // wtf? happens in sot/source/sdstor/stg.cxx
+        {
+            return fn;
+        }
+#if !defined _WIN32
+        assert(fn.startswith("/") || fn == "<stdin>");
+#endif
+        s_Mode = fn == "<stdin>" ? STDIN : GOOD;
+        return getFileNameOfSpellingLoc(spellingLocation);
+    }
+}
 
 bool Plugin::isInUnoIncludeFile(SourceLocation spellingLocation) const
 {
-    StringRef name {
-        compiler.getSourceManager().getFilename(spellingLocation) };
+    StringRef name{ getFileNameOfSpellingLoc(spellingLocation) };
     return compiler.getSourceManager().isInMainFile(spellingLocation)
         ? (isSamePathname(name, SRCDIR "/cppu/source/cppu/compat.cxx")
            || isSamePathname(name, SRCDIR "/cppuhelper/source/compat.cxx")
diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx
index 5299e7f2eac3..4c4d9a70fcb3 100644
--- a/compilerplugins/clang/plugin.hxx
+++ b/compilerplugins/clang/plugin.hxx
@@ -72,6 +72,9 @@ protected:
     const Stmt* getParentStmt( const Stmt* stmt );
     Stmt* getParentStmt( Stmt* stmt );
     const FunctionDecl* getParentFunctionDecl( const Stmt* stmt );
+
+    /// to check file names against whitelists, so that it works with preprocessed input too
+    StringRef getFileNameOfSpellingLoc(SourceLocation spellingLocation) const;
     /**
      Checks if the location is inside an UNO file, more specifically, if it forms part of the URE stable interface,
      which is not allowed to be changed.
diff --git a/compilerplugins/clang/pluginhandler.cxx b/compilerplugins/clang/pluginhandler.cxx
index b1e789a4a8c5..a4637cd78e6d 100644
--- a/compilerplugins/clang/pluginhandler.cxx
+++ b/compilerplugins/clang/pluginhandler.cxx
@@ -55,9 +55,21 @@ static int pluginCount = 0;
 static bool bPluginObjectsCreated = false;
 static bool unitTestMode = false;
 
+StringRef initMainFileName(CompilerInstance& compiler)
+{
+    StringRef const& fn(compiler.getASTContext().getSourceManager().getFileEntryForID(
+        compiler.getASTContext().getSourceManager().getMainFileID())->getName());
+    if (fn == "<stdin>")
+        // stdin means icecream, so we can rely on -main-file-name containing the full path name
+        return compiler.getCodeGenOpts().MainFileName;
+    else
+        // this is always a full path name
+        return fn;
+}
+
 PluginHandler::PluginHandler( CompilerInstance& compiler, const std::vector< std::string >& args )
     : compiler( compiler )
-    , mainFileName(compiler.getASTContext().getSourceManager().getFileEntryForID(compiler.getASTContext().getSourceManager().getMainFileID())->getName())
+    , mainFileName(initMainFileName(compiler))
     , rewriter( compiler.getSourceManager(), compiler.getLangOpts())
     , scope( "mainfile" )
     , warningsAsErrors( false )
diff --git a/compilerplugins/clang/pluginhandler.hxx b/compilerplugins/clang/pluginhandler.hxx
index 0b53d7043f00..1cb405d54d35 100644
--- a/compilerplugins/clang/pluginhandler.hxx
+++ b/compilerplugins/clang/pluginhandler.hxx
@@ -60,6 +60,7 @@ public:
     // without corrupting the source
     bool checkOverlap(SourceRange range);
     void addSourceModification(SourceRange range);
+    StringRef const& getMainFileName() const { return mainFileName; }
 private:
     void handleOption( const std::string& option );
     void createPlugins( std::set< std::string > rewriters );
diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx
index 8133e281d8aa..f4e7e8e5929b 100644
--- a/compilerplugins/clang/refcounting.cxx
+++ b/compilerplugins/clang/refcounting.cxx
@@ -507,7 +507,8 @@ bool RefCounting::VisitVarDecl(const VarDecl * varDecl) {
               << varDecl->getSourceRange();
         }
         if (containsSalhelperReferenceObjectSubclass(varDecl->getType().getTypePtr())) {
-            StringRef name { compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation())) };
+            StringRef name { getFileNameOfSpellingLoc(
+                compiler.getSourceManager().getSpellingLoc(varDecl->getLocation())) };
             // this is playing games that it believes is safe
             if (loplugin::isSamePathname(name, SRCDIR "/stoc/source/security/permissions.cxx"))
                 return true;
diff --git a/compilerplugins/clang/reservedid.cxx b/compilerplugins/clang/reservedid.cxx
index cfb9a5b35818..e3cb737cf6b5 100644
--- a/compilerplugins/clang/reservedid.cxx
+++ b/compilerplugins/clang/reservedid.cxx
@@ -104,8 +104,7 @@ void ReservedId::run() {
                     if (d->getKind() == MacroDirective::MD_Define) {
                         auto loc = d->getLocation();
                         if (loc.isValid() && !ignoreLocation(loc)) {
-                            auto file = compiler.getSourceManager()
-                                .getFilename(loc);
+                            auto file = getFileNameOfSpellingLoc(loc);
                             if (!loplugin::isSamePathname(
                                     file,
                                     SRCDIR
@@ -137,7 +136,7 @@ bool ReservedId::VisitNamedDecl(NamedDecl const * decl) {
     if (ignoreLocation(spelLoc)) {
         return true;
     }
-    auto filename = compiler.getSourceManager().getFilename(spelLoc);
+    auto filename = getFileNameOfSpellingLoc(spelLoc);
     if (loplugin::hasPathnamePrefix(filename, SRCDIR "/bridges/source/cpp_uno/")
         && filename.endswith("share.hxx"))
     {
@@ -268,7 +267,7 @@ ReservedId::Kind ReservedId::determineKind(llvm::StringRef const & id) {
 
 bool ReservedId::isInLokIncludeFile(SourceLocation spellingLocation) const {
     return loplugin::hasPathnamePrefix(
-        compiler.getSourceManager().getFilename(spellingLocation),
+        getFileNameOfSpellingLoc(spellingLocation),
         SRCDIR "/include/LibreOfficeKit/");
 }
 
diff --git a/compilerplugins/clang/salbool.cxx b/compilerplugins/clang/salbool.cxx
index e828dbfcfc55..02cc2f609661 100644
--- a/compilerplugins/clang/salbool.cxx
+++ b/compilerplugins/clang/salbool.cxx
@@ -767,7 +767,7 @@ bool SalBool::TraverseStaticAssertDecl(StaticAssertDecl * decl) {
     // inside static_assert in cppu/source/uno/check.cxx:
     return
         loplugin::isSamePathname(
-            compiler.getSourceManager().getFilename(decl->getLocation()),
+            getFileNameOfSpellingLoc(decl->getLocation()),
             SRCDIR "/cppu/source/uno/check.cxx")
         || RecursiveASTVisitor::TraverseStaticAssertDecl(decl);
 }
@@ -803,7 +803,7 @@ bool SalBool::isInSpecialMainFile(SourceLocation spellingLocation) const {
     if (!compiler.getSourceManager().isInMainFile(spellingLocation)) {
         return false;
     }
-    auto f = compiler.getSourceManager().getFilename(spellingLocation);
+    auto f = getFileNameOfSpellingLoc(spellingLocation);
     return loplugin::isSamePathname(f, SRCDIR "/cppu/qa/test_any.cxx")
         || loplugin::isSamePathname(f, SRCDIR "/cppu/source/uno/check.cxx");
         // TODO: the offset checks
diff --git a/compilerplugins/clang/shouldreturnbool.cxx b/compilerplugins/clang/shouldreturnbool.cxx
index d993bf25f21e..ea9e696674de 100644
--- a/compilerplugins/clang/shouldreturnbool.cxx
+++ b/compilerplugins/clang/shouldreturnbool.cxx
@@ -36,9 +36,7 @@ public:
     {
         if (!compiler.getLangOpts().CPlusPlus)
             return;
-        StringRef fn(compiler.getSourceManager()
-                         .getFileEntryForID(compiler.getSourceManager().getMainFileID())
-                         ->getName());
+        StringRef fn(handler.getMainFileName());
         // functions used as function pointers
         if (loplugin::isSamePathname(fn, SRCDIR "/sal/rtl/alloc_cache.cxx"))
             return;
diff --git a/compilerplugins/clang/simplifydynamiccast.cxx b/compilerplugins/clang/simplifydynamiccast.cxx
index f305f8cbeaef..eb5d111d11a7 100644
--- a/compilerplugins/clang/simplifydynamiccast.cxx
+++ b/compilerplugins/clang/simplifydynamiccast.cxx
@@ -29,8 +29,7 @@ public:
 
     virtual void run() override
     {
-        //        StringRef fn( compiler.getSourceManager().getFileEntryForID(
-        //                          compiler.getSourceManager().getMainFileID())->getName() );
+        //        StringRef fn(handler.getMainFileName());
         //        if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx"))
         //             return;
 
diff --git a/compilerplugins/clang/staticmethods.cxx b/compilerplugins/clang/staticmethods.cxx
index 50d432081f00..aa1b97e01015 100644
--- a/compilerplugins/clang/staticmethods.cxx
+++ b/compilerplugins/clang/staticmethods.cxx
@@ -60,7 +60,7 @@ bool isDerivedFromTestFixture(const CXXRecordDecl *decl) {
 StringRef StaticMethods::getFilename(SourceLocation loc)
 {
     SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc);
-    return compiler.getSourceManager().getFilename(spellingLocation);
+    return getFileNameOfSpellingLoc(spellingLocation);
 }
 
 bool startsWith(const std::string& rStr, const char* pSubStr) {
diff --git a/compilerplugins/clang/stringconcat.cxx b/compilerplugins/clang/stringconcat.cxx
index f5b8d8c2d2ea..818d8314fa45 100644
--- a/compilerplugins/clang/stringconcat.cxx
+++ b/compilerplugins/clang/stringconcat.cxx
@@ -97,7 +97,7 @@ bool StringConcat::VisitCallExpr(CallExpr const * expr) {
         leftLoc = left->getArg(1)->getLocStart();
     }
     StringRef name {
-        compiler.getSourceManager().getFilename(
+        getFileNameOfSpellingLoc(
             compiler.getSourceManager().getSpellingLoc(expr->getLocStart())) };
     if (loplugin::isSamePathname(
             name, SRCDIR "/sal/qa/rtl/strings/test_ostring_concat.cxx")
diff --git a/compilerplugins/clang/stringconstant.cxx b/compilerplugins/clang/stringconstant.cxx
index 0555b20af24a..8c01c9e5c017 100644
--- a/compilerplugins/clang/stringconstant.cxx
+++ b/compilerplugins/clang/stringconstant.cxx
@@ -325,7 +325,8 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) {
     {
         // u.equalsIgnoreAsciiCaseAscii("foo") ->
         // u.equalsIngoreAsciiCase("foo"):
-        auto file = compiler.getSourceManager().getFilename(
+
+        auto file = getFileNameOfSpellingLoc(
             compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
         if (loplugin::isSamePathname(
                 file, SRCDIR "/sal/qa/rtl/strings/test_oustring_compare.cxx"))
@@ -343,7 +344,7 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) {
     {
         // u.equalsIgnoreAsciiCaseAsciiL("foo", 3) ->
         // u.equalsIngoreAsciiCase("foo"):
-        auto file = compiler.getSourceManager().getFilename(
+        auto file = getFileNameOfSpellingLoc(
             compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
         if (loplugin::isSamePathname(
                 file, SRCDIR "/sal/qa/rtl/strings/test_oustring_compare.cxx"))
@@ -710,7 +711,7 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) {
         case 2:
             {
                 // b.append("foo", 3) -> b.append("foo"):
-                auto file = compiler.getSourceManager().getFilename(
+                auto file = getFileNameOfSpellingLoc(
                     compiler.getSourceManager().getSpellingLoc(
                         expr->getLocStart()));
                 if (loplugin::isSamePathname(
@@ -1077,8 +1078,7 @@ bool StringConstant::VisitCXXConstructExpr(CXXConstructExpr const * expr) {
                                 if (dc.Operator(OO_Plus).Namespace("rtl")
                                     .GlobalNamespace())
                                 {
-                                    auto file =
-                                        compiler.getSourceManager().getFilename(
+                                    auto file = getFileNameOfSpellingLoc(
                                             compiler.getSourceManager()
                                             .getSpellingLoc(
                                                 expr->getLocStart()));
diff --git a/compilerplugins/clang/stringstatic.cxx b/compilerplugins/clang/stringstatic.cxx
index 00f1c9f6eab1..7fa14c0766c7 100644
--- a/compilerplugins/clang/stringstatic.cxx
+++ b/compilerplugins/clang/stringstatic.cxx
@@ -40,8 +40,7 @@ private:
 
 void StringStatic::run()
 {
-    StringRef fn( compiler.getSourceManager().getFileEntryForID(
-                      compiler.getSourceManager().getMainFileID())->getName() );
+    StringRef fn(handler.getMainFileName());
     // passing around pointers to global OUString
     if (loplugin::hasPathnamePrefix(fn, SRCDIR "/filter/source/svg/"))
          return;
diff --git a/compilerplugins/clang/unnecessaryoverride.cxx b/compilerplugins/clang/unnecessaryoverride.cxx
index 338598985289..092decc797fc 100644
--- a/compilerplugins/clang/unnecessaryoverride.cxx
+++ b/compilerplugins/clang/unnecessaryoverride.cxx
@@ -72,8 +72,7 @@ public:
     virtual void run() override
     {
         // ignore some files with problematic macros
-        StringRef fn( compiler.getSourceManager().getFileEntryForID(
-                          compiler.getSourceManager().getMainFileID())->getName() );
+        StringRef fn(handler.getMainFileName());
         if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/factories/ChildWindowPane.cxx"))
              return;
         if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/Date.cxx"))
@@ -113,7 +112,8 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
         return true;
     }
 
-    StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(methodDecl->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(
+        compiler.getSourceManager().getSpellingLoc(methodDecl->getLocStart()));
 
     if (isa<CXXDestructorDecl>(methodDecl)
        && !isInUnoIncludeFile(methodDecl))
diff --git a/compilerplugins/clang/unnecessaryparen.cxx b/compilerplugins/clang/unnecessaryparen.cxx
index caeadcac0072..0cad779ca7dd 100644
--- a/compilerplugins/clang/unnecessaryparen.cxx
+++ b/compilerplugins/clang/unnecessaryparen.cxx
@@ -67,8 +67,7 @@ public:
 
     virtual void run() override
     {
-        StringRef fn( compiler.getSourceManager().getFileEntryForID(
-                          compiler.getSourceManager().getMainFileID())->getName() );
+        StringRef fn(handler.getMainFileName());
         // fixing this, makes the source in the .y files look horrible
         if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx"))
              return;
diff --git a/compilerplugins/clang/unoany.cxx b/compilerplugins/clang/unoany.cxx
index db20779746bc..8caa7c2a54cf 100644
--- a/compilerplugins/clang/unoany.cxx
+++ b/compilerplugins/clang/unoany.cxx
@@ -28,7 +28,8 @@ bool UnoAny::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const * expr)
     if (ignoreLocation(expr)) {
         return true;
     }
-    StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(
+            compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
     if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Any.hxx")) {
         return true;
     }
diff --git a/compilerplugins/clang/unusedvariablemore.cxx b/compilerplugins/clang/unusedvariablemore.cxx
index ead91586c460..fa2ff366052b 100644
--- a/compilerplugins/clang/unusedvariablemore.cxx
+++ b/compilerplugins/clang/unusedvariablemore.cxx
@@ -63,9 +63,7 @@ static bool startswith(const std::string& rStr, const char* pSubStr)
 
 void UnusedVariableMore::run()
 {
-    std::string fn(compiler.getSourceManager()
-                       .getFileEntryForID(compiler.getSourceManager().getMainFileID())
-                       ->getName());
+    std::string fn(handler.getMainFileName());
     loplugin::normalizeDotDotInFilePath(fn);
 
     // ignore QA folders
diff --git a/compilerplugins/clang/useuniqueptr.cxx b/compilerplugins/clang/useuniqueptr.cxx
index 7a3722b785f8..5d8d6c57a2fb 100644
--- a/compilerplugins/clang/useuniqueptr.cxx
+++ b/compilerplugins/clang/useuniqueptr.cxx
@@ -32,9 +32,7 @@ public:
 
     virtual void run() override
     {
-        std::string fn(compiler.getSourceManager()
-                           .getFileEntryForID(compiler.getSourceManager().getMainFileID())
-                           ->getName());
+        std::string fn(handler.getMainFileName());
         loplugin::normalizeDotDotInFilePath(fn);
         // can't change these because we pass them down to the SfxItemPool stuff
         if (fn == SRCDIR "/sc/source/core/data/docpool.cxx")
@@ -249,7 +247,8 @@ void UseUniquePtr::CheckDeleteExpr(const CXXMethodDecl* methodDecl, const CXXDel
     if (ignoreLocation(fieldDecl))
         return;
     // to ignore things like the CPPUNIT macros
-    StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(
+        compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocStart()));
     if (loplugin::hasPathnamePrefix(aFileName, WORKDIR "/"))
         return;
     // passes and stores pointers to member fields
diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index af2b1bf46cdd..84d7ffea6bb2 100644
--- a/compilerplugins/clang/vclwidgets.cxx
+++ b/compilerplugins/clang/vclwidgets.cxx
@@ -239,7 +239,7 @@ bool VCLWidgets::VisitCXXDestructorDecl(const CXXDestructorDecl* pCXXDestructorD
     if (!bOk) {
         SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
                               pCXXDestructorDecl->getLocStart());
-        StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
+        StringRef filename = getFileNameOfSpellingLoc(spellingLocation);
         if (   !(loplugin::isSamePathname(filename, SRCDIR "/vcl/source/window/window.cxx"))
             && !(loplugin::isSamePathname(filename, SRCDIR "/vcl/source/gdi/virdev.cxx"))
             && !(loplugin::isSamePathname(filename, SRCDIR "/vcl/qa/cppunit/lifecycle.cxx")) )
@@ -278,7 +278,7 @@ void VCLWidgets::checkAssignmentForVclPtrToRawConversion(const SourceLocation& s
     if (!rhs) {
         return;
     }
-    StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
+    StringRef filename = getFileNameOfSpellingLoc(spellingLocation);
     if (loplugin::isSamePathname(filename, SRCDIR "/include/rtl/ref.hxx")) {
         return;
     }
@@ -360,7 +360,7 @@ bool VCLWidgets::VisitVarDecl(const VarDecl * pVarDecl) {
     if (pVarDecl->getInit()) {
         checkAssignmentForVclPtrToRawConversion(spellingLocation, pVarDecl->getType().getTypePtr(), pVarDecl->getInit());
     }
-    StringRef aFileName = compiler.getSourceManager().getFilename(spellingLocation);
+    StringRef aFileName = getFileNameOfSpellingLoc(spellingLocation);
     if (loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/vclptr.hxx"))
         return true;
     if (loplugin::isSamePathname(aFileName, SRCDIR "/vcl/source/window/layout.cxx"))
@@ -412,7 +412,8 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
     if (ignoreLocation(fieldDecl)) {
         return true;
     }
-    StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocStart()));
+    StringRef aFileName = getFileNameOfSpellingLoc(
+        compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocStart()));
     if (loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/vclptr.hxx"))
         return true;
     if (loplugin::isSamePathname(aFileName, SRCDIR "/include/rtl/ref.hxx"))
@@ -669,7 +670,7 @@ bool VCLWidgets::VisitCXXDeleteExpr(const CXXDeleteExpr *pCXXDeleteExpr)
     if (pPointee && isDerivedFromVclReferenceBase(pPointee)) {
         SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
                               pCXXDeleteExpr->getLocStart());
-        StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
+        StringRef filename = getFileNameOfSpellingLoc(spellingLocation);
         if ( !(loplugin::isSamePathname(filename, SRCDIR "/include/vcl/vclreferencebase.hxx")))
         {
             report(
@@ -845,7 +846,8 @@ bool VCLWidgets::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr )
     const CXXConstructorDecl* pConstructorDecl = constructExpr->getConstructor();
     const CXXRecordDecl* recordDecl = pConstructorDecl->getParent();
     if (isDerivedFromVclReferenceBase(recordDecl)) {
-        StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(constructExpr->getLocStart()));
+        StringRef aFileName = getFileNameOfSpellingLoc(
+            compiler.getSourceManager().getSpellingLoc(constructExpr->getLocStart()));
         if (!loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/vclptr.hxx")) {
             report(
                 DiagnosticsEngine::Warning,
commit 243f7d73a0b6ef9cea63bfcca0a07aa9c19e259c
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date:   Fri Jul 6 15:26:39 2018 +0530

    Unit tests for a couple of cases...
    
    for the fixes in
    commit 49324c8bc90002b89990bcfe17da77ae1de55cd9
    
    "Generalize FG cycle detection for cycles involving
    a mix of formula-groups and plain formula-cells
    which are not grouped"
    
    Change-Id: I63b4f3ff488f8e788f42527f939769887877b989
    Reviewed-on: https://gerrit.libreoffice.org/57047
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/sc/qa/unit/parallelism.cxx b/sc/qa/unit/parallelism.cxx
index c5c196154123..b9ccf7b9cb3c 100644
--- a/sc/qa/unit/parallelism.cxx
+++ b/sc/qa/unit/parallelism.cxx
@@ -52,6 +52,8 @@ public:
     void testVLOOKUPSUM();
     void testSingleRef();
     void testSUMIFImplicitRange();
+    void testFGCycleWithPlainFormulaCell1();
+    void testFGCycleWithPlainFormulaCell2();
 
     CPPUNIT_TEST_SUITE(ScParallelismTest);
     CPPUNIT_TEST(testSUMIFS);
@@ -60,6 +62,8 @@ public:
     CPPUNIT_TEST(testVLOOKUPSUM);
     CPPUNIT_TEST(testSingleRef);
     CPPUNIT_TEST(testSUMIFImplicitRange);
+    CPPUNIT_TEST(testFGCycleWithPlainFormulaCell1);
+    CPPUNIT_TEST(testFGCycleWithPlainFormulaCell2);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -396,6 +400,94 @@ void ScParallelismTest::testSUMIFImplicitRange()
     m_pDoc->DeleteTab(0);
 }
 
+void ScParallelismTest::testFGCycleWithPlainFormulaCell1()
+{
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, false);
+    m_pDoc->InsertTab(0, "1");
+    const size_t nNumRows = 1048;
+    // Column A contains no formula-group
+    // A1 = 100
+    m_pDoc->SetValue(0, 0, 0, 100.0);
+    // A500 = B499 + 1
+    m_pDoc->SetFormula(ScAddress(0, 499, 0),
+                       "=$B499 + 1",
+                       formula::FormulaGrammar::GRAM_NATIVE_UI);
+    // Column B has a formula-group referencing column A.
+    OUString aFormula;
+    for (size_t i = 0; i < nNumRows; ++i)
+    {
+        aFormula = "=$A" + OUString::number(i+1) + " + 100";
+        m_pDoc->SetFormula(ScAddress(1, i, 0),
+                           aFormula,
+                           formula::FormulaGrammar::GRAM_NATIVE_UI);
+    }
+    m_xDocShell->DoHardRecalc();
+    // Value at A500 must be 101
+    const size_t nVal = 100;
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Value at A500", nVal + 1, static_cast<size_t>(m_pDoc->GetValue(0, 499, 0)));
+    for (size_t i = 0; i < nNumRows; ++i)
+    {
+        OString aMsg = "Value at cell B" + OString::number(i+1);
+        size_t nExpected = nVal;
+        if (i == 0)
+            nExpected = 200;
+        else if (i == 499)
+            nExpected = 201;
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), nExpected, static_cast<size_t>(m_pDoc->GetValue(1, i, 0)));
+    }
+    m_pDoc->DeleteTab(0);
+}
+
+void ScParallelismTest::testFGCycleWithPlainFormulaCell2()
+{
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, false);
+    m_pDoc->InsertTab(0, "1");
+    const size_t nNumRows = 1048;
+    // Column A
+    OUString aFormula;
+    for (size_t i = 0; i < nNumRows; ++i)
+    {
+        aFormula = "=$B" + OUString::number(i+1) + " + 1";
+        m_pDoc->SetFormula(ScAddress(0, i, 0),
+                           aFormula,
+                           formula::FormulaGrammar::GRAM_NATIVE_UI);
+    }
+    // Column B
+    for (size_t i = 0; i < nNumRows; ++i)
+    {
+        aFormula = "=$C" + OUString::number(i+1) + " + 1";
+        m_pDoc->SetFormula(ScAddress(1, i, 0),
+                           aFormula,
+                           formula::FormulaGrammar::GRAM_NATIVE_UI);
+    }
+
+    // Column C has no FG but a cell at C500 that references A499
+    m_pDoc->SetFormula(ScAddress(2, 499, 0), // C500
+                       "=$A499 + 1",
+                       formula::FormulaGrammar::GRAM_NATIVE_UI);
+    m_xDocShell->DoHardRecalc();
+
+    size_t nExpected = 0;
+    for (size_t i = 0; i < nNumRows; ++i)
+    {
+        OString aMsg = "Value at cell A" + OString::number(i+1);
+        nExpected = 2;
+        if (i == 499)  // A500 must have value = 5
+            nExpected = 5;
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), nExpected, static_cast<size_t>(m_pDoc->GetValue(0, i, 0)));
+        aMsg = "Value at cell B" + OString::number(i+1);
+        nExpected = 1;
+        if (i == 499)  // B500 must have value = 4
+            nExpected = 4;
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), nExpected, static_cast<size_t>(m_pDoc->GetValue(1, i, 0)));
+    }
+
+    // C500 must have value = 3
+    nExpected = 3;
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Value at cell C500", nExpected, static_cast<size_t>(m_pDoc->GetValue(2, 499, 0)));
+    m_pDoc->DeleteTab(0);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(ScParallelismTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit 24afa5ddbecf54b545b6ff966af1521b8c1b8984
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date:   Fri Jul 6 04:37:01 2018 +0530

    Generalize FG cycle detection for...
    
    ...cycles involving a mix of formula-groups and plain
    formula-cells which are not grouped.
    
    This fixes a crash in tdf#104213/1
    
    Change-Id: I63b8b7379e4e5eaf322a3318f061a9e5fbc931ef
    Reviewed-on: https://gerrit.libreoffice.org/57031
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index a9df1a3be625..34c578076d97 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -67,7 +67,6 @@ public:
     SvNumFormatType mnFormatType;
     bool mbInvariant:1;
     bool mbSubTotal:1;
-    bool mbSeenInPath:1; // For detecting cycle of formula groups
     bool mbPartOfCycle:1; // To flag FG's part of a cycle
 
     sal_uInt8 meCalcState;
@@ -134,6 +133,7 @@ private:
                                                       number formats as hard number format */
     bool            mbPostponedDirty : 1;   // if cell needs to be set dirty later
     bool            mbIsExtRef       : 1; // has references in ScExternalRefManager; never cleared after set
+    bool            mbSeenInPath     : 1; // For detecting cycle involving formula groups and singleton formulacells
 
     /**
      * Update reference in response to cell copy-n-paste.
@@ -453,6 +453,8 @@ public:
     bool IsPostponedDirty() const { return mbPostponedDirty;}
 
     void SetIsExtRef() { mbIsExtRef = true; }
+    bool GetSeenInPath() { return mbSeenInPath; }
+    void SetSeenInPath(bool bSet) { mbSeenInPath = bSet; }
 
 #if DUMP_COLUMN_STORAGE
     void Dump() const;
diff --git a/sc/inc/recursionhelper.hxx b/sc/inc/recursionhelper.hxx
index 030e52c04b7c..b2d21daa378b 100644
--- a/sc/inc/recursionhelper.hxx
+++ b/sc/inc/recursionhelper.hxx
@@ -46,7 +46,7 @@ typedef ::std::list< ScFormulaRecursionEntry > ScFormulaRecursionList;
 class ScRecursionHelper
 {
     typedef ::std::stack< ScFormulaCell* >  ScRecursionInIterationStack;
-    typedef ::std::vector< ScFormulaCellGroup* > ScFGList;
+    typedef ::std::vector< ScFormulaCell* > ScFGList;
     ScFormulaRecursionList              aRecursionFormulas;
     ScFormulaRecursionList::iterator    aInsertPos;
     ScFormulaRecursionList::iterator    aLastIterationStart;
@@ -54,6 +54,8 @@ class ScRecursionHelper
     ScFGList                            aFGList;
     sal_uInt16                              nRecursionCount;
     sal_uInt16                              nIteration;
+    // Count of ScFormulaCell::CheckComputeDependencies in current call-stack.
+    sal_uInt16                              nDependencyComputationLevel;
     bool                                bInRecursionReturn;
     bool                                bDoingRecursion;
     bool                                bInIterationReturn;
@@ -68,6 +70,9 @@ public:
     sal_uInt16  GetRecursionCount() const       { return nRecursionCount; }
     void    IncRecursionCount()             { ++nRecursionCount; }
     void    DecRecursionCount()             { --nRecursionCount; }
+    sal_uInt16 GetDepComputeLevel()         { return nDependencyComputationLevel; }
+    void    IncDepComputeLevel()            { ++nDependencyComputationLevel; }
+    void    DecDepComputeLevel()            { --nDependencyComputationLevel; }
     /// A pure recursion return, no iteration.
     bool    IsInRecursionReturn() const     { return bInRecursionReturn &&
         !bInIterationReturn; }
@@ -99,9 +104,10 @@ public:
 
     void Clear();
 
-    /** Detects whether the formula-group is part of a simple cycle of formula-groups. */
-    bool PushFormulaGroup(ScFormulaCellGroup* pGrp);
+    /** Detects a simple cycle involving formula-groups and singleton formula-cells. */
+    bool PushFormulaGroup(ScFormulaCell* pCell);
     void PopFormulaGroup();
+    bool AnyParentFGInCycle();
 };
 
 /** A class to wrap ScRecursionHelper::PushFormulaGroup(),
@@ -113,8 +119,18 @@ class ScFormulaGroupCycleCheckGuard
     bool mbShouldPop;
 public:
     ScFormulaGroupCycleCheckGuard() = delete;
-    ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCellGroup* pGrp);
+    ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCell* pCell);
     ~ScFormulaGroupCycleCheckGuard();
+
+};
+
+class ScFormulaGroupDependencyComputeGuard
+{
+    ScRecursionHelper& mrRecHelper;
+public:
+    ScFormulaGroupDependencyComputeGuard() = delete;
+    ScFormulaGroupDependencyComputeGuard(ScRecursionHelper& rRecursionHelper);
+    ~ScFormulaGroupDependencyComputeGuard();
 };
 
 #endif // INCLUDED_SC_INC_RECURSIONHELPER_HXX
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 5ef16b9bf2c6..21f38f54711d 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2855,16 +2855,32 @@ bool ScColumn::HandleRefArrayForParallelism( SCROW nRow1, SCROW nRow2, const ScF
                 size_t nEnd = std::min(it->size, nOffset+nRowsToRead); // last row + 1
                 sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
                 std::advance(itCell, nOffset);
+                // Loop inside the formula block.
                 for (size_t i = nOffset; i < nEnd; ++itCell, ++i)
                 {
-                    // Loop inside the formula block.
+                    // Check if itCell is already in path.
+                    // If yes use a cycle guard to mark all elements of the cycle
+                    // and return false
+                    const ScFormulaCellGroupRef& mxGroupChild = (*itCell)->GetCellGroup();
+                    ScFormulaCell* pChildTopCell = mxGroupChild ? mxGroupChild->mpTopCell : *itCell;
+                    if (pChildTopCell->GetSeenInPath())
+                    {
+                        ScRecursionHelper& rRecursionHelper = GetDoc()->GetRecursionHelper();
+                        ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, pChildTopCell);
+                        return false;
+                    }
+
                     (*itCell)->MaybeInterpret();
 
                     // child cell's Interpret could result in calling dependency calc
                     // and that could detect a cycle involving mxGroup
                     // and do early exit in that case.
                     if (mxGroup->mbPartOfCycle)
+                    {
+                        // Set itCell as dirty as itCell may be interpreted in InterpretTail()
+                        (*itCell)->SetDirtyVar();
                         return false;
+                    }
                 }
                 nRow += nEnd - nOffset;
                 break;
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 5c79b1780adb..e370deaacb6c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -526,7 +526,6 @@ ScFormulaCellGroup::ScFormulaCellGroup() :
     mnFormatType(SvNumFormatType::NUMBER),
     mbInvariant(false),
     mbSubTotal(false),
-    mbSeenInPath(false),
     mbPartOfCycle(false),
     meCalcState(sc::GroupCalcEnabled)
 {
@@ -628,6 +627,7 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) :
     mbAllowNumberFormatChange(false),
     mbPostponedDirty(false),
     mbIsExtRef(false),
+    mbSeenInPath(false),
     aPos(rPos)
 {
 }
@@ -659,6 +659,7 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
     mbAllowNumberFormatChange(false),
     mbPostponedDirty(false),
     mbIsExtRef(false),
+    mbSeenInPath(false),
     aPos(rPos)
 {
     Compile( rFormula, true, eGrammar );    // bNoListening, Insert does that
@@ -693,6 +694,7 @@ ScFormulaCell::ScFormulaCell(
     mbAllowNumberFormatChange(false),
     mbPostponedDirty(false),
     mbIsExtRef(false),
+    mbSeenInPath(false),
     aPos(rPos)
 {
     assert(pArray); // Never pass a NULL pointer here.
@@ -742,6 +744,7 @@ ScFormulaCell::ScFormulaCell(
     mbAllowNumberFormatChange(false),
     mbPostponedDirty(false),
     mbIsExtRef(false),
+    mbSeenInPath(false),
     aPos(rPos)
 {
     // RPN array generation
@@ -790,6 +793,7 @@ ScFormulaCell::ScFormulaCell(
     mbAllowNumberFormatChange(false),
     mbPostponedDirty(false),
     mbIsExtRef(false),
+    mbSeenInPath(false),
     aPos(rPos)
 {
     if (bSubTotal)
@@ -821,6 +825,7 @@ ScFormulaCell::ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const
     mbAllowNumberFormatChange(false),
     mbPostponedDirty(false),
     mbIsExtRef(false),
+    mbSeenInPath(false),
     aPos(rPos)
 {
     pCode = rCell.pCode->Clone();
@@ -1474,12 +1479,11 @@ void ScFormulaCell::Interpret()
 {
     ScRecursionHelper& rRecursionHelper = pDocument->GetRecursionHelper();
 
-    if (mxGroup && mxGroup->mbSeenInPath)
+    ScFormulaCell* pTopCell = mxGroup ? mxGroup->mpTopCell : this;
+
+    if (pTopCell->mbSeenInPath && rRecursionHelper.GetDepComputeLevel())
     {
-        // This call arose from a dependency calculation and
-        // we just found a cycle.
-        // This will mark all elements in the cycle as parts-of-cycle
-        ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, mxGroup.get());
+        ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, pTopCell);
         return;
     }
 
@@ -1541,15 +1545,25 @@ void ScFormulaCell::Interpret()
 #if DEBUG_CALCULATION
         aDC.enterGroup();
 #endif
-
+        bool bPartOfCycleBefore = mxGroup && mxGroup->mbPartOfCycle;
         bool bGroupInterpreted = InterpretFormulaGroup();
+        bool bPartOfCycleAfter = mxGroup && mxGroup->mbPartOfCycle;
 
 #if DEBUG_CALCULATION
         aDC.leaveGroup();
 #endif
         if (!bGroupInterpreted)
         {
-            ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, mxGroup.get());
+            // Dependency calc inside InterpretFormulaGroup() failed due to
+            // detection of a cycle and there are parent FG's in the cycle.
+            // Skip InterpretTail() in such cases, only run InterpretTail for the "cycle-starting" FG
+            if (!bPartOfCycleBefore && bPartOfCycleAfter && rRecursionHelper.AnyParentFGInCycle())
+            {
+                pDocument->DecInterpretLevel();
+                return;
+            }
+
+            ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, this);
             InterpretTail( pDocument->GetNonThreadedContext(), SCITP_NORMAL);
         }
 
@@ -4331,6 +4345,7 @@ struct ScDependantsCalculator
         // Partially from ScGroupTokenConverter::convert in sc/source/core/data/grouptokenconverter.cxx
 
         ScRangeList aRangeList;
+        bool bHasSelfReferences = false;
         for (auto p: mrCode.RPNTokens())
         {
             switch (p->GetType())
@@ -4346,7 +4361,10 @@ struct ScDependantsCalculator
                     if (aRef.IsRowRel())
                     {
                         if (isSelfReferenceRelative(aRefPos, aRef.Row()))
-                            return false;
+                        {
+                            bHasSelfReferences = true;
+                            continue;
+                        }
 
                         // Trim data array length to actual data range.
                         SCROW nTrimLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), mnLen);
@@ -4357,7 +4375,10 @@ struct ScDependantsCalculator
                     else
                     {
                         if (isSelfReferenceAbsolute(aRefPos))
-                            return false;
+                        {
+                            bHasSelfReferences = true;
+                            continue;
+                        }
 
                         aRangeList.Join(ScRange(aRefPos.Col(), aRefPos.Row(), aRefPos.Tab()));
                     }
@@ -4377,22 +4398,37 @@ struct ScDependantsCalculator
                     if (bIsRef1RowRel)
                     {
                         if (isSelfReferenceRelative(aAbs.aStart, aRef.Ref1.Row()))
-                            return false;
+                        {
+                            bHasSelfReferences = true;
+                            continue;
+                        }
                     }
                     else if (isSelfReferenceAbsolute(aAbs.aStart))
-                        return false;
+                    {
+                        bHasSelfReferences = true;
+                        continue;
+                    }
 
                     bool bIsRef2RowRel = aRef.Ref2.IsRowRel();
                     if (bIsRef2RowRel)
                     {
                         if (isSelfReferenceRelative(aAbs.aEnd, aRef.Ref2.Row()))
-                            return false;
+                        {
+                            bHasSelfReferences = true;
+                            continue;
+                        }
                     }
                     else if (isSelfReferenceAbsolute(aAbs.aEnd))
-                        return false;
+                    {
+                        bHasSelfReferences = true;
+                        continue;
+                    }
 
                     if (isDoubleRefSpanGroupRange(aAbs, bIsRef1RowRel, bIsRef2RowRel))
-                        return false;
+                    {
+                        bHasSelfReferences = true;
+                        continue;
+                    }
 
                     // Row reference is relative.
                     bool bAbsLast = !aRef.Ref2.IsRowRel();
@@ -4421,6 +4457,9 @@ struct ScDependantsCalculator
             }
         }
 
+        // Compute dependencies irrespective of the presence of any self references.
+        // These dependencies would get computed via InterpretTail anyway when we disable group calc, so lets do it now.
+        // The advantage is that the FG's get marked for cycles early if present, and can avoid lots of complications.
         for (size_t i = 0; i < aRangeList.size(); ++i)
         {
             const ScRange & rRange = aRangeList[i];
@@ -4432,7 +4471,7 @@ struct ScDependantsCalculator
                     return false;
             }
         }
-        return true;
+        return !bHasSelfReferences;
     }
 };
 
@@ -4503,7 +4542,7 @@ bool ScFormulaCell::CheckComputeDependencies(sc::FormulaLogger::GroupScope& rSco
 
     bool bOKToParallelize = false;
     {
-        ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, mxGroup.get());
+        ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, this);
         if (mxGroup->mbPartOfCycle)
         {
             mxGroup->meCalcState = sc::GroupCalcDisabled;
@@ -4511,6 +4550,7 @@ bool ScFormulaCell::CheckComputeDependencies(sc::FormulaLogger::GroupScope& rSco
             return false;
         }
 
+        ScFormulaGroupDependencyComputeGuard aDepComputeGuard(rRecursionHelper);
         ScDependantsCalculator aCalculator(*pDocument, *pCode, *this, mxGroup->mpTopCell->aPos);
         bOKToParallelize = aCalculator.DoIt();
     }
diff --git a/sc/source/core/tool/recursionhelper.cxx b/sc/source/core/tool/recursionhelper.cxx
index 8cfef9776e35..dd5be99c7155 100644
--- a/sc/source/core/tool/recursionhelper.cxx
+++ b/sc/source/core/tool/recursionhelper.cxx
@@ -13,6 +13,7 @@
 void ScRecursionHelper::Init()
 {
     nRecursionCount    = 0;
+    nDependencyComputationLevel = 0;
     bInRecursionReturn = bDoingRecursion = bInIterationReturn = false;
     aInsertPos = GetIterationEnd();
     ResetIteration();
@@ -96,12 +97,22 @@ void ScRecursionHelper::Clear()
     Init();
 }
 
-bool ScRecursionHelper::PushFormulaGroup(ScFormulaCellGroup* pGrp)
+static ScFormulaCell* lcl_GetTopCell(ScFormulaCell* pCell)
 {
-    if (!pGrp)
-        return false;
+    if (!pCell)
+        return nullptr;
+
+    const ScFormulaCellGroupRef& mxGroup = pCell->GetCellGroup();
+    if (!mxGroup)
+        return pCell;
+    return mxGroup->mpTopCell;
+}
+
+bool ScRecursionHelper::PushFormulaGroup(ScFormulaCell* pCell)
+{
+    assert(pCell);
 
-    if (pGrp->mbSeenInPath)
+    if (pCell->GetSeenInPath())
     {
         // Found a simple cycle of formula-groups.
         // Disable group calc for all elements of this cycle.
@@ -111,14 +122,16 @@ bool ScRecursionHelper::PushFormulaGroup(ScFormulaCellGroup* pGrp)
         {
             --nIdx;
             assert(nIdx >= 0);
-            aFGList[nIdx]->mbPartOfCycle = true;
-        } while (aFGList[nIdx] != pGrp);
+            const ScFormulaCellGroupRef& mxGroup = aFGList[nIdx]->GetCellGroup();
+            if (mxGroup)
+                mxGroup->mbPartOfCycle = true;
+        } while (aFGList[nIdx] != pCell);
 
         return false;
     }
 
-    pGrp->mbSeenInPath = true;
-    aFGList.push_back(pGrp);
+    pCell->SetSeenInPath(true);
+    aFGList.push_back(pCell);
     return true;
 }
 
@@ -126,15 +139,34 @@ void ScRecursionHelper::PopFormulaGroup()
 {
     if (aFGList.empty())
         return;
-    ScFormulaCellGroup* pGrp = aFGList.back();
-    pGrp->mbSeenInPath = false;
+    ScFormulaCell* pCell = aFGList.back();
+    pCell->SetSeenInPath(false);
     aFGList.pop_back();
 }
 
-ScFormulaGroupCycleCheckGuard::ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCellGroup* pGrp) :
+bool ScRecursionHelper::AnyParentFGInCycle()
+{
+    sal_Int32 nIdx = aFGList.size() - 1;
+    while (nIdx >= 0)
+    {
+        const ScFormulaCellGroupRef& mxGroup = aFGList[nIdx]->GetCellGroup();
+        if (mxGroup)
+            return mxGroup->mbPartOfCycle;
+        --nIdx;
+    };
+    return false;
+}
+
+ScFormulaGroupCycleCheckGuard::ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCell* pCell) :
     mrRecHelper(rRecursionHelper)
 {
-    mbShouldPop = mrRecHelper.PushFormulaGroup(pGrp);
+    if (pCell)
+    {
+        pCell = lcl_GetTopCell(pCell);
+        mbShouldPop = mrRecHelper.PushFormulaGroup(pCell);
+    }
+    else
+        mbShouldPop = false;
 }
 
 ScFormulaGroupCycleCheckGuard::~ScFormulaGroupCycleCheckGuard()
@@ -143,4 +175,15 @@ ScFormulaGroupCycleCheckGuard::~ScFormulaGroupCycleCheckGuard()
         mrRecHelper.PopFormulaGroup();
 }
 
+ScFormulaGroupDependencyComputeGuard::ScFormulaGroupDependencyComputeGuard(ScRecursionHelper& rRecursionHelper) :
+    mrRecHelper(rRecursionHelper)
+{
+    mrRecHelper.IncDepComputeLevel();
+}
+
+ScFormulaGroupDependencyComputeGuard::~ScFormulaGroupDependencyComputeGuard()
+{
+    mrRecHelper.DecDepComputeLevel();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 0f95580d392bb1a6f103f3a1543fb61a16f9f263
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date:   Thu Jul 5 16:30:37 2018 +0530

    Use cycle guard for calls to InterpretTail too
    
    Some formula-groups even though a part of a cycle
    may get skipped from getting flagged(mbPartOfCycle)
    in the dependency calculator because it has other
    problems like self references. Such FG's can be
    caught when they through InterpretTail() by having
    a cycle guard there.
    
    Concretely it fixes a crash in the bugdoc of
    tdf#94271-2.
    
    Change-Id: I508df88804c7cd8dbbb6497188b1c9559bec3aa6
    Reviewed-on: https://gerrit.libreoffice.org/57004
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 96aabc5ae07c..5c79b1780adb 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1540,14 +1540,18 @@ void ScFormulaCell::Interpret()
 
 #if DEBUG_CALCULATION
         aDC.enterGroup();
+#endif
+
         bool bGroupInterpreted = InterpretFormulaGroup();
+
+#if DEBUG_CALCULATION
         aDC.leaveGroup();
+#endif
         if (!bGroupInterpreted)
+        {
+            ScFormulaGroupCycleCheckGuard aCycleCheckGuard(rRecursionHelper, mxGroup.get());
             InterpretTail( pDocument->GetNonThreadedContext(), SCITP_NORMAL);
-#else
-        if (!InterpretFormulaGroup())
-            InterpretTail( pDocument->GetNonThreadedContext(), SCITP_NORMAL);
-#endif
+        }
 
         pDocument->DecInterpretLevel();
     }
diff --git a/sc/source/core/tool/recursionhelper.cxx b/sc/source/core/tool/recursionhelper.cxx
index 0c185dba3c6b..8cfef9776e35 100644
--- a/sc/source/core/tool/recursionhelper.cxx
+++ b/sc/source/core/tool/recursionhelper.cxx
@@ -98,7 +98,9 @@ void ScRecursionHelper::Clear()
 
 bool ScRecursionHelper::PushFormulaGroup(ScFormulaCellGroup* pGrp)
 {
-    assert(pGrp);
+    if (!pGrp)
+        return false;
+
     if (pGrp->mbSeenInPath)
     {
         // Found a simple cycle of formula-groups.
commit 9ceeb4619ba762c47589023d99c43c774caab441
Author: Tamas Bunth <tamas.bunth at collabora.co.uk>
Date:   Tue Jun 26 13:45:40 2018 +0200

    HSQLDB Migration: overwrite backup xml
    
    Change-Id: I080568f2d278e8a7153188497e3987217d9d188f
    Reviewed-on: https://gerrit.libreoffice.org/56464
    Tested-by: Jenkins
    Reviewed-by: Tamás Bunth <btomi96 at gmail.com>

diff --git a/dbaccess/source/core/dataaccess/datasource.cxx b/dbaccess/source/core/dataaccess/datasource.cxx
index 29d5816bc043..597c5a6d560b 100644
--- a/dbaccess/source/core/dataaccess/datasource.cxx
+++ b/dbaccess/source/core/dataaccess/datasource.cxx
@@ -599,8 +599,12 @@ Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const OUString
         {
             // back up content xml file if migration was successful
             Reference<XStorage> xRootStorage = m_pImpl->getOrCreateRootStorage();
+
+            constexpr char BACKUP_XML_NAME[] = "content_before_migration.xml";
+            if(xRootStorage->isStreamElement(BACKUP_XML_NAME))
+                xRootStorage->removeElement(BACKUP_XML_NAME);
             xRootStorage->copyElementTo("content.xml", xRootStorage,
-                    "content_before_migration.xml");
+                BACKUP_XML_NAME);
 
             m_pImpl->m_sConnectURL = "sdbc:embedded:firebird";
         }
commit 9eb929aa8cb3f5b0fee1264119a55cdd8cbe8f0e
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Jul 6 09:46:01 2018 +0200

    connectivity: turn on clang-format for the Writer driver
    
    I (tried to) keep this consistent locally with astyle in the past,
    switching to clang-format means consistency is enforced by CI.
    
    Change-Id: I1016e253c6536b207a05328e5f6f13de37889588
    Reviewed-on: https://gerrit.libreoffice.org/57046
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins

diff --git a/connectivity/source/drivers/writer/WCatalog.cxx b/connectivity/source/drivers/writer/WCatalog.cxx
index 9d273e201945..0baa759da14c 100644
--- a/connectivity/source/drivers/writer/WCatalog.cxx
+++ b/connectivity/source/drivers/writer/WCatalog.cxx
@@ -34,21 +34,21 @@ namespace connectivity
 {
 namespace writer
 {
-
-OWriterCatalog::OWriterCatalog(OWriterConnection* pConnection) : file::OFileCatalog(pConnection)
+OWriterCatalog::OWriterCatalog(OWriterConnection* pConnection)
+    : file::OFileCatalog(pConnection)
 {
 }
 
 void OWriterCatalog::refreshTables()
 {
-    ::std::vector< OUString> aVector;
+    ::std::vector<OUString> aVector;
     uno::Sequence<OUString> aTypes;
     OWriterConnection::ODocHolder aDocHolder(static_cast<OWriterConnection*>(m_pConnection));
-    uno::Reference< sdbc::XResultSet > xResult = m_xMetaData->getTables(uno::Any(), "%", "%", aTypes);
+    uno::Reference<sdbc::XResultSet> xResult = m_xMetaData->getTables(uno::Any(), "%", "%", aTypes);
 
     if (xResult.is())
     {
-        uno::Reference< sdbc::XRow > xRow(xResult, uno::UNO_QUERY);
+        uno::Reference<sdbc::XRow> xRow(xResult, uno::UNO_QUERY);
         while (xResult->next())
             aVector.push_back(xRow->getString(3));
     }
diff --git a/connectivity/source/drivers/writer/WConnection.cxx b/connectivity/source/drivers/writer/WConnection.cxx
index cede7c409b0e..26234ed5e7cf 100644
--- a/connectivity/source/drivers/writer/WConnection.cxx
+++ b/connectivity/source/drivers/writer/WConnection.cxx
@@ -40,20 +40,22 @@ namespace connectivity
 {
 namespace writer
 {
-
-OWriterConnection::OWriterConnection(ODriver* _pDriver) : OConnection(_pDriver),m_nDocCount(0)
+OWriterConnection::OWriterConnection(ODriver* _pDriver)
+    : OConnection(_pDriver)
+    , m_nDocCount(0)
 {
 }
 
 OWriterConnection::~OWriterConnection() = default;
 
-void OWriterConnection::construct(const OUString& rURL, const uno::Sequence< beans::PropertyValue >& rInfo)
+void OWriterConnection::construct(const OUString& rURL,
+                                  const uno::Sequence<beans::PropertyValue>& rInfo)
 {
     //  open file
 
     sal_Int32 nLen = rURL.indexOf(':');
-    nLen = rURL.indexOf(':',nLen+1);
-    OUString aDSN(rURL.copy(nLen+1));
+    nLen = rURL.indexOf(':', nLen + 1);
+    OUString aDSN(rURL.copy(nLen + 1));
 
     m_aFileName = aDSN;
     INetURLObject aURL;
@@ -73,8 +75,8 @@ void OWriterConnection::construct(const OUString& rURL, const uno::Sequence< bea
     m_sPassword.clear();
     const char pPwd[] = "password";
 
-    const beans::PropertyValue* pIter  = rInfo.getConstArray();
-    const beans::PropertyValue* pEnd   = pIter + rInfo.getLength();
+    const beans::PropertyValue* pIter = rInfo.getConstArray();
+    const beans::PropertyValue* pEnd = pIter + rInfo.getLength();
     for (; pIter != pEnd; ++pIter)
     {
         if (pIter->Name == pPwd)
@@ -104,18 +106,18 @@ uno::Reference<text::XTextDocument> const& OWriterConnection::acquireDoc()
     if (!m_sPassword.isEmpty())
     {
         const sal_Int32 nPos = aArgs.getLength();
-        aArgs.realloc(nPos+1);
+        aArgs.realloc(nPos + 1);
         aArgs[nPos].Name = "Password";
         aArgs[nPos].Value <<= m_sPassword;
     }
 
-    uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(getDriver()->getComponentContext());
-    uno::Reference< lang::XComponent > xComponent;
+    uno::Reference<frame::XDesktop2> xDesktop
+        = frame::Desktop::create(getDriver()->getComponentContext());
+    uno::Reference<lang::XComponent> xComponent;
     uno::Any aLoaderException;
     try
     {
-        xComponent = xDesktop->loadComponentFromURL(
-                         m_aFileName, "_blank", 0, aArgs);
+        xComponent = xDesktop->loadComponentFromURL(m_aFileName, "_blank", 0, aArgs);
     }
     catch (const uno::Exception&)
     {
@@ -133,13 +135,13 @@ uno::Reference<text::XTextDocument> const& OWriterConnection::acquireDoc()
             uno::Exception aLoaderError;
             OSL_VERIFY(aLoaderException >>= aLoaderError);
 
-            SAL_WARN("connectivity.writer", "empty m_xDoc, exception type: " << aLoaderException.getValueTypeName() << ", error message: " << aLoaderError);
+            SAL_WARN("connectivity.writer",
+                     "empty m_xDoc, exception type: " << aLoaderException.getValueTypeName()
+                                                      << ", error message: " << aLoaderError);
         }
 
         const OUString sError(m_aResources.getResourceStringWithSubstitution(
-                                  STR_COULD_NOT_LOAD_FILE,
-                                  "$filename$", m_aFileName
-                              ));
+            STR_COULD_NOT_LOAD_FILE, "$filename$", m_aFileName));
         ::dbtools::throwGenericSQLException(sError, *this);
     }
     osl_atomic_increment(&m_nDocCount);
@@ -154,7 +156,7 @@ void OWriterConnection::releaseDoc()
     {
         if (m_xCloseVetoButTerminateListener.is())
         {
-            m_xCloseVetoButTerminateListener->stop();   // dispose m_xDoc
+            m_xCloseVetoButTerminateListener->stop(); // dispose m_xDoc
             m_xCloseVetoButTerminateListener.clear();
         }
         m_xDoc.clear();
@@ -168,7 +170,7 @@ void OWriterConnection::disposing()
     m_nDocCount = 0;
     if (m_xCloseVetoButTerminateListener.is())
     {
-        m_xCloseVetoButTerminateListener->stop();   // dispose m_xDoc
+        m_xCloseVetoButTerminateListener->stop(); // dispose m_xDoc
         m_xCloseVetoButTerminateListener.clear();
     }
     m_xDoc.clear();
@@ -178,17 +180,15 @@ void OWriterConnection::disposing()
 
 // XServiceInfo
 
+IMPLEMENT_SERVICE_INFO(OWriterConnection, "com.sun.star.sdbc.drivers.writer.Connection",
+                       "com.sun.star.sdbc.Connection")
 
-IMPLEMENT_SERVICE_INFO(OWriterConnection, "com.sun.star.sdbc.drivers.writer.Connection", "com.sun.star.sdbc.Connection")
-
-
-uno::Reference< sdbc::XDatabaseMetaData > SAL_CALL OWriterConnection::getMetaData()
+uno::Reference<sdbc::XDatabaseMetaData> SAL_CALL OWriterConnection::getMetaData()
 {
     ::osl::MutexGuard aGuard(m_aMutex);
     checkDisposed(OConnection_BASE::rBHelper.bDisposed);
 
-
-    uno::Reference< sdbc::XDatabaseMetaData > xMetaData = m_xMetaData;
+    uno::Reference<sdbc::XDatabaseMetaData> xMetaData = m_xMetaData;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list