diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h index 504645993a2..a08912c4a57 100644 --- a/src/corelib/tools/qtaggedpointer.h +++ b/src/corelib/tools/qtaggedpointer.h @@ -72,12 +72,31 @@ public: return !isNull(); } - QTaggedPointer &operator=(T *other) noexcept +#ifdef Q_QDOC + QTaggedPointer &operator=(T *other) noexcept; +#else + // Disables the usage of `ptr = {}`, which would go through this operator + // (rather than using the implicitly-generated assignment operator). + // The operators have different semantics: the ones here leave the tag intact, + // the implicitly-generated one overwrites it. + template , bool> = false> + QTaggedPointer &operator=(U *other) noexcept { - d = reinterpret_cast(other) | (d & tagMask()); + T *otherT = other; + d = reinterpret_cast(otherT) | (d & tagMask()); return *this; } + template , bool> = false> + QTaggedPointer &operator=(U) noexcept + { + d = reinterpret_cast(static_cast(nullptr)) | (d & tagMask()); + return *this; + } +#endif + static constexpr Tag maximumTag() noexcept { return TagType(typename QtPrivate::TagInfo::TagType(tagMask())); diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp index 752bf48d93a..5cb82329d0c 100644 --- a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp +++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp @@ -11,6 +11,7 @@ class tst_QTaggedPointer : public QObject private Q_SLOTS: void constExpr(); void construction(); + void assignment(); void dereferenceOperator(); void pointerOperator(); void negationOperator(); @@ -80,6 +81,47 @@ void tst_QTaggedPointer::construction() } } +void tst_QTaggedPointer::assignment() +{ + QScopedPointer rawPointer(new int(5)); + QTaggedPointer p(rawPointer.data(), 0x1); + QTaggedPointer p2(rawPointer.data(), 0x2); + + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + QCOMPARE(p2.data(), rawPointer.data()); + QCOMPARE(p2.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = p2; + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x0)); +} + class AbstractClass { public: