diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h index 7d631a5e0c..6fa1e67acb 100644 --- a/src/corelib/tools/qtaggedpointer.h +++ b/src/corelib/tools/qtaggedpointer.h @@ -73,10 +73,8 @@ namespace QtPrivate { template ::TagType> class QTaggedPointer { - static constexpr quintptr tagMask = QtPrivate::TagInfo::alignment - 1; - static constexpr quintptr pointerMask = ~tagMask; - - using TagInternalType = typename QtPrivate::TagInfo::TagType; + static constexpr quintptr tagMask() { return QtPrivate::TagInfo::alignment - 1; } + static constexpr quintptr pointerMask() { return ~tagMask(); } public: using Type = T; @@ -87,7 +85,7 @@ public: { Q_STATIC_ASSERT(sizeof(Type*) == sizeof(QTaggedPointer)); - Q_ASSERT_X((quintptr(pointer) & tagMask) == 0, + Q_ASSERT_X((quintptr(pointer) & tagMask()) == 0, "QTaggedPointer", "Pointer is not aligned"); setTag(tag); @@ -111,37 +109,37 @@ public: QTaggedPointer &operator=(T *other) noexcept { - d = reinterpret_cast(other) | (d & tagMask); + d = reinterpret_cast(other) | (d & tagMask()); return *this; } QTaggedPointer &operator=(std::nullptr_t) noexcept { - d &= tagMask; + d &= tagMask(); return *this; } static constexpr TagType maximumTag() noexcept { - return TagType(TagInternalType(tagMask)); + return TagType(typename QtPrivate::TagInfo::TagType(tagMask())); } void setTag(TagType tag) { - Q_ASSERT_X((static_cast(tag) & pointerMask) == 0, + Q_ASSERT_X((static_cast::TagType>(tag) & pointerMask()) == 0, "QTaggedPointer::setTag", "Tag is larger than allowed by number of available tag bits"); - d = (d & pointerMask) | (static_cast(tag) & tagMask); + d = (d & pointerMask()) | (static_cast::TagType>(tag) & tagMask()); } TagType tag() const noexcept { - return TagType(TagInternalType(d & tagMask)); + return TagType(typename QtPrivate::TagInfo::TagType(d & tagMask())); } Type* pointer() const noexcept { - return reinterpret_cast(d & pointerMask); + return reinterpret_cast(d & pointerMask()); } bool isNull() const noexcept diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp index 36308d61bc..d98a53098f 100644 --- a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp +++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp @@ -43,6 +43,7 @@ private Q_SLOTS: void tag(); void objectMember(); void customTagType(); + void taggedLinkedList(); }; void tst_QTaggedPointer::construction() @@ -396,5 +397,32 @@ void tst_QTaggedPointer::customTagType() QCOMPARE(p.tag(), Bar::FirstTag | Bar::SecondTag); } +// Compile-only test to ensure it's possible to use tagged pointers +// with incomplete types. +struct LinkedListItem +{ + enum Tag { + NoTag = 0, + FirstTag = 1 + }; + Q_DECLARE_FLAGS(Tags, Tag) + + QTaggedPointer next; + + ~LinkedListItem() + { + delete next.pointer(); + } +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(LinkedListItem::Tags) + +void tst_QTaggedPointer::taggedLinkedList() +{ + QScopedPointer lli(new LinkedListItem); + lli->next = QTaggedPointer(new LinkedListItem); + lli->next.setTag(LinkedListItem::FirstTag); +} + QTEST_MAIN(tst_QTaggedPointer) #include "tst_qtaggedpointer.moc"