summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qtaggedpointer.h22
-rw-r--r--tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp28
2 files changed, 38 insertions, 12 deletions
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 <typename T, typename Tag = typename QtPrivate::TagInfo<T>::TagType>
class QTaggedPointer
{
- static constexpr quintptr tagMask = QtPrivate::TagInfo<T>::alignment - 1;
- static constexpr quintptr pointerMask = ~tagMask;
-
- using TagInternalType = typename QtPrivate::TagInfo<T>::TagType;
+ static constexpr quintptr tagMask() { return QtPrivate::TagInfo<T>::alignment - 1; }
+ static constexpr quintptr pointerMask() { return ~tagMask(); }
public:
using Type = T;
@@ -87,7 +85,7 @@ public:
{
Q_STATIC_ASSERT(sizeof(Type*) == sizeof(QTaggedPointer<Type>));
- Q_ASSERT_X((quintptr(pointer) & tagMask) == 0,
+ Q_ASSERT_X((quintptr(pointer) & tagMask()) == 0,
"QTaggedPointer<T, Tag>", "Pointer is not aligned");
setTag(tag);
@@ -111,37 +109,37 @@ public:
QTaggedPointer<T, Tag> &operator=(T *other) noexcept
{
- d = reinterpret_cast<quintptr>(other) | (d & tagMask);
+ d = reinterpret_cast<quintptr>(other) | (d & tagMask());
return *this;
}
QTaggedPointer<T, Tag> &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<T>::TagType(tagMask()));
}
void setTag(TagType tag)
{
- Q_ASSERT_X((static_cast<TagInternalType>(tag) & pointerMask) == 0,
+ Q_ASSERT_X((static_cast<typename QtPrivate::TagInfo<T>::TagType>(tag) & pointerMask()) == 0,
"QTaggedPointer<T, Tag>::setTag", "Tag is larger than allowed by number of available tag bits");
- d = (d & pointerMask) | (static_cast<TagInternalType>(tag) & tagMask);
+ d = (d & pointerMask()) | (static_cast<typename QtPrivate::TagInfo<T>::TagType>(tag) & tagMask());
}
TagType tag() const noexcept
{
- return TagType(TagInternalType(d & tagMask));
+ return TagType(typename QtPrivate::TagInfo<T>::TagType(d & tagMask()));
}
Type* pointer() const noexcept
{
- return reinterpret_cast<T*>(d & pointerMask);
+ return reinterpret_cast<T*>(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<LinkedListItem, Tag> next;
+
+ ~LinkedListItem()
+ {
+ delete next.pointer();
+ }
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(LinkedListItem::Tags)
+
+void tst_QTaggedPointer::taggedLinkedList()
+{
+ QScopedPointer<LinkedListItem> lli(new LinkedListItem);
+ lli->next = QTaggedPointer<LinkedListItem, LinkedListItem::Tag>(new LinkedListItem);
+ lli->next.setTag(LinkedListItem::FirstTag);
+}
+
QTEST_MAIN(tst_QTaggedPointer)
#include "tst_qtaggedpointer.moc"