From a2f83283a64460ca26530321f8eb64f3ddfe4c8b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 23 Aug 2010 13:44:12 +0200 Subject: Fix assignment of a container included in the container itself Task-number: QTBUG-13079 Reviewed-by: Joao --- src/corelib/tools/qhash.h | 5 +- src/corelib/tools/qlinkedlist.h | 5 +- src/corelib/tools/qlist.h | 5 +- src/corelib/tools/qmap.h | 5 +- src/corelib/tools/qvector.h | 5 +- tests/auto/collections/tst_collections.cpp | 87 ++++++++++++++++++++++++++++++ 6 files changed, 102 insertions(+), 10 deletions(-) diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 0777f06..c7e4bc1 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -589,10 +589,11 @@ template Q_INLINE_TEMPLATE QHash &QHash::operator=(const QHash &other) { if (d != other.d) { - other.d->ref.ref(); + QHashData *o = other.d; + o->ref.ref(); if (!d->ref.deref()) freeData(d); - d = other.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index d145fe3..9b3efa3 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -312,10 +312,11 @@ template QLinkedList &QLinkedList::operator=(const QLinkedList &l) { if (d != l.d) { - l.d->ref.ref(); + QLinkedListData *o = l.d; + o->ref.ref(); if (!d->ref.deref()) free(d); - d = l.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 722744c..d843cbe 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -424,10 +424,11 @@ template Q_INLINE_TEMPLATE QList &QList::operator=(const QList &l) { if (d != l.d) { - l.d->ref.ref(); + QListData::Data *o = l.d; + o->ref.ref(); if (!d->ref.deref()) free(d); - d = l.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index e4b73a1..1c2aad3 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -426,10 +426,11 @@ template Q_INLINE_TEMPLATE QMap &QMap::operator=(const QMap &other) { if (d != other.d) { - other.d->ref.ref(); + QMapData* o = other.d; + o->ref.ref(); if (!d->ref.deref()) freeData(d); - d = other.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index c2e2485..b762b8a 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -377,10 +377,11 @@ inline void QVector::replace(int i, const T &t) template QVector &QVector::operator=(const QVector &v) { - v.d->ref.ref(); + QVectorData *o = v.d; + o->ref.ref(); if (!d->ref.deref()) free(p); - d = v.d; + d = o; if (!d->sharable) detach_helper(); return *this; diff --git a/tests/auto/collections/tst_collections.cpp b/tests/auto/collections/tst_collections.cpp index d092c34..8617e02 100644 --- a/tests/auto/collections/tst_collections.cpp +++ b/tests/auto/collections/tst_collections.cpp @@ -165,6 +165,7 @@ private slots: void containerTypedefs(); void forwardDeclared(); void alignment(); + void QTBUG13079_collectionInsideCollection(); }; struct LargeStatic { @@ -3589,5 +3590,91 @@ void tst_Collections::alignment() } #endif +#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS + +template class C> +struct QTBUG13079_Node { + C children; + QString s; + + ~QTBUG13079_Node() { + children.begin(); //play with memory + } +}; +template class C> void QTBUG13079_collectionInsideCollectionImpl() +{ + C > nodeList; + nodeList << QTBUG13079_Node(); + nodeList.first().s = "parent"; + nodeList.first().children << QTBUG13079_Node(); + nodeList.first().children.first().s = "child"; + + nodeList = nodeList.first().children; + QCOMPARE(nodeList.first().s, QString::fromLatin1("child")); + + nodeList = nodeList.first().children; + QCOMPARE(nodeList.count(), 0); + nodeList << QTBUG13079_Node(); +} + +template class C> +struct QTBUG13079_NodeAssoc { + C children; + QString s; + + ~QTBUG13079_NodeAssoc() { + children.begin(); //play with memory + } +}; +template class C> void QTBUG13079_collectionInsideCollectionAssocImpl() +{ + C > nodeMap; + nodeMap[18] = QTBUG13079_NodeAssoc(); + nodeMap[18].s = "parent"; + nodeMap[18].children[12] = QTBUG13079_NodeAssoc(); + nodeMap[18].children[12].s = "child"; + + nodeMap = nodeMap[18].children; + QCOMPARE(nodeMap[12].s, QString::fromLatin1("child")); + + nodeMap = nodeMap[12].children; + QCOMPARE(nodeMap.count(), 0); + nodeMap[42] = QTBUG13079_NodeAssoc(); +} + + +static quint32 qHash(const QTBUG13079_Node &) +{ + return 0; +} + +bool operator==(const QTBUG13079_Node &a, const QTBUG13079_Node &b) +{ + return a.s == b.s && a.children == b.children; +} + +#endif + +void tst_Collections::QTBUG13079_collectionInsideCollection() +{ +#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + + { + QSet > nodeSet; + nodeSet << QTBUG13079_Node(); + nodeSet = nodeSet.begin()->children; + QCOMPARE(nodeSet.count(), 0); + } + + QTBUG13079_collectionInsideCollectionAssocImpl(); + QTBUG13079_collectionInsideCollectionAssocImpl(); +#endif +} + QTEST_APPLESS_MAIN(tst_Collections) #include "tst_collections.moc" -- cgit v0.12