Skip to content

Commit

Permalink
QMetaType: extern-template the built-in Core types' QMetaTypeInterface
Browse files Browse the repository at this point in the history
This *should* make no difference in behavior, it just prevents the
instantiation of the QMetaTypeInterface and all the lambdas used in it
in every compilation unit, with a copy in every library. Now, a simple
function like:

  QMetaType f() { return QMetaType::fromType<int>(); }

produces only a single function, with a reference into QtCore:

_Z1fv:
        movq    _ZN9QtPrivate25QMetaTypeInterfaceWrapperIiE8metaTypeE@GOTPCREL(%rip),%rax
        ret

The code above *does* work on Windows, producing:

_Z1fv:
        movq    __imp__ZN9QtPrivate25QMetaTypeInterfaceWrapperIiE8metaTypeE(%rip), %rax
        ret

However, it breaks the staticMetaObjects' metatype listing, because
getting the address of a __declspec(dllimport) variable is not a
constant expression (it lacks data relocations). So this is disabled on
Windows.

This change also broke the INTEGRITY build. I've simply disabled the
optimization there without attempting to understand why it fails.

Task-number: QTBUG-93471
Pick-to: 6.4
Change-Id: Id0fb9ab0089845ee8843fffd16f97748a00b4d64
Reviewed-by: Fabian Kosmale <[email protected]>
  • Loading branch information
thiagomacieira committed Jun 28, 2022
1 parent b6a953b commit dbf5840
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 6 deletions.
9 changes: 5 additions & 4 deletions src/corelib/kernel/qmetatype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2975,12 +2975,13 @@ QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
*/

namespace QtPrivate {
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC)
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)

// Explicit instantiation definition
#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
template class QMetaTypeForType<Name>;
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
template class QMetaTypeForType<Name>; \
template struct QMetaTypeInterfaceWrapper<Name>;
QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
Expand Down
17 changes: 15 additions & 2 deletions src/corelib/kernel/qmetatype.h
Original file line number Diff line number Diff line change
Expand Up @@ -2377,11 +2377,24 @@ class QMetaTypeInterfaceWrapper<void>
/*
MSVC instantiates extern templates
(https://developercommunity.visualstudio.com/t/c11-extern-templates-doesnt-work-for-class-templat/157868)
The INTEGRITY compiler apparently does too.
On Windows (with other compilers or whenever MSVC is fixed), we can't declare
QMetaTypeInterfaceWrapper with __declspec(dllimport) because taking its
address is not a core constant expression.
*/
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC)
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)

#define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
#ifdef QT_NO_DATA_RELOCATION
# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
#else
# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
extern template class Q_CORE_EXPORT QMetaTypeForType<Name>; \
extern template struct Q_CORE_EXPORT QMetaTypeInterfaceWrapper<Name>;
#endif

QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
Expand Down

0 comments on commit dbf5840

Please sign in to comment.