MSVC: improve QASV(const char(&str)[N]) compilation time

The lengthHelperContainer() implementation for sizeof(Char) == 1 case
is using qstrnlen() for the non-constexpr case.
qstrnlen() is an inline function which is effectively a nullptr check
and a memchr() call.

For some reason, on MSVC this combination resulted in very slow
compilation for the user projects, where each call to
QObject::setObjectName() was hitting this codepath.

Fix it by replacing the qstrnlen() call with strnlen_s() for MSVC.
It seems that for now all versions of MSVC are affected. However,
introduce a new Q_COMPILER_SLOW_QSTRNLEN_COMPILATION definition,
which will allow us to check for the compiler version later on.
For now this definition is set for all MSVC versions unconditionally.

Fixes: QTBUG-124376
Pick-to: 6.7.1
Change-Id: Id769bef1e950ffa756acf7af39d362fd8b112019
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit d849cb80a4ba468e2c6097ebfcab384ddaec8e67)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2024-04-24 16:35:01 +02:00 committed by Qt Cherry-pick Bot
parent 843b9921f3
commit 7faabcce1a
2 changed files with 12 additions and 1 deletions

View File

@ -857,6 +857,8 @@
# if _MSC_VER < 1936
# define Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
# endif
// QTBUG-124376: MSVC is slow at compiling qstrnlen()
# define Q_COMPILER_SLOW_QSTRNLEN_COMPILATION
# endif /* __cplusplus */
#endif // defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)

View File

@ -174,12 +174,21 @@ lengthHelperContainer(const Char (&str)[N])
return lengthHelperContainerLoop(str);
}
inline qsizetype qstrnlen_helper(const char *str, size_t maxlen)
{
#if !defined(Q_COMPILER_SLOW_QSTRNLEN_COMPILATION)
return qstrnlen(str, maxlen);
#else
return strnlen_s(str, maxlen);
#endif
}
template <typename Char, size_t N> [[nodiscard]] constexpr inline
std::enable_if_t<sizeof(Char) == 1, qsizetype> lengthHelperContainer(const Char (&str)[N])
{
#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
if (!q20::is_constant_evaluated())
return qstrnlen(reinterpret_cast<const char *>(str), N);
return qstrnlen_helper(reinterpret_cast<const char *>(str), N);
#endif
return lengthHelperContainerLoop(str);