diff options
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 11 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp | 45 |
2 files changed, 50 insertions, 6 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 2a86a1dd7f..c412f96110 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -228,20 +228,19 @@ public: if (size() == capacity()) { // i.e. size() != 0 T copy(t); reallocate(size(), size() << 1); - const qsizetype idx = s++; - new (data() + idx) T(std::move(copy)); + new (end()) T(std::move(copy)); } else { - const qsizetype idx = s++; - new (data() + idx) T(t); + new (end()) T(t); } + ++s; } void append(T &&t) { if (size() == capacity()) reallocate(size(), size() << 1); - const qsizetype idx = s++; - new (data() + idx) T(std::move(t)); + new (end()) T(std::move(t)); + ++s; } void append(const T *buf, qsizetype size); diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 3631f4f977..4944da71a9 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -30,6 +30,7 @@ #include <qvarlengtharray.h> #include <qvariant.h> #include <qscopeguard.h> +#include <qscopedvaluerollback.h> #include <memory> @@ -85,6 +86,7 @@ private slots: void removeLast(); void oldTests(); void appendCausingRealloc(); + void appendIsStronglyExceptionSafe(); void resize(); void realloc(); void iterators(); @@ -402,6 +404,49 @@ void tst_QVarLengthArray::appendCausingRealloc() d.append(i); } +void tst_QVarLengthArray::appendIsStronglyExceptionSafe() +{ +#ifdef QT_NO_EXCEPTIONS + QSKIP("This test requires exception support enabled in the compiler."); +#else + static bool throwOnCopyNow = false; + static bool throwOnMoveNow = false; + struct Thrower { + Thrower() = default; + Thrower(const Thrower &) + { + if (throwOnCopyNow) + throw 1; + } + Thrower &operator=(const Thrower &) = default; + Thrower(Thrower &&) + { + if (throwOnMoveNow) + throw 1; + } + Thrower &operator=(Thrower &&) = default; + ~Thrower() = default; + }; + + { + // ### TODO: QVLA isn't exception-safe when throwing during reallocation, + // ### so check with size() < capacity() for now + QVarLengthArray<Thrower, 2> vla(1); + { + Thrower t; + const QScopedValueRollback rb(throwOnCopyNow, true); + QVERIFY_THROWS_EXCEPTION(int, vla.push_back(t)); + QCOMPARE(vla.size(), 1); + } + { + const QScopedValueRollback rb(throwOnMoveNow, true); + QVERIFY_THROWS_EXCEPTION(int, vla.push_back({})); + QCOMPARE(vla.size(), 1); + } + } +#endif +} + void tst_QVarLengthArray::resize() { // Empty Movable |