From dc2ae08e02730ab795445bc047221aa56914f723 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 23 Jan 2024 08:45:02 -0800 Subject: [PATCH] QStringView: stop instantiating std::char_traits and It's deprecated and will be removed with LLVM 19. Amends b1ee49b46533d39f7fabda68d0bd08a1ab130a27. Pick-to: 6.7 Change-Id: I5dd50a1a7ca5424d9e7afffd17ad07b3ab3fc18a Reviewed-by: Thiago Macieira Reviewed-by: Marc Mutz --- src/corelib/text/qstringalgorithms.h | 54 ++++++++++++++++++---------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/corelib/text/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h index 082f970b6c2..320a08737d8 100644 --- a/src/corelib/text/qstringalgorithms.h +++ b/src/corelib/text/qstringalgorithms.h @@ -4,15 +4,17 @@ #ifndef QSTRINGALGORITHMS_H #define QSTRINGALGORITHMS_H +#include +#include #include #include -#include #if 0 #pragma qt_class(QStringAlgorithms) #endif #include // std::find -#include // std::char_traits + +#include // for memchr QT_BEGIN_NAMESPACE @@ -125,6 +127,25 @@ namespace QtPrivate { [[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLatin1(QStringView s) noexcept; [[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf16(QStringView s) noexcept; +template [[nodiscard]] constexpr Q_ALWAYS_INLINE +qsizetype lengthHelperContainerLoop(const Char (&str)[N]) +{ +#if defined(__cpp_lib_constexpr_algorithms) && defined(Q_CC_GNU_ONLY) + // libstdc++'s std::find / std::find_if manages to execute more steps + // than the loop below + const auto it = std::find(str, str + N, Char(0)); + return it - str; +#else + // std::char_traits is deprecated for C not one of the standard char + // types, so we have to roll out our own loop. + for (size_t i = 0; i < N; ++i) { + if (str[i] == Char(0)) + return qsizetype(i); + } + return qsizetype(N); +#endif +} + template [[nodiscard]] constexpr Q_ALWAYS_INLINE std::enable_if_t lengthHelperContainer(const Char (&str)[N]) @@ -133,9 +154,12 @@ lengthHelperContainer(const Char (&str)[N]) // at which the compiler gives up pre-calculating the std::find() below and // instead inserts code to be executed at runtime. constexpr size_t RuntimeThreshold = -#if defined(Q_CC_CLANG) // tested through Clang 16.0.0 - 100 -#elif defined(Q_CC_GNU) // tested through GCC 13.1 at -O3 compilation level +#if defined(Q_CC_CLANG) + // tested on Clang 15, 16 & 17 + 1023 +#elif defined(Q_CC_GNU) + // tested through GCC 13.1 at -O3 compilation level + // note: at -O2, GCC always generates a loop! __cplusplus >= 202002L ? 39 : 17 #else 0 @@ -150,24 +174,18 @@ lengthHelperContainer(const Char (&str)[N]) #endif } - // libstdc++'s std::find_if yields a higher threshold than - // std::char_traits::find - -#if __cplusplus >= 202002 && defined(__cpp_lib_constexpr_algorithms) - const auto it = std::find(str, str + N, Char(0)); - return it - str; -#else - const auto it = std::char_traits::find(str, N, Char(0)); - return it ? std::distance(str, it) : ptrdiff_t(N); -#endif + return lengthHelperContainerLoop(str); } template [[nodiscard]] constexpr inline std::enable_if_t lengthHelperContainer(const Char (&str)[N]) { - // std::char_traits::find will call memchr or __builtin_memchr for us - const auto it = std::char_traits::find(str, N, Char(0)); - return it ? std::distance(str, it) : ptrdiff_t(N); +#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED + if (!qIsConstantEvaluated()) + return qstrnlen(reinterpret_cast(str), N); +#endif + + return lengthHelperContainerLoop(str); } template