From 3ad9f94ff2de3a1f812bb0139ff31e31d5ffb529 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 21 Feb 2023 10:15:28 +0100 Subject: [PATCH] QVariant: Move some inline methods into a private header We want to be able to use those from qtdeclarative. Clearly, they are intended to be inline. Task-number: QTBUG-108789 Change-Id: I3560e9b58213c4f41dbf6553021f3d6187960e8b Reviewed-by: Fabian Kosmale Reviewed-by: Thiago Macieira --- src/corelib/CMakeLists.txt | 2 +- src/corelib/kernel/qvariant.cpp | 70 +------------------------ src/corelib/kernel/qvariant_p.h | 92 +++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 70 deletions(-) create mode 100644 src/corelib/kernel/qvariant_p.h diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index eb4d4acceb..99572c1bc3 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -181,7 +181,7 @@ qt_internal_add_module(Core kernel/qtestsupport_core.cpp kernel/qtestsupport_core.h kernel/qtimer.cpp kernel/qtimer.h kernel/qtimer_p.h kernel/qtranslator.cpp kernel/qtranslator.h kernel/qtranslator_p.h - kernel/qvariant.cpp kernel/qvariant.h + kernel/qvariant.cpp kernel/qvariant.h kernel/qvariant_p.h kernel/qvariantmap.h kernel/qvarianthash.h kernel/qvariantlist.h plugin/qfactoryinterface.cpp plugin/qfactoryinterface.h plugin/qfactoryloader.cpp plugin/qfactoryloader_p.h diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 2939795709..86eb678d81 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -3,7 +3,7 @@ // Copyright (C) 2015 Olivier Goffart // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include "qvariant.h" +#include "qvariant_p.h" #include "qbitarray.h" #include "qbytearray.h" #include "qdatastream.h" @@ -231,21 +231,6 @@ static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface return true; } -template static QVariant::PrivateShared * -customConstructShared(size_t size, size_t align, F &&construct) -{ - struct Deleter { - void operator()(QVariant::PrivateShared *p) const - { QVariant::PrivateShared::free(p); } - }; - - // this is exception-safe - std::unique_ptr ptr; - ptr.reset(QVariant::PrivateShared::create(size, align)); - construct(ptr->data()); - return ptr.release(); -} - // the type of d has already been set, but other field are not set static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant::Private *d, const void *copy) @@ -306,59 +291,6 @@ static QVariant::Private clonePrivate(const QVariant::Private &other) } // anonymous used to hide QVariant handlers -inline QVariant::PrivateShared *QVariant::PrivateShared::create(size_t size, size_t align) -{ - size += sizeof(PrivateShared); - if (align > sizeof(PrivateShared)) { - // The alignment is larger than the alignment we can guarantee for the pointer - // directly following PrivateShared, so we need to allocate some additional - // memory to be able to fit the object into the available memory with suitable - // alignment. - size += align - sizeof(PrivateShared); - } - void *data = operator new(size); - auto *ps = new (data) QVariant::PrivateShared(); - ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps)); - return ps; -} - -inline void QVariant::PrivateShared::free(PrivateShared *p) -{ - p->~PrivateShared(); - operator delete(p); -} - -inline QVariant::Private::Private(const QtPrivate::QMetaTypeInterface *iface) noexcept - : is_shared(false), is_null(false), packedType(quintptr(iface) >> 2) -{ - Q_ASSERT((quintptr(iface) & 0x3) == 0); -} - -template inline -QVariant::Private::Private(std::piecewise_construct_t, const T &t) - : is_shared(!CanUseInternalSpace), is_null(std::is_same_v) -{ - // confirm noexceptness - static constexpr bool isNothrowQVariantConstructible = noexcept(QVariant(t)); - static constexpr bool isNothrowCopyConstructible = std::is_nothrow_copy_constructible_v; - static constexpr bool isNothrowCopyAssignable = std::is_nothrow_copy_assignable_v; - - const QtPrivate::QMetaTypeInterface *iface = QtPrivate::qMetaTypeInterfaceForType(); - Q_ASSERT((quintptr(iface) & 0x3) == 0); - packedType = quintptr(iface) >> 2; - - if constexpr (CanUseInternalSpace) { - static_assert(isNothrowQVariantConstructible == isNothrowCopyConstructible); - static_assert(isNothrowQVariantConstructible == isNothrowCopyAssignable); - new (data.data) T(t); - } else { - static_assert(!isNothrowQVariantConstructible); // we allocate memory, even if T doesn't - data.shared = customConstructShared(sizeof(T), alignof(T), [=](void *where) { - new (where) T(t); - }); - } -} - /*! \class QVariant \inmodule QtCore diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h new file mode 100644 index 0000000000..f5f4d0fb8a --- /dev/null +++ b/src/corelib/kernel/qvariant_p.h @@ -0,0 +1,92 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QVARIANT_P_H +#define QVARIANT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qvariant.h" + +QT_BEGIN_NAMESPACE + +template static QVariant::PrivateShared * +customConstructShared(size_t size, size_t align, F &&construct) +{ + struct Deleter { + void operator()(QVariant::PrivateShared *p) const + { QVariant::PrivateShared::free(p); } + }; + + // this is exception-safe + std::unique_ptr ptr; + ptr.reset(QVariant::PrivateShared::create(size, align)); + construct(ptr->data()); + return ptr.release(); +} + +inline QVariant::PrivateShared *QVariant::PrivateShared::create(size_t size, size_t align) +{ + size += sizeof(PrivateShared); + if (align > sizeof(PrivateShared)) { + // The alignment is larger than the alignment we can guarantee for the pointer + // directly following PrivateShared, so we need to allocate some additional + // memory to be able to fit the object into the available memory with suitable + // alignment. + size += align - sizeof(PrivateShared); + } + void *data = operator new(size); + auto *ps = new (data) QVariant::PrivateShared(); + ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps)); + return ps; +} + +inline void QVariant::PrivateShared::free(PrivateShared *p) +{ + p->~PrivateShared(); + operator delete(p); +} + +inline QVariant::Private::Private(const QtPrivate::QMetaTypeInterface *iface) noexcept + : is_shared(false), is_null(false), packedType(quintptr(iface) >> 2) +{ + Q_ASSERT((quintptr(iface) & 0x3) == 0); +} + +template inline +QVariant::Private::Private(std::piecewise_construct_t, const T &t) + : is_shared(!CanUseInternalSpace), is_null(std::is_same_v) +{ + // confirm noexceptness + static constexpr bool isNothrowQVariantConstructible = noexcept(QVariant(t)); + static constexpr bool isNothrowCopyConstructible = std::is_nothrow_copy_constructible_v; + static constexpr bool isNothrowCopyAssignable = std::is_nothrow_copy_assignable_v; + + const QtPrivate::QMetaTypeInterface *iface = QtPrivate::qMetaTypeInterfaceForType(); + Q_ASSERT((quintptr(iface) & 0x3) == 0); + packedType = quintptr(iface) >> 2; + + if constexpr (CanUseInternalSpace) { + static_assert(isNothrowQVariantConstructible == isNothrowCopyConstructible); + static_assert(isNothrowQVariantConstructible == isNothrowCopyAssignable); + new (data.data) T(t); + } else { + static_assert(!isNothrowQVariantConstructible); // we allocate memory, even if T doesn't + data.shared = customConstructShared(sizeof(T), alignof(T), [=](void *where) { + new (where) T(t); + }); + } +} + +QT_END_NAMESPACE + +#endif // QVARIANT_P_H