summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetatype.cpp51
-rw-r--r--src/corelib/kernel/qmetatype.h18
-rw-r--r--src/corelib/kernel/qmetatype_p.h39
-rw-r--r--src/corelib/kernel/qvariant.cpp3
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp124
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h2
-rw-r--r--tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp67
7 files changed, 242 insertions, 62 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index f2676fa48f..16d51ae7a1 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -414,7 +414,9 @@ const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInte
The enum describes attributes of a type supported by QMetaType.
- \value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
+ \value NeedsConstruction This type has a non-trivial default constructor. If the flag is not set, instances can be safely initialized with memset to 0.
+ \value NeedsCopyConstruction (since 6.5) This type has a non-trivial copy construtcor. If the flag is not set, instances can be copied with memcpy.
+ \value NeedsMoveConstruction (since 6.5) This type has a non-trivial move constructor. If the flag is not set, instances can be moved with memcpy.
\value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects.
\value RelocatableType An instance of a type having this attribute can be safely moved to a different memory location using memcpy.
\omitvalue MovableType
@@ -429,6 +431,14 @@ const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInte
\omitvalue PointerToGadget
\omitvalue IsQmlList
\value IsConst Indicates that values of this types are immutable; for instance because they are pointers to const objects.
+
+ \note Before Qt 6.5, both the NeedsConstruction and NeedsDestruction flags
+ were incorrectly set if the either copy construtor or destructor were
+ non-trivial (that is, if the type was not trivial).
+
+ Note that the Needs flags may be set but the meta type may not have a
+ publicly-accessible constructor of the relevant type or a
+ publicly-accessible destructor.
*/
/*!
@@ -598,16 +608,17 @@ int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
*/
void *QMetaType::create(const void *copy) const
{
- if (d_ptr && (copy ? !!d_ptr->copyCtr : !!d_ptr->defaultCtr)) {
- void *where =
+ if (copy ? !isCopyConstructible() : !isDefaultConstructible())
+ return nullptr;
+
+ void *where =
#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__ ?
operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)) :
#endif
operator new(d_ptr->size);
- return construct(where, copy);
- }
- return nullptr;
+ QtMetaTypePrivate::construct(d_ptr, where, copy);
+ return where;
}
/*!
@@ -621,9 +632,8 @@ void *QMetaType::create(const void *copy) const
*/
void QMetaType::destroy(void *data) const
{
- if (d_ptr) {
- if (d_ptr->dtor)
- d_ptr->dtor(d_ptr, data);
+ if (data && isDestructible()) {
+ QtMetaTypePrivate::destruct(d_ptr, data);
if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
operator delete(data, std::align_val_t(d_ptr->alignment));
} else {
@@ -662,16 +672,11 @@ void *QMetaType::construct(void *where, const void *copy) const
{
if (!where)
return nullptr;
- if (d_ptr) {
- if (copy && d_ptr->copyCtr) {
- d_ptr->copyCtr(d_ptr, where, copy);
- return where;
- } else if (!copy && d_ptr->defaultCtr) {
- d_ptr->defaultCtr(d_ptr, where);
- return where;
- }
- }
- return nullptr;
+ if (copy ? !isCopyConstructible() : !isDefaultConstructible())
+ return nullptr;
+
+ QtMetaTypePrivate::construct(d_ptr, where, copy);
+ return where;
}
/*!
@@ -687,12 +692,8 @@ void *QMetaType::construct(void *where, const void *copy) const
*/
void QMetaType::destruct(void *data) const
{
- if (!data)
- return;
- if (d_ptr && d_ptr->dtor) {
- d_ptr->dtor(d_ptr, data);
- return;
- }
+ if (data && isDestructible())
+ QtMetaTypePrivate::destruct(d_ptr, data);
}
static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 28d246d2cf..7a66767258 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -381,6 +381,9 @@ public:
IsPointer = 0x800,
IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T>
IsConst = 0x2000,
+ // since 6.5:
+ NeedsCopyConstruction = 0x4000,
+ NeedsMoveConstruction = 0x8000,
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@@ -1187,8 +1190,10 @@ namespace QtPrivate {
struct QMetaTypeTypeFlags
{
enum { Flags = (QTypeInfo<T>::isRelocatable ? QMetaType::RelocatableType : 0)
- | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
- | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
+ | (!std::is_trivially_default_constructible_v<T> ? QMetaType::NeedsConstruction : 0)
+ | (!std::is_trivially_destructible_v<T> ? QMetaType::NeedsDestruction : 0)
+ | (!std::is_trivially_copy_constructible_v<T> ? QMetaType::NeedsCopyConstruction : 0)
+ | (!std::is_trivially_move_constructible_v<T> ? QMetaType::NeedsMoveConstruction : 0)
| (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
| (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
| (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
@@ -2312,10 +2317,11 @@ class QMetaTypeForType
{
public:
static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
+ static constexpr unsigned Flags = QMetaTypeTypeFlags<S>::Flags;
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
{
- if constexpr (std::is_default_constructible_v<S>) {
+ if constexpr (std::is_default_constructible_v<S> && !std::is_trivially_default_constructible_v<S>) {
return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
} else {
return nullptr;
@@ -2324,7 +2330,7 @@ public:
static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
{
- if constexpr (std::is_copy_constructible_v<S>) {
+ if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
return [](const QMetaTypeInterface *, void *addr, const void *other) {
new (addr) S(*reinterpret_cast<const S *>(other));
};
@@ -2335,7 +2341,7 @@ public:
static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
{
- if constexpr (std::is_move_constructible_v<S>) {
+ if constexpr (std::is_move_constructible_v<S> && !std::is_trivially_move_constructible_v<S>) {
return [](const QMetaTypeInterface *, void *addr, void *other) {
new (addr) S(std::move(*reinterpret_cast<S *>(other)));
};
@@ -2386,7 +2392,7 @@ struct QMetaTypeInterfaceWrapper
/*.revision=*/ 0,
/*.alignment=*/ alignof(T),
/*.size=*/ sizeof(T),
- /*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
+ /*.flags=*/ QMetaTypeForType<T>::Flags,
/*.typeId=*/ BuiltinMetaType<T>::value,
/*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
/*.name=*/ QMetaTypeForType<T>::getName(),
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index 89f1854bf6..08c1aeaa1d 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -141,21 +141,52 @@ inline bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) n
inline bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
- // ### broken
- return checkMetaTypeFlagOrPointer(iface, iface->copyCtr, QMetaType::NeedsConstruction);
+ return checkMetaTypeFlagOrPointer(iface, iface->copyCtr, QMetaType::NeedsCopyConstruction);
}
inline bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
- return iface->moveCtr;
+ return checkMetaTypeFlagOrPointer(iface, iface->moveCtr, QMetaType::NeedsMoveConstruction);
}
inline bool isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
- // ### broken
return checkMetaTypeFlagOrPointer(iface, iface->dtor, QMetaType::NeedsDestruction);
}
+inline void defaultConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
+{
+ Q_ASSERT(isDefaultConstructible(iface));
+ if (iface->defaultCtr)
+ iface->defaultCtr(iface, where);
+ else
+ memset(where, 0, iface->size);
+}
+
+inline void copyConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
+{
+ Q_ASSERT(isCopyConstructible(iface));
+ if (iface->copyCtr)
+ iface->copyCtr(iface, where, copy);
+ else
+ memcpy(where, copy, iface->size);
+}
+
+inline void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
+{
+ if (copy)
+ copyConstruct(iface, where, copy);
+ else
+ defaultConstruct(iface, where);
+}
+
+inline void destruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
+{
+ Q_ASSERT(isDestructible(iface));
+ if (iface->dtor)
+ iface->dtor(iface, where);
+}
+
const char *typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d);
template<typename T>
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 59148e1579..0fd14296e9 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -222,7 +222,8 @@ static void customConstruct(QVariant::Private *d, const void *copy)
return;
}
- if (!isCopyConstructible(iface) || (!copy && !isDefaultConstructible(iface))) {
+ if (!isCopyConstructible(iface) || (!copy && !isDefaultConstructible(iface))
+ || !isDestructible(iface)) {
*d = QVariant::Private();
qWarning("QVariant: Provided metatype does not support "
"destruction, copy and default construction");
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index c25c5c6b16..dc7936cb23 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -397,13 +397,15 @@ protected:
++failureCount;
qWarning() << "Wrong typeInfo returned for" << tp;
}
- if (!info.isRegistered()) {
+ if (info.flags() != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction |
+ QMetaType::NeedsCopyConstruction | QMetaType::NeedsMoveConstruction)) {
++failureCount;
- qWarning() << name << "is not a registered metatype";
+ qWarning() << "Wrong typeInfo returned for" << tp << "got"
+ << Qt::showbase << Qt::hex << info.flags();
}
- if (QMetaType::typeFlags(tp) != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) {
+ if (!info.isRegistered()) {
++failureCount;
- qWarning() << "Wrong typeInfo returned for" << tp;
+ qWarning() << name << "is not a registered metatype";
}
if (!QMetaType::isRegistered(tp)) {
++failureCount;
@@ -981,7 +983,9 @@ template <typename T> void addFlagsRow(const char *name, int id = qMetaTypeId<T>
QTest::newRow(name)
<< id
<< bool(QTypeInfo<T>::isRelocatable)
- << bool(QTypeInfo<T>::isComplex)
+ << bool(!std::is_trivially_default_constructible_v<T>)
+ << bool(!std::is_trivially_copy_constructible_v<T>)
+ << bool(!std::is_trivially_destructible_v<T>)
<< bool(QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value)
<< bool(std::is_enum<T>::value)
<< false;
@@ -991,15 +995,17 @@ void tst_QMetaType::flags_data()
{
QTest::addColumn<int>("type");
QTest::addColumn<bool>("isRelocatable");
- QTest::addColumn<bool>("isComplex");
+ QTest::addColumn<bool>("needsConstruction");
+ QTest::addColumn<bool>("needsCopyConstruction");
+ QTest::addColumn<bool>("needsDestruction");
QTest::addColumn<bool>("isPointerToQObject");
QTest::addColumn<bool>("isEnum");
QTest::addColumn<bool>("isQmlList");
// invalid ids.
- QTest::newRow("-1") << -1 << false << false << false << false << false;
- QTest::newRow("-124125534") << -124125534 << false << false << false << false << false;
- QTest::newRow("124125534") << 124125534 << false << false << false << false << false;
+ QTest::newRow("-1") << -1 << false << false << false << false << false << false << false;
+ QTest::newRow("-124125534") << -124125534 << false << false << false << false << false << false << false;
+ QTest::newRow("124125534") << 124125534 << false << false << false << false << false << false << false;
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
addFlagsRow<RealType>(#RealType, MetaTypeId);
@@ -1029,7 +1035,9 @@ void tst_QMetaType::flags()
{
QFETCH(int, type);
QFETCH(bool, isRelocatable);
- QFETCH(bool, isComplex);
+ QFETCH(bool, needsConstruction);
+ QFETCH(bool, needsCopyConstruction);
+ QFETCH(bool, needsDestruction);
QFETCH(bool, isPointerToQObject);
QFETCH(bool, isEnum);
QFETCH(bool, isQmlList);
@@ -1037,14 +1045,92 @@ void tst_QMetaType::flags()
ignoreInvalidMetaTypeWarning(type);
QMetaType meta(type);
- QCOMPARE(bool(meta.flags() & QMetaType::NeedsConstruction), isComplex);
- QCOMPARE(bool(meta.flags() & QMetaType::NeedsDestruction), isComplex);
+ QCOMPARE(bool(meta.flags() & QMetaType::NeedsConstruction), needsConstruction);
+ QCOMPARE(bool(meta.flags() & QMetaType::NeedsCopyConstruction), needsCopyConstruction);
+ QCOMPARE(bool(meta.flags() & QMetaType::NeedsDestruction), needsDestruction);
QCOMPARE(bool(meta.flags() & QMetaType::RelocatableType), isRelocatable);
QCOMPARE(bool(meta.flags() & QMetaType::PointerToQObject), isPointerToQObject);
QCOMPARE(bool(meta.flags() & QMetaType::IsEnumeration), isEnum);
QCOMPARE(bool(meta.flags() & QMetaType::IsQmlList), isQmlList);
}
+class NonDefaultConstructible
+{
+ NonDefaultConstructible(int) {}
+};
+
+struct MoveOnly
+{
+ MoveOnly() = default;
+ MoveOnly(const MoveOnly &) = delete;
+ MoveOnly(MoveOnly &&) = default;
+ MoveOnly &operator=(const MoveOnly &) = delete;
+ MoveOnly &operator=(MoveOnly &&) = default;
+};
+
+class Indestructible
+{
+protected:
+ ~Indestructible() {}
+};
+
+template <typename T> static void addFlags2Row(QMetaType metaType = QMetaType::fromType<T>())
+{
+ QTest::newRow(metaType.name() ? metaType.name() : "UnknownType")
+ << metaType
+ << std::is_default_constructible_v<T>
+ << std::is_copy_constructible_v<T>
+ << std::is_move_constructible_v<T>
+ << std::is_destructible_v<T>
+ << (QTypeTraits::has_operator_equal<T>::value || QTypeTraits::has_operator_less_than<T>::value)
+ << QTypeTraits::has_operator_less_than<T>::value;
+};
+
+void tst_QMetaType::flags2_data()
+{
+ QTest::addColumn<QMetaType>("type");
+ QTest::addColumn<bool>("isDefaultConstructible");
+ QTest::addColumn<bool>("isCopyConstructible");
+ QTest::addColumn<bool>("isMoveConstructible");
+ QTest::addColumn<bool>("isDestructible");
+ QTest::addColumn<bool>("isEqualityComparable");
+ QTest::addColumn<bool>("isOrdered");
+
+ addFlags2Row<void>(QMetaType());
+ addFlags2Row<void>();
+
+#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
+ addFlags2Row<RealType>();
+ QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ADD_METATYPE_TEST_ROW)
+ QT_FOR_EACH_STATIC_CORE_CLASS(ADD_METATYPE_TEST_ROW)
+ QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(ADD_METATYPE_TEST_ROW)
+ QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW)
+#undef ADD_METATYPE_TEST_ROW
+
+ addFlags2Row<NonDefaultConstructible>();
+ addFlags2Row<MoveOnly>();
+ addFlags2Row<QObject>();
+ addFlags2Row<Indestructible>();
+}
+
+void tst_QMetaType::flags2()
+{
+ QFETCH(QMetaType, type);
+ QFETCH(bool, isDefaultConstructible);
+ QFETCH(bool, isCopyConstructible);
+ QFETCH(bool, isMoveConstructible);
+ QFETCH(bool, isDestructible);
+ QFETCH(bool, isEqualityComparable);
+ QFETCH(bool, isOrdered);
+
+ QCOMPARE(type.isDefaultConstructible(), isDefaultConstructible);
+ QCOMPARE(type.isCopyConstructible(), isCopyConstructible);
+ QCOMPARE(type.isMoveConstructible(), isMoveConstructible);
+ QCOMPARE(type.isDestructible(), isDestructible);
+ QCOMPARE(type.isEqualityComparable(), isEqualityComparable);
+ QCOMPARE(type.isOrdered(), isOrdered);
+}
+
void tst_QMetaType::flagsBinaryCompatibility6_0_data()
{
// Changing traits of a built-in type is illegal from BC point of view.
@@ -1092,14 +1178,12 @@ void tst_QMetaType::flagsBinaryCompatibility6_0()
const auto currentFlags = QMetaType::typeFlags(id);
auto expectedFlags = QMetaType::TypeFlags(flags);
- if (!(currentFlags.testFlag(QMetaType::NeedsConstruction) && currentFlags.testFlag(QMetaType::NeedsDestruction))) {
- if (expectedFlags.testFlag(QMetaType::NeedsConstruction) && expectedFlags.testFlag(QMetaType::NeedsDestruction)) {
- // If type changed from RELOCATABLE to trivial, that's fine
- expectedFlags.setFlag(QMetaType::NeedsConstruction, false);
- expectedFlags.setFlag(QMetaType::NeedsDestruction, false);
- }
- }
- quint32 mask_5_0 = 0x1fb; // Only compare the values that were already defined in 5.0
+
+ // Only compare the values that were already defined in 5.0.
+ // In 6.5, some types lost NeedsConstruction and NeedsDestruction, but
+ // that's acceptable if that's because they were trivial
+ quint32 mask_5_0 = 0x1ff & ~quint32(QMetaType::NeedsConstruction | QMetaType::NeedsDestruction
+ | QMetaType::RelocatableType);
QCOMPARE(quint32(currentFlags) & mask_5_0, quint32(expectedFlags) & mask_5_0);
}
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 37d9f958e9..796d64c5a3 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -69,6 +69,8 @@ private slots:
void alignOf();
void flags_data();
void flags();
+ void flags2_data();
+ void flags2();
void flagsBinaryCompatibility6_0_data();
void flagsBinaryCompatibility6_0();
void construct_data();
diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
index f4d64567ec..686e2a0e8b 100644
--- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
+++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
@@ -20,6 +20,8 @@ private slots:
void sizeOf();
void flags_data();
void flags();
+ void flags2_data();
+ void flags2();
void construct_data();
void construct();
void constructCopy_data();
@@ -298,15 +300,19 @@ template <typename T> void addFlagsRow(const char *name, int id = qMetaTypeId<T>
QTest::newRow(name)
<< id
<< bool(QTypeInfo<T>::isRelocatable)
- << bool(QTypeInfo<T>::isComplex);
+ << bool(!std::is_trivially_default_constructible_v<T>)
+ << bool(!std::is_trivially_copy_constructible_v<T>)
+ << bool(!std::is_trivially_destructible_v<T>);
}
-
+// tst_QGuiMetaType::flags is nearly identical to tst_QMetaType::flags
void tst_QGuiMetaType::flags_data()
{
QTest::addColumn<int>("type");
QTest::addColumn<bool>("isRelocatable");
- QTest::addColumn<bool>("isComplex");
+ QTest::addColumn<bool>("needsConstruction");
+ QTest::addColumn<bool>("needsCopyConstruction");
+ QTest::addColumn<bool>("needsDestruction");
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
addFlagsRow<RealType>(#RealType, MetaTypeId);
@@ -318,13 +324,62 @@ void tst_QGuiMetaType::flags()
{
QFETCH(int, type);
QFETCH(bool, isRelocatable);
- QFETCH(bool, isComplex);
+ QFETCH(bool, needsConstruction);
+ QFETCH(bool, needsCopyConstruction);
+ QFETCH(bool, needsDestruction);
- QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), isComplex);
- QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), isComplex);
+ QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), needsConstruction);
+ QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsCopyConstruction), needsCopyConstruction);
+ QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), needsDestruction);
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::RelocatableType), isRelocatable);
}
+template <typename T> static void addFlags2Row(QMetaType metaType = QMetaType::fromType<T>())
+{
+ QTest::newRow(metaType.name() ? metaType.name() : "UnknownType")
+ << metaType
+ << std::is_default_constructible_v<T>
+ << std::is_copy_constructible_v<T>
+ << std::is_move_constructible_v<T>
+ << std::is_destructible_v<T>
+ << (QTypeTraits::has_operator_equal<T>::value || QTypeTraits::has_operator_less_than<T>::value)
+ << QTypeTraits::has_operator_less_than<T>::value;
+};
+
+// tst_QGuiMetaType::flags2 is nearly identical to tst_QMetaType::flags2
+void tst_QGuiMetaType::flags2_data()
+{
+ QTest::addColumn<QMetaType>("type");
+ QTest::addColumn<bool>("isDefaultConstructible");
+ QTest::addColumn<bool>("isCopyConstructible");
+ QTest::addColumn<bool>("isMoveConstructible");
+ QTest::addColumn<bool>("isDestructible");
+ QTest::addColumn<bool>("isEqualityComparable");
+ QTest::addColumn<bool>("isOrdered");
+
+#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
+ addFlags2Row<RealType>();
+QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW)
+#undef ADD_METATYPE_TEST_ROW
+}
+
+void tst_QGuiMetaType::flags2()
+{
+ QFETCH(QMetaType, type);
+ QFETCH(bool, isDefaultConstructible);
+ QFETCH(bool, isCopyConstructible);
+ QFETCH(bool, isMoveConstructible);
+ QFETCH(bool, isDestructible);
+ QFETCH(bool, isEqualityComparable);
+ QFETCH(bool, isOrdered);
+
+ QCOMPARE(type.isDefaultConstructible(), isDefaultConstructible);
+ QCOMPARE(type.isCopyConstructible(), isCopyConstructible);
+ QCOMPARE(type.isMoveConstructible(), isMoveConstructible);
+ QCOMPARE(type.isDestructible(), isDestructible);
+ QCOMPARE(type.isEqualityComparable(), isEqualityComparable);
+ QCOMPARE(type.isOrdered(), isOrdered);
+}
void tst_QGuiMetaType::construct_data()
{