From 7d63efc16f65f98c657caa90e0d7e9b72a879ade Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Jan 2022 17:54:55 +0100 Subject: [PATCH] Prevent repeated instantiations of qRegisterNormalizedMetaType>() This, finally, shows some expected results: Clang -ftime-trace: $ ClangBuildAnalyzer --analyze qtgui-spec-before.trace | head -n6 Analyzing build trace from 'qtgui-spec-before.trace'... **** Time summary: Compilation (523 times): Parsing (frontend): 665.7 s Codegen & opts (backend): 298.9 s $ ClangBuildAnalyzer --analyze qtgui-spec-after.trace | head -n6 Analyzing build trace from 'qtgui-spec-after.trace'... **** Time summary: Compilation (525 times): Parsing (frontend): 628.3 s Codegen & opts (backend): 301.0 s GCC 11 time (bash builtin): $ time for ((i=0; i < 3; ++i)) do touch ../qt5/qtbase/src/gui/painting/qpolygon.h ; ninja libQt6Gui.so; done [268/268] Creating library symlink qtbase/lib/libQt6Gui.so.6 qtbase/lib/libQt6Gui.so [268/268] Creating library symlink qtbase/lib/libQt6Gui.so.6 qtbase/lib/libQt6Gui.so [268/268] Creating library symlink qtbase/lib/libQt6Gui.so.6 qtbase/lib/libQt6Gui.so real 4m10,918s user 49m10,099s sys 3m11,719s $ git revert --no-commit HEAD $ time for ((i=0; i < 3; ++i)) do touch ../qt5/qtbase/src/gui/painting/qpolygon.h ; ninja libQt6Gui.so; done [268/268] Creating library symlink qtbase/lib/libQt6Gui.so.6 qtbase/lib/libQt6Gui.so [268/268] Creating library symlink qtbase/lib/libQt6Gui.so.6 qtbase/lib/libQt6Gui.so [268/268] Creating library symlink qtbase/lib/libQt6Gui.so.6 qtbase/lib/libQt6Gui.so real 4m18,630s user 51m11,491s sys 3m16,479s The technique in the comment in qmetatype.h doesn't work on Clang - it runs into -Winstantiation-after-specialization. The whole extern template stuff so miserably fails to meet the goals set out in N1448, not only for MSVC and class templates, but, it seems, on all compilers, and for function templates, too, that I'm giving up on it for now. Unfortunately, I'm not really seeing a way to hide this stuff behind a macro, yet. Task-number: QTBUG-97601 Pick-to: 6.3 Change-Id: I500fd04555e0bd76ac021f75582bd8d8cf339378 Reviewed-by: Thiago Macieira --- src/corelib/itemmodels/qabstractitemmodel.cpp | 3 +++ src/corelib/itemmodels/qabstractitemmodel.h | 4 ++++ src/corelib/kernel/qmetatype.h | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index b28597468f..2907cb66ae 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -60,6 +60,9 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcCheckIndex, "qt.core.qabstractitemmodel.checkindex") +int qRegisterNormalizedMetaType_QList_QModelIndex(const QByteArray &name) +{ return qRegisterNormalizedMetaTypeImplementation>(name); } + QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &index) { Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index a059036d12..a8d8a7de4b 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -537,6 +537,10 @@ inline Qt::ItemFlags QModelIndex::flags() const inline size_t qHash(const QModelIndex &index, size_t seed = 0) noexcept { return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed; } +Q_CORE_EXPORT int qRegisterNormalizedMetaType_QList_QModelIndex(const QByteArray &name); +template <> inline int qRegisterNormalizedMetaType>(const QByteArray &name) +{ return qRegisterNormalizedMetaType_QList_QModelIndex(name); } + QT_END_NAMESPACE Q_DECLARE_METATYPE(QModelIndexList) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index dd37ab2fa1..cff94d3324 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1226,7 +1226,7 @@ namespace QtPrivate { } template -int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName) +int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName) { #ifndef QT_NO_QOBJECT Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), @@ -1254,6 +1254,22 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz return id; } +// This primary template calls the -Implementation, like all other specialisations should. +// But the split allows to +// - in a header: +// - declare, but not define, a specialization of this template +// - add an explicit instantiation declaration (extern template ...) +// - in the .cpp file: +// - define the specialization to call the -Implementation +// - add an explicit instantiation definition +// This prevents the compiler from taking the leeway for inline functions in +// [temp.explicit]/13 Note 4 +template +int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName) +{ + return qRegisterNormalizedMetaTypeImplementation(normalizedTypeName); +} + template int qRegisterMetaType(const char *typeName) {