sc/CppunitTest_sc_basic_types_test.mk |   35 +++++
 sc/Module_sc.mk                       |    1 
 sc/inc/address.hxx                    |  217 ++++++++++++++++------------------
 sc/qa/unit/ScAddressTest.cxx          |   78 ++++++++++++
 4 files changed, 217 insertions(+), 114 deletions(-)

New commits:
commit ee1a2299931c33470fc28c3e5f26f69d3c35b0d8
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Tue Aug 26 21:56:16 2025 +0200
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Aug 27 16:52:10 2025 +0200

    sc: use three-way comparison to reduce the number of operators
    
    Change-Id: Ie3c409b0b8b7f66e4d6e7bd548b798a6474e5250
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190256
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 7c19ef3925ac..61d895c443c2 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -393,33 +393,17 @@ public:
         return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == 
rAddress.nTab;
     }
 
-    /** Less than ordered by tab,col,row. */
-    constexpr bool operator<(const ScAddress& rAddress) const
+    constexpr auto operator<=>(const ScAddress& rAddress) const
     {
-        if (nTab == rAddress.nTab)
+        if (auto bTabResult = nTab <=> rAddress.nTab; bTabResult == 0)
         {
-            if (nCol == rAddress.nCol)
-                return nRow < rAddress.nRow;
+            if (auto bColResult = nCol <=> rAddress.nCol; bColResult == 0)
+                return nRow <=> rAddress.nRow;
             else
-                return nCol < rAddress.nCol;
+                return bColResult;
         }
         else
-            return nTab < rAddress.nTab;
-    }
-
-    constexpr bool operator<=( const ScAddress& rAddress ) const
-    {
-        return operator<(rAddress) || operator==(rAddress);
-    }
-
-    constexpr bool operator>(const ScAddress& rAddress) const
-    {
-        return !(operator<=(rAddress));
-    }
-
-    constexpr bool operator>=(const ScAddress& rAddress) const
-    {
-        return !(operator<(rAddress));
+            return bTabResult;
     }
 
     /** Less than ordered by tab,row,col as needed by row-wise import/export */
commit 4ad007de60abb686a080680380893b3aebc05daa
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Tue Aug 26 21:52:14 2025 +0200
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Aug 27 16:52:01 2025 +0200

    sc: make ScAddress constexpr and clean-up
    
    - remove the inlines which are implicit anyway
    - make compile type tests of the class
    - move inline methods into body
    
    Change-Id: If2656c1b750a300bc0ed589bc7ea6aec27b3237a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190255
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Tested-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sc/CppunitTest_sc_basic_types_test.mk 
b/sc/CppunitTest_sc_basic_types_test.mk
new file mode 100644
index 000000000000..072ec157c989
--- /dev/null
+++ b/sc/CppunitTest_sc_basic_types_test.mk
@@ -0,0 +1,35 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,sc_basic_types_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,sc_basic_types_test,\
+    sc/qa/unit/ScAddressTest \
+))
+
+$(eval $(call gb_CppunitTest_use_external,sc_basic_types_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_set_include,sc_basic_types_test,\
+    -I$(SRCDIR)/sc/source/ui/inc \
+    -I$(SRCDIR)/sc/source/core/inc \
+    -I$(SRCDIR)/sc/inc \
+    $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,sc_basic_types_test,\
+    sal \
+))
+
+# Needed for include/test/cppunitasserthelper.hxx
+$(eval $(call gb_CppunitTest_use_sdk_api,sc_basic_types_test))
+
+
+# vim: set noet sw=4 ts=4:
diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk
index 3e1dc0d120e0..64fdfca08289 100644
--- a/sc/Module_sc.mk
+++ b/sc/Module_sc.mk
@@ -61,6 +61,7 @@ $(eval $(call gb_Module_add_check_targets,sc,\
        CppunitTest_sc_filters_test \
        CppunitTest_sc_mark_test \
        CppunitTest_sc_core \
+       CppunitTest_sc_basic_types_test \
        CppunitTest_sc_dataprovider \
        CppunitTest_sc_cache_test \
        CppunitTest_sc_parallelism \
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 02bd6579450e..7c19ef3925ac 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -248,77 +248,107 @@ public:
         {}
     };
 
-    ScAddress() :
+    constexpr ScAddress() :
         nRow(0), nCol(0), nTab(0)
     {}
-    ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) :
+
+    constexpr ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) :
         nRow(nRowP), nCol(nColP), nTab(nTabP)
     {}
+
     /** coverity[uninit_member] - Yes, it is what it seems to be: 
Uninitialized.
         May be used for performance reasons if it is initialized by other 
means. */
-    ScAddress( Uninitialized )
+    constexpr ScAddress( Uninitialized )
     {}
-    ScAddress( InitializeInvalid ) :
+
+    constexpr ScAddress( InitializeInvalid ) :
         nRow(-1), nCol(-1), nTab(-1)
     {}
-    ScAddress( const ScAddress& rAddress ) :
+
+    constexpr ScAddress( const ScAddress& rAddress ) :
         nRow(rAddress.nRow), nCol(rAddress.nCol), nTab(rAddress.nTab)
     {}
-    inline ScAddress& operator=( const ScAddress& rAddress );
 
-    inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
+    constexpr ScAddress& operator=(const ScAddress& rAddress)
+    {
+        nCol = rAddress.nCol;
+        nRow = rAddress.nRow;
+        nTab = rAddress.nTab;
+        return *this;
+    }
 
-    SCROW Row() const
+    constexpr void Set(SCCOL nColP, SCROW nRowP, SCTAB nTabP)
+    {
+        nCol = nColP;
+        nRow = nRowP;
+        nTab = nTabP;
+    }
+
+    constexpr SCROW Row() const
     {
         return nRow;
     }
 
-    SCCOL Col() const
+    constexpr SCCOL Col() const
     {
         return nCol;
     }
-    SCTAB Tab() const
+
+    constexpr SCTAB Tab() const
     {
         return nTab;
     }
-    void SetRow( SCROW nRowP )
+
+    constexpr void SetRow( SCROW nRowP )
     {
         nRow = nRowP;
     }
-    void SetCol( SCCOL nColP )
+
+    constexpr void SetCol( SCCOL nColP )
     {
         nCol = nColP;
     }
-    void SetTab( SCTAB nTabP )
+
+    constexpr void SetTab( SCTAB nTabP )
     {
         nTab = nTabP;
     }
-    void SetInvalid()
+
+    constexpr void SetInvalid()
     {
         nRow = -1;
         nCol = -1;
         nTab = -1;
     }
-    bool IsValid() const
+
+    constexpr bool IsValid() const
     {
         return (nRow >= 0) && (nCol >= 0) && (nTab >= 0);
     }
 
-    inline void PutInOrder( ScAddress& rAddress );
+    constexpr void PutInOrder(ScAddress& rAddress)
+    {
+        ::PutInOrder(nCol, rAddress.nCol);
+        ::PutInOrder(nRow, rAddress.nRow);
+        ::PutInOrder(nTab, rAddress.nTab);
+    }
 
-    void IncRow( SCROW nDelta = 1 )
+    constexpr void IncRow( SCROW nDelta = 1 )
     {
-        nRow = sal::static_int_cast<SCROW>(nRow + nDelta);
+        nRow = static_cast<SCROW>(nRow + nDelta);
     }
-    void IncCol( SCCOL nDelta = 1 )
+
+    constexpr void IncCol( SCCOL nDelta = 1 )
     {
-        nCol = sal::static_int_cast<SCCOL>(nCol + nDelta);
+        nCol = static_cast<SCCOL>(nCol + nDelta);
     }
-    void IncTab( SCTAB nDelta = 1 )
+
+    constexpr void IncTab( SCTAB nDelta = 1 )
     {
-        nTab = sal::static_int_cast<SCTAB>(nTab + nDelta);
+        nTab = static_cast<SCTAB>(nTab + nDelta);
     }
-    void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
+
+    constexpr void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
     {
         nColP = nCol;
         nRowP = nRow;
@@ -358,13 +388,72 @@ public:
     [[nodiscard]] SC_DLLPUBLIC bool Move( SCCOL nDeltaX, SCROW nDeltaY, SCTAB 
nDeltaZ,
             ScAddress& rErrorPos, const ScDocument& rDoc );
 
-    inline bool operator==( const ScAddress& rAddress ) const;
-    inline bool operator!=( const ScAddress& rAddress ) const;
-    inline bool operator<( const ScAddress& rAddress ) const;
-    inline bool operator<=( const ScAddress& rAddress ) const;
-    inline bool lessThanByRow( const ScAddress& rAddress ) const;
+    constexpr bool operator==( const ScAddress& rAddress ) const
+    {
+        return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == 
rAddress.nTab;
+    }
 
-    inline size_t hash() const;
+    /** Less than ordered by tab,col,row. */
+    constexpr bool operator<(const ScAddress& rAddress) const
+    {
+        if (nTab == rAddress.nTab)
+        {
+            if (nCol == rAddress.nCol)
+                return nRow < rAddress.nRow;
+            else
+                return nCol < rAddress.nCol;
+        }
+        else
+            return nTab < rAddress.nTab;
+    }
+
+    constexpr bool operator<=( const ScAddress& rAddress ) const
+    {
+        return operator<(rAddress) || operator==(rAddress);
+    }
+
+    constexpr bool operator>(const ScAddress& rAddress) const
+    {
+        return !(operator<=(rAddress));
+    }
+
+    constexpr bool operator>=(const ScAddress& rAddress) const
+    {
+        return !(operator<(rAddress));
+    }
+
+    /** Less than ordered by tab,row,col as needed by row-wise import/export */
+    bool lessThanByRow(const ScAddress& rAddress) const
+    {
+        if (nTab == rAddress.nTab)
+        {
+            if (nRow == rAddress.nRow)
+                return nCol < rAddress.nCol;
+            else
+                return nRow < rAddress.nRow;
+        }
+        else
+            return nTab < rAddress.nTab;
+    }
+
+    size_t hash() const
+    {
+    #if SAL_TYPES_SIZEOFPOINTER == 8
+        // 16 bits for the columns, and 20 bits for the rows
+        return (static_cast<size_t>(nTab) << 36) ^
+               (static_cast<size_t>(nCol) << 20) ^
+                static_cast<size_t>(nRow);
+    #else
+        // Assume that there are not that many addresses with row > 2^16 AND 
column
+        // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
+        if (nRow <= 0xffff)
+            return (static_cast<size_t>(nTab) << 24) ^
+                (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
+        else
+            return (static_cast<size_t>(nTab) << 28) ^
+                (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
+    #endif
+    }
 
     /**
      * Create a human-readable string representation of the cell address.  You
@@ -390,90 +479,6 @@ inline std::basic_ostream<charT, traits> & operator 
<<(std::basic_ostream<charT,
     return stream;
 }
 
-inline void ScAddress::PutInOrder( ScAddress& rAddress )
-{
-    ::PutInOrder(nCol, rAddress.nCol);
-    ::PutInOrder(nRow, rAddress.nRow);
-    ::PutInOrder(nTab, rAddress.nTab);
-}
-
-inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
-{
-    nCol = nColP;
-    nRow = nRowP;
-    nTab = nTabP;
-}
-
-inline ScAddress& ScAddress::operator=( const ScAddress& rAddress )
-{
-    nCol = rAddress.nCol;
-    nRow = rAddress.nRow;
-    nTab = rAddress.nTab;
-    return *this;
-}
-
-inline bool ScAddress::operator==( const ScAddress& rAddress ) const
-{
-    return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == 
rAddress.nTab;
-}
-
-inline bool ScAddress::operator!=( const ScAddress& rAddress ) const
-{
-    return !operator==( rAddress );
-}
-
-/** Less than ordered by tab,col,row. */
-inline bool ScAddress::operator<( const ScAddress& rAddress ) const
-{
-    if (nTab == rAddress.nTab)
-    {
-        if (nCol == rAddress.nCol)
-            return nRow < rAddress.nRow;
-        else
-            return nCol < rAddress.nCol;
-    }
-    else
-        return nTab < rAddress.nTab;
-}
-
-inline bool ScAddress::operator<=( const ScAddress& rAddress ) const
-{
-    return operator<( rAddress ) || operator==( rAddress );
-}
-
-/** Less than ordered by tab,row,col as needed by row-wise import/export */
-inline bool ScAddress::lessThanByRow( const ScAddress& rAddress ) const
-{
-    if (nTab == rAddress.nTab)
-    {
-        if (nRow == rAddress.nRow)
-            return nCol < rAddress.nCol;
-        else
-            return nRow < rAddress.nRow;
-    }
-    else
-        return nTab < rAddress.nTab;
-}
-
-inline size_t ScAddress::hash() const
-{
-#if SAL_TYPES_SIZEOFPOINTER == 8
-    // 16 bits for the columns, and 20 bits for the rows
-    return (static_cast<size_t>(nTab) << 36) ^
-           (static_cast<size_t>(nCol) << 20) ^
-            static_cast<size_t>(nRow);
-#else
-    // Assume that there are not that many addresses with row > 2^16 AND column
-    // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
-    if (nRow <= 0xffff)
-        return (static_cast<size_t>(nTab) << 24) ^
-            (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
-    else
-        return (static_cast<size_t>(nTab) << 28) ^
-            (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
-#endif
-}
-
 struct ScAddressHashFunctor
 {
     size_t operator()( const ScAddress & rAddress ) const
@@ -482,7 +487,7 @@ struct ScAddressHashFunctor
     }
 };
 
-[[nodiscard]] inline bool ValidAddress( const ScAddress& rAddress, SCCOL 
nMaxCol, SCROW nMaxRow )
+[[nodiscard]] constexpr bool ValidAddress(const ScAddress& rAddress, SCCOL 
nMaxCol, SCROW nMaxRow)
 {
     return ValidCol(rAddress.Col(), nMaxCol) && ValidRow(rAddress.Row(), 
nMaxRow) && ValidTab(rAddress.Tab());
 }
diff --git a/sc/qa/unit/ScAddressTest.cxx b/sc/qa/unit/ScAddressTest.cxx
new file mode 100644
index 000000000000..97f17b79da38
--- /dev/null
+++ b/sc/qa/unit/ScAddressTest.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <address.hxx>
+
+#include <cppunit/plugin/TestPlugIn.h>
+
+// Compile time tests for ScAddress
+
+static_assert(ScAddress() == ScAddress(0, 0, 0));
+static_assert(ScAddress().IsValid() == true);
+static_assert(ScAddress(ScAddress::INITIALIZE_INVALID).IsValid() == false);
+
+// Equal, not Equal
+
+// Format is Col, Row, Tab and Col has priority over Row
+static_assert(ScAddress(0, 0, 0) != ScAddress(1, 0, 0)); // A1 != B1
+static_assert(ScAddress(0, 0, 0) != ScAddress(0, 1, 0)); // A1 != A2
+static_assert(ScAddress(0, 0, 0) != ScAddress(0, 0, 1)); // Sheet1:A1 != 
Sheet2:A1
+static_assert(ScAddress(0, 0, 0) == ScAddress(0, 0, 0)); // A1 == A1
+
+// Less
+
+static_assert(!(ScAddress(1, 0, 0) < ScAddress(1, 0, 0))); // B1 < B1
+static_assert(!(ScAddress(0, 1, 0) < ScAddress(0, 1, 0))); // A2 < A2
+static_assert(!(ScAddress(0, 0, 1) < ScAddress(0, 0, 1))); // Sheet2:A1 < 
Sheet2:A1
+
+static_assert(ScAddress(0, 0, 0) < ScAddress(1, 0, 0)); // A1 < B1
+static_assert(ScAddress(0, 1, 0) < ScAddress(1, 0, 0)); // A2 < B1
+static_assert(ScAddress(0, 10000, 0) < ScAddress(1, 0, 0)); // A10000 < B1
+static_assert(ScAddress(0, 10000, 0) < ScAddress(1, 10000, 0)); // A10000 < 
B10000
+static_assert(ScAddress(1, 0, 0) < ScAddress(1, 0, 1)); // Sheet1:A1 < 
Sheet2:A1
+
+// Less or Equal
+
+static_assert(ScAddress(1, 0, 0) <= ScAddress(1, 0, 0)); // B1 <= B1
+static_assert(ScAddress(0, 1, 0) <= ScAddress(0, 1, 0)); // A2 <= A2
+static_assert(ScAddress(0, 0, 1) <= ScAddress(0, 0, 1)); // Sheet2:A1 <= 
Sheet2:A1
+
+static_assert(ScAddress(0, 0, 0) <= ScAddress(1, 0, 0)); // A1 <= B1
+static_assert(ScAddress(0, 1, 0) <= ScAddress(1, 0, 0)); // A2 <= B1
+static_assert(ScAddress(0, 10000, 0) <= ScAddress(1, 0, 0)); // A10000 <= B1
+static_assert(ScAddress(0, 10000, 0) <= ScAddress(1, 10000, 0)); // A10000 <= 
B10000
+static_assert(ScAddress(1, 0, 0) <= ScAddress(1, 0, 1)); // Sheet1:A1 <= 
Sheet2:A1
+
+// More
+
+static_assert(!(ScAddress(1, 0, 0) > ScAddress(1, 0, 0))); // B1 > B1
+static_assert(!(ScAddress(0, 1, 0) > ScAddress(0, 1, 0))); // A2 > A2
+static_assert(!(ScAddress(0, 0, 1) > ScAddress(0, 0, 1))); // Sheet1:A1 > 
Sheet2:A1
+
+static_assert(ScAddress(1, 0, 0) > ScAddress(0, 0, 0)); // B1 > A1
+static_assert(ScAddress(1, 0, 0) > ScAddress(0, 1, 0)); // B1 > A2
+static_assert(ScAddress(1, 0, 0) > ScAddress(0, 10000, 0)); // B1 > A10000
+static_assert(ScAddress(1, 10000, 0) > ScAddress(0, 10000, 0)); // B10000 > 
A10000
+static_assert(ScAddress(1, 0, 1) > ScAddress(1, 0, 0)); // Sheet2:A1 > 
Sheet1:A1
+
+// More or Equal
+
+static_assert(ScAddress(1, 0, 0) >= ScAddress(1, 0, 0)); // B1 >= B1
+static_assert(ScAddress(0, 1, 0) >= ScAddress(0, 1, 0)); // A2 >= A2
+static_assert(ScAddress(0, 0, 1) >= ScAddress(0, 0, 1)); // Sheet1:A1 >= 
Sheet2:A1
+
+static_assert(ScAddress(1, 0, 0) >= ScAddress(0, 0, 0)); // B1 >= A1
+static_assert(ScAddress(1, 0, 0) >= ScAddress(0, 1, 0)); // B1 >= A2
+static_assert(ScAddress(1, 0, 0) >= ScAddress(0, 10000, 0)); // B1 >= A10000
+static_assert(ScAddress(1, 10000, 0) >= ScAddress(0, 10000, 0)); // B10000 >= 
A10000
+static_assert(ScAddress(1, 0, 1) >= ScAddress(1, 0, 0)); // Sheet2:A1 >= 
Sheet1:A1
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to