summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/tools
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2021-12-08 17:27:52 +0100
committerMarc Mutz <marc.mutz@qt.io>2021-12-09 18:59:55 +0000
commite297e80fd0ec6ce4c97ee1b40426c76377b45ecc (patch)
treecf6ee3f6f0a2bcb2ac57a63035d1f0ceba914a50 /tests/auto/corelib/tools
parentc1f510b3596eaefb54cec83206cccbfecd25fc3b (diff)
QVarLengthArray: make reallocation strongly exception safe
The old code had several bugs: - it immediately clobbered *this with new state, before having copied over the elements from the old to the new buffer - when buffer relocation threw, it would keep the new (partially-filled) buffer and throw away the old - it unconditionally used std::move() for non-relocatable types, making it impossible to restore the original buffer when a move throws Instead of clobbering *this with new state, do all the work on the side and change *this only once the reallocation has happened successfully. Also use q_uninitialized_relocate_n() and unique_ptr in the implementation to simplify the code. The former got the necessary update to use std::move_if_noexcept() instead of an unconditional std::move() for the non-relocatable case. [ChangeLog][QtCore][QVarLengthArray] The append()-like functions are now strongly exception safe. This means reallocation will now use copies instead of moves, unless the value_type has a noexcept move constructor. Fixes: QTBUG-99039 Change-Id: I031251b8d14ac045592d01caed59d4638c3d9892 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'tests/auto/corelib/tools')
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp24
1 files changed, 22 insertions, 2 deletions
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index 4944da71a9..8f2871a54f 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -429,8 +429,6 @@ void tst_QVarLengthArray::appendIsStronglyExceptionSafe()
};
{
- // ### TODO: QVLA isn't exception-safe when throwing during reallocation,
- // ### so check with size() < capacity() for now
QVarLengthArray<Thrower, 2> vla(1);
{
Thrower t;
@@ -443,6 +441,28 @@ void tst_QVarLengthArray::appendIsStronglyExceptionSafe()
QVERIFY_THROWS_EXCEPTION(int, vla.push_back({}));
QCOMPARE(vla.size(), 1);
}
+ vla.push_back({});
+ QCOMPARE(vla.size(), 2);
+ {
+ Thrower t;
+ {
+ // tests the copy inside append()
+ const QScopedValueRollback rb(throwOnCopyNow, true);
+ QVERIFY_THROWS_EXCEPTION(int, vla.push_back(t));
+ QCOMPARE(vla.size(), 2);
+ }
+ {
+ // tests the move inside reallocate()
+ const QScopedValueRollback rb(throwOnMoveNow, true);
+ QVERIFY_THROWS_EXCEPTION(int, vla.push_back(t));
+ QCOMPARE(vla.size(), 2);
+ }
+ }
+ {
+ const QScopedValueRollback rb(throwOnMoveNow, true);
+ QVERIFY_THROWS_EXCEPTION(int, vla.push_back({}));
+ QCOMPARE(vla.size(), 2);
+ }
}
#endif
}