From 660014156d33d6c1635e22016d20506494e8878b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jun 2022 15:49:02 -0700 Subject: [PATCH] QMetaType: don't use global relocations to the lambdas and structures The way the Qt 6.0 QMetaTypeInterface was designed, using a static inline variable in a template, would normally require the linker and dynamic linker to merge all copies and choose a single copy as the official one. But because of hidden visibility and of Windows DLLs, QMetaType already copes with multiple copies NOT getting merged. So we may as well ask the linkers not to bother and use simpler, local relocations to find those symbols. They are all supposed to still be equivalent and it's an ODR violation if they're not. The Apple ld64 linker complains if you use this type of global relocation: ld: warning: direct access in function [...] to global weak symbol 'QtPrivate::QMetaTypeInterfaceWrapper::metaType' Fixes: QTBUG-93471 Change-Id: Id0fb9ab0089845ee8843fffd16f98a10aa719434 Reviewed-by: Qt CI Bot Reviewed-by: Fabian Kosmale (cherry picked from commit 6234182d82b5f645a61c89219d71ab6a4ac03609) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qmetatype.h | 17 +++++++++++++++++ .../corelib/kernel/qmetatype/tst_qmetatype2.cpp | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index cdad83a4670..70cf942a4a1 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -2268,6 +2268,20 @@ struct QDataStreamOperatorForType static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr; }; +// Performance optimization: +// +// Don't add all these symbols to the dynamic symbol tables on ELF systems and +// on Darwin. Each library is going to have a copy anyway and QMetaType already +// copes with some of these being "hidden" (see QMetaType::idHelper()). We may +// as well let the linker know it can always use the local copy. +// +// This is currently not enabled for GCC due to +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106023 + +#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG) +# pragma GCC visibility push(hidden) +#endif + template class QMetaTypeForType { @@ -2358,6 +2372,9 @@ struct QMetaTypeInterfaceWrapper }; }; +#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG) +# pragma GCC visibility pop +#endif template<> class QMetaTypeInterfaceWrapper diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp index 11dc593ebb7..265ec3095f5 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp @@ -522,6 +522,14 @@ void tst_QMetaType::operatorEqAcrossLibs() QCOMPARE(QByteArray(lib2Type.name()), QByteArray(localType.name())); QCOMPARE(lib1Type, localType); QCOMPARE(lib2Type, localType); + +#if !defined(Q_OS_WIN) && !defined(Q_OS_INTEGRITY) + if (actualTypeId < QMetaType::FirstGuiType && actualTypeId != QMetaType::Void) { + // for built-in QtCore types, we expect the interfaces to be the same too + QCOMPARE(lib1Iface, localIface); + QCOMPARE(lib2Iface, localIface); + } +#endif } class WithPrivateDTor {