From 9160cf6a070e8c18e2ecc764d1a957b3e37212b5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 22 Jul 2022 09:11:16 -0700 Subject: [PATCH] QVariant: do allow non-default-constructible types So long as you only ask us to copy it. Copying is mandatory, though. I'll firm up the warning in a later commit, which may not get cherry- picked as far back. Fixes: QTBUG-105140 Change-Id: I3859764fed084846bcb0fffd170432abf65dc197 Reviewed-by: Fabian Kosmale (cherry picked from commit df0085d3a28005e84eb7688cc2575a121ba322aa) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qvariant.cpp | 2 +- .../corelib/kernel/qvariant/tst_qvariant.cpp | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index a2711a48f85..94d062f6332 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -220,7 +220,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) *d = QVariant::Private(); return; } - if (!(iface->copyCtr && iface->defaultCtr)) { + if (!iface->copyCtr || (!copy && !iface->defaultCtr)) { // QVariant requires type to be copy and default constructible *d = QVariant::Private(); qWarning("QVariant: Provided metatype does not support " diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 240c25ae480..f20fd0cd878 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -289,6 +289,7 @@ private slots: void constructFromIncompatibleMetaType_data(); void constructFromIncompatibleMetaType(); + void copyNonDefaultConstructible(); private: void dataStream_data(QDataStream::Version version); @@ -5110,11 +5111,19 @@ void tst_QVariant::equalsWithoutMetaObject() QVERIFY(qobjectVariant != noMetaObjectVariant); } -class NonDefaultConstructible +struct NonDefaultConstructible { - NonDefaultConstructible(int ) {} + NonDefaultConstructible(int i) :i(i) {} + int i; + friend bool operator==(NonDefaultConstructible l, NonDefaultConstructible r) + { return l.i == r.i; } }; +template <> char *QTest::toString(const NonDefaultConstructible &ndc) +{ + return qstrdup('{' + QByteArray::number(ndc.i) + '}'); +} + struct Indestructible { Indestructible() {} @@ -5154,5 +5163,23 @@ void tst_QVariant::constructFromIncompatibleMetaType() QVERIFY(!QVariant(regular).convert(type)); } +void tst_QVariant::copyNonDefaultConstructible() +{ + NonDefaultConstructible ndc(42); + QVariant var(QMetaType::fromType(), &ndc); + QVERIFY(var.isDetached()); + QCOMPARE(var.metaType(), QMetaType::fromType()); + QVERIFY(var.constData() != &ndc); + + // qvariant_cast and QVariant::value don't compile + QCOMPARE(*static_cast(var.constData()), ndc); + + QVariant var2 = var; + var2.detach(); // force another copy + QVERIFY(var2.isDetached()); + QVERIFY(var2.constData() != var.constData()); + QCOMPARE(var2, var); +} + QTEST_MAIN(tst_QVariant) #include "tst_qvariant.moc"