chart2/source/tools/ExplicitCategoriesProvider.cxx |    5 ++
 chart2/source/view/main/VDataSeries.cxx            |    3 +
 compilerplugins/clang/check.cxx                    |   10 +++++
 compilerplugins/clang/check.hxx                    |    2 +
 compilerplugins/clang/nullptr.cxx                  |    9 ++++
 compilerplugins/clang/test/nullptr.cxx             |    6 +++
 config_host/config_global.h.in                     |    3 +
 configure.ac                                       |   23 +++++++++++
 include/o3tl/compare.hxx                           |   41 +++++++++++++++++++++
 solenv/clang-format/excludelist                    |    1 
 10 files changed, 100 insertions(+), 3 deletions(-)

New commits:
commit 648878703d26cf73d66d9ac9132b0aa7f551ba28
Author:     Stephan Bergmann <[email protected]>
AuthorDate: Wed Feb 7 09:34:10 2024 +0100
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Wed Feb 7 21:03:54 2024 +0100

    double operator < is not a strict weak ordering due to NaN
    
    ...so recent LLVM 19 trunk libc++ in debug mode complained during
    CppunitTest_chart2_export3 about
    
    > 
~/llvm/inst/bin/../include/c++/v1/__debug_utils/strict_weak_ordering_check.h:59:
 assertion __comp(*(__first + __a), *(__first + __b)) failed: Your comparator 
is not a valid strict-weak ordering
    
    at
    
    > 5   libsystem_c.dylib                   0x0000000183279a40 abort + 180
    > 6   libc++.1.0.dylib                    0x0000000101045d98 
_ZNSt3__123__cxx_atomic_notify_oneEPVKv + 0
    > 7   libchartcorelo.dylib                0x00000002f9e05990 
_ZNSt3__135__check_strict_weak_ordering_sortedB8de190000IPdNS_6__lessIvvEEEEvT_S4_RT0_
 + 732
    > 8   libchartcorelo.dylib                0x00000002f9e055ac 
_ZNSt3__111__sort_implB8de190000INS_17_ClassicAlgPolicyENS_11__wrap_iterIPdEENS_6__lessIvvEEEEvT0_S7_RT1_
 + 172
    > 9   libchartcorelo.dylib                0x00000002f9e054d4 
_ZNSt3__14sortB8de190000INS_11__wrap_iterIPdEENS_6__lessIvvEEEEvT_S6_T0_ + 68
    > 10  libchartcorelo.dylib                0x00000002f9e04f94 
_ZNSt3__14sortB8de190000INS_11__wrap_iterIPdEEEEvT_S4_ + 64
    > 11  libchartcorelo.dylib                0x00000002f9dfea10 
_ZN5chartL22lcl_fillDateCategoriesERKN3com3sun4star3uno9ReferenceINS2_6chart24data13XDataSequenceEEERNSt3__16vectorIdNSB_9allocatorIdEEEEbRNS_10ChartModelE
 + 1404
    > 12  libchartcorelo.dylib                0x00000002f9dfe28c 
_ZN5chart26ExplicitCategoriesProvider4initEv + 280
    > 13  libchartcorelo.dylib                0x00000002f9dff0b8 
_ZN5chart26ExplicitCategoriesProvider10isDateAxisEv + 28
    > 14  libchartcorelo.dylib                0x00000002f9bcb738 
_ZN5chart14VSeriesPlotter9addSeriesENSt3__110unique_ptrINS_11VDataSeriesENS1_14default_deleteIS3_EEEEiii
 + 200
    > 15  libchartcorelo.dylib                0x00000002f9b951e4 
_ZN5chart8BarChart9addSeriesENSt3__110unique_ptrINS_11VDataSeriesENS1_14default_deleteIS3_EEEEiii
 + 280
    
    Change-Id: Ie0711ca60130759f3daaf8332ab326fa29cb5cba
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163074
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/chart2/source/tools/ExplicitCategoriesProvider.cxx 
b/chart2/source/tools/ExplicitCategoriesProvider.cxx
index 59189aa1931f..7f6de91b6e82 100644
--- a/chart2/source/tools/ExplicitCategoriesProvider.cxx
+++ b/chart2/source/tools/ExplicitCategoriesProvider.cxx
@@ -32,6 +32,7 @@
 #include <DataSeries.hxx>
 
 #include <com/sun/star/chart2/AxisType.hpp>
+#include <o3tl/compare.hxx>
 #include <o3tl/safeint.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <comphelper/diagnose_ex.hxx>
@@ -460,7 +461,9 @@ static bool lcl_fillDateCategories( const uno::Reference< 
data::XDataSequence >&
                 rDateCategories.push_back( 
std::numeric_limits<double>::quiet_NaN() );
             }
         }
-        std::sort( rDateCategories.begin(), rDateCategories.end() );
+        std::sort(
+            rDateCategories.begin(), rDateCategories.end(),
+            [](auto x, auto y) { return o3tl::strong_order(x, y) < 0; } );
     }
 
     return bAnyDataFound && bOnlyDatesFound;
commit 56e6d683dba66d4f2f80145064d2bda2ea4b27b1
Author:     Stephan Bergmann <[email protected]>
AuthorDate: Wed Feb 7 09:39:27 2024 +0100
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Wed Feb 7 21:03:46 2024 +0100

    double operator < is not a strict weak ordering due to NaN
    
    ...so recent LLVM 19 trunk libc++ in debug mode complained during
    CppunitTest_chart2_export2 about
    
    > 
~/llvm/inst/bin/../include/c++/v1/__debug_utils/strict_weak_ordering_check.h:59:
 assertion __comp(*(__first + __a), *(__first + __b)) failed: Your comparator 
is not a valid strict-weak ordering
    
    at
    
    > 5   libsystem_c.dylib                   0x0000000183279a40 abort + 180
    > 6   libc++.1.0.dylib                    0x00000001030f9d98 
_ZNSt3__123__cxx_atomic_notify_oneEPVKv + 0
    > 7   libchartcorelo.dylib                0x00000002f817f0ec 
_ZNSt3__135__check_strict_weak_ordering_sortedB8de190000INS_11__wrap_iterIPNS_6vectorIdNS_9allocatorIdEEEEEEN5chart12_GLOBAL__N_116lcl_LessXOfPointEEEvT_SB_RT0_
 + 960
    > 8   libchartcorelo.dylib                0x00000002f817e6cc 
_ZNSt3__118__stable_sort_implB8de190000INS_17_ClassicAlgPolicyENS_11__wrap_iterIPNS_6vectorIdNS_9allocatorIdEEEEEEN5chart12_GLOBAL__N_116lcl_LessXOfPointEEEvT0_SC_RT1_
 + 268
    > 9   libchartcorelo.dylib                0x00000002f8172a90 
_ZNSt3__111stable_sortB8de190000INS_11__wrap_iterIPNS_6vectorIdNS_9allocatorIdEEEEEEN5chart12_GLOBAL__N_116lcl_LessXOfPointEEEvT_SB_T0_
 + 68
    > 10  libchartcorelo.dylib                0x00000002f8172820 
_ZN5chart11VDataSeries15doSortByXValuesEv + 508
    > 11  libchartcorelo.dylib                0x00000002f8064c44 
_ZN5chart9AreaChart12createShapesEv + 1528
    > 12  libchartcorelo.dylib                0x00000002f80f2ae0 
_ZN5chart9ChartView28impl_createDiagramAndContentERKNS_18CreateShapeParam2DERKN3com3sun4star3awt4SizeE
 + 4440
    > 13  libchartcorelo.dylib                0x00000002f80f77ac 
_ZN5chart9ChartView14createShapes2DERKN3com3sun4star3awt4SizeE + 2728
    > 14  libchartcorelo.dylib                0x00000002f80f58ec 
_ZN5chart9ChartView12createShapesEv + 692
    > 15  libchartcorelo.dylib                0x00000002f80f4598 
_ZN5chart9ChartView15impl_updateViewEb + 288
    
    But the introduced use of `std::strong_order(first[0], second[0]) < 0` then
    triggered a false
    
    > lo/core/chart2/source/view/main/VDataSeries.cxx:105:61: error: 
NullToMemberPointer ValueDependentIsNotNull ZeroLiteral -> nullptr 
[loplugin:nullptr]
    >   105 |             return std::strong_order(first[0], second[0]) < 0;
    >       |                                                             ^
    
    so needed some hack in loplugin:nullptr.
    
    And old versions of libc++, still used at least on Android, do not have any
    implementations of std::strong_order.  So detect those cases in configure.ac
    (checking for std::strong_order for double, which is what is actually being 
used
    in the code) and fall back to operator <=> for now, even if that will not
    provide a strict weak ordering and will thus continue to violate the
    requirements of std::sort.
    
    And then our venerable clang-format 5.0.0 would have broken the token `<=>` 
into
    `<= >`, so exclude include/o3tl/compare.hxx from its mis-treatment.
    
    Change-Id: I7a64a630eb5f560dce59f3ff9d51ca3d1adc70be
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163075
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/chart2/source/view/main/VDataSeries.cxx 
b/chart2/source/view/main/VDataSeries.cxx
index 455c991b9f89..17dc8f1a3beb 100644
--- a/chart2/source/view/main/VDataSeries.cxx
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -38,6 +38,7 @@
 #include <com/sun/star/chart2/RelativePosition.hpp>
 #include <com/sun/star/chart2/RelativeSize.hpp>
 
+#include <o3tl/compare.hxx>
 #include <osl/diagnose.h>
 #include <tools/color.hxx>
 #include <comphelper/diagnose_ex.hxx>
@@ -101,7 +102,7 @@ struct lcl_LessXOfPoint
     {
         if( !first.empty() && !second.empty() )
         {
-            return first[0]<second[0];
+            return o3tl::strong_order(first[0], second[0]) < 0;
         }
         return false;
     }
diff --git a/compilerplugins/clang/check.cxx b/compilerplugins/clang/check.cxx
index 4ff081b6923e..60e476cc37b7 100644
--- a/compilerplugins/clang/check.cxx
+++ b/compilerplugins/clang/check.cxx
@@ -133,6 +133,16 @@ TypeCheck TypeCheck::Pointer() const {
     return TypeCheck();
 }
 
+TypeCheck TypeCheck::MemberPointerOf() const {
+    if (!type_.isNull()) {
+        auto const t = type_->getAs<clang::MemberPointerType>();
+        if (t != nullptr) {
+            return TypeCheck(t->getClass());
+        }
+    }
+    return TypeCheck();
+}
+
 TerminalCheck TypeCheck::Enum() const {
     if (!type_.isNull()) {
         auto const t = type_->getAs<clang::EnumType>();
diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx
index af6cd355a416..65ee16d77f2c 100644
--- a/compilerplugins/clang/check.hxx
+++ b/compilerplugins/clang/check.hxx
@@ -62,6 +62,8 @@ public:
 
     TypeCheck Pointer() const;
 
+    TypeCheck MemberPointerOf() const;
+
     TerminalCheck Enum() const;
 
     TypeCheck LvalueReference() const;
diff --git a/compilerplugins/clang/nullptr.cxx 
b/compilerplugins/clang/nullptr.cxx
index 0213b6b05c88..04fb5bf0f9fd 100644
--- a/compilerplugins/clang/nullptr.cxx
+++ b/compilerplugins/clang/nullptr.cxx
@@ -131,11 +131,18 @@ bool Nullptr::VisitImplicitCastExpr(CastExpr const * 
expr) {
     case Expr::NPCK_CXX11_nullptr:
         break;
     default:
-        if (loplugin::TypeCheck(expr->getType()).Typedef("locale_t")
+        auto const tc = loplugin::TypeCheck(expr->getType());
+        if (tc.Typedef("locale_t")
             .GlobalNamespace())
         {
             break; // POSIX locale_t is left unspecified
         }
+        // Hack to handle libc++ and stdlibc++ `std::strong_ordering x; x < 0` 
etc.:
+        if 
(tc.MemberPointerOf().ClassOrStruct("_CmpUnspecifiedParam").StdNamespace()
+            || 
tc.Pointer().ClassOrStruct("__unspec").Namespace("__cmp_cat").StdNamespace())
+        {
+            break;
+        }
         handleNull(expr->getSubExpr(), expr->getCastKindName(), k);
         break;
     }
diff --git a/compilerplugins/clang/test/nullptr.cxx 
b/compilerplugins/clang/test/nullptr.cxx
index bf7376cb6562..392a930bf9b8 100644
--- a/compilerplugins/clang/test/nullptr.cxx
+++ b/compilerplugins/clang/test/nullptr.cxx
@@ -7,6 +7,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include "sal/config.h"
+
+#include <compare>
+
 struct S
 {
     void* p;
@@ -18,6 +22,8 @@ int main()
         0 // expected-error {{NullToPointer ValueDependentIsNotNull 
ZeroLiteral -> nullptr [loplugin:nullptr]}}
     };
     (void)s;
+
+    (void)(std::strong_order(0, 1) < 0);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/config_host/config_global.h.in b/config_host/config_global.h.in
index dce52798a1fe..5b42b2c5a8bd 100644
--- a/config_host/config_global.h.in
+++ b/config_host/config_global.h.in
@@ -24,6 +24,9 @@ Any change in this header will cause a rebuild of almost 
everything.
 // constexpr", and <https://wg21.link/P1143R2> "Adding the constinit keyword":
 #define HAVE_CPP_CONSTINIT_SORTED_VECTOR 0
 
+// Compiler supports C++20 <compare> std::strong_order:
+#define HAVE_CPP_STRONG_ORDER 0
+
 /* "CWG motion 23: P1825R0 'Merged wording for P0527R1 and P1155R3' (DR)" in
    <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4829.html> 
"N4829 Editors' Report --
    Programming Languages -- C++" marks
diff --git a/configure.ac b/configure.ac
index 5937983f7ac2..721851c52d87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14787,6 +14787,29 @@ CXX=$save_CXX
 CXXFLAGS=$save_CXXFLAGS
 AC_LANG_POP([C++])
 
+AC_MSG_CHECKING([whether $CXX_BASE supports a working C++20 std::strong_order])
+dnl ...which is known to not be implemented in libc++ prior to
+dnl 
<https://github.com/llvm/llvm-project/commit/d8380ad977e94498e170b06449c81f1fc27da7b5>
 "[libc++]
+dnl [P1614] Implement [cmp.alg]'s std::{strong,weak,partial}_order" in LLVM 14:
+AC_LANG_PUSH([C++])
+save_CXX=$CXX
+if test "$COM" = MSC && test "$COM_IS_CLANG" != TRUE; then
+    CXX="env LIB=$ILIB $CXX"
+fi
+save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $CXXFLAGS_CXX11"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([
+        #include <compare>
+    ], [
+        (void) (std::strong_order(1.0, 2.0) < 0);
+    ])], [
+        AC_DEFINE([HAVE_CPP_STRONG_ORDER],[1])
+        AC_MSG_RESULT([yes])
+    ], [AC_MSG_RESULT([no])])
+CXX=$save_CXX
+CXXFLAGS=$save_CXXFLAGS
+AC_LANG_POP([C++])
+
 # ===================================================================
 # Creating bigger shared library to link against
 # ===================================================================
diff --git a/include/o3tl/compare.hxx b/include/o3tl/compare.hxx
new file mode 100644
index 000000000000..27c6b31ac647
--- /dev/null
+++ b/include/o3tl/compare.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <compare>
+
+#include <config_global.h>
+
+namespace o3tl
+{
+// A poor approximation of C++20 <compare> std::strong_order, falling back to 
operator <=> (so e.g.
+// not providing a strict weak ordering for floating-point types with NaN):
+#if HAVE_CPP_STRONG_ORDER
+
+inline constexpr auto strong_order = std::strong_order;
+
+#else
+
+namespace detail
+{
+struct strong_order
+{
+    auto operator()(auto x, auto y) const { return x <=> y; }
+};
+}
+
+inline constexpr auto strong_order = detail::strong_order();
+
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index f15ac0ba31f3..e6e95fe011b2 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -5292,6 +5292,7 @@ include/linguistic/lngprophelp.hxx
 include/linguistic/misc.hxx
 include/linguistic/spelldta.hxx
 include/o3tl/any.hxx
+include/o3tl/compare.hxx
 include/o3tl/cow_wrapper.hxx
 include/o3tl/enumarray.hxx
 include/o3tl/enumrange.hxx

Reply via email to