diff options
author | Marc Mutz <[email protected]> | 2025-05-21 13:14:20 +0200 |
---|---|---|
committer | Marc Mutz <[email protected]> | 2025-05-22 12:08:48 +0000 |
commit | 82015992c853b50dac167da26b8b858ac4794c66 (patch) | |
tree | 65ffecf6a0d7d5ee9bb2183ecd62695bf7f80e73 | |
parent | b9c92154062a1d6c0f62860a9fa775cba6bac9ef (diff) |
We have implementation divergence with libc++'s ~unique_ptr()
behavior, so make sure QScopedPointer behaves the same way as
unique_ptr is spec'ed, even though to check it, one has to rely
on UB, at least according to LLVM devs (I don't think the test
as written invokes UB).
Code's a bit duplicated. I tried making the struct a template,
but it's just too much of a fuss (needs a variable template,
which we can't use in Qt 5), so I decided to use cut'n'paste.
Task-number: QTBUG-137069
Pick-to: 6.9 6.8 6.5 5.15
Change-Id: I8b55718eaf3c6ad9a4d89d4fc9d64f0c41bb21fa
Reviewed-by: Ahmad Samir <[email protected]>
-rw-r--r-- | tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp index 3468c97f429..97ce0271634 100644 --- a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp +++ b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp @@ -4,6 +4,8 @@ #include <QTest> #include <QtCore/QScopedPointer> +#include <QtCore/qstdlibdetection.h> + /*! \class tst_QScopedPointer \internal @@ -22,6 +24,7 @@ private Q_SLOTS: void dataOnValue(); void dataSignature(); void reset(); + void resetDeleteOrdering(); void dereferenceOperator(); void dereferenceOperatorSignature(); void pointerOperator(); @@ -127,6 +130,85 @@ void tst_QScopedPointer::reset() } } +void tst_QScopedPointer::resetDeleteOrdering() +{ + { + struct CheckingDeleter; + using SP = QScopedPointer<int, CheckingDeleter>; + static const SP *instance = nullptr; // QScopedPointer does not handle stateful deleters + static const int *expected = nullptr; + + struct CheckingDeleter { + static void cleanup(int *p) + { + const auto *value = instance->get(); + std::unique_ptr<int> deleter(p); + QT_TRY { QCOMPARE(value, expected); } QT_CATCH(...) {} // eat QTest failure exception, if any + } + void operator()(int *p) { cleanup(p); } + }; + + // reset() + { + SP p(new int{42}); + instance = &p; + expected = nullptr; + p.reset(); + } + if (QTest::currentTestFailed()) + return; + // destructor + { + SP p(new int{48}); + instance = &p; + expected = p.get(); // inconsistent with reset(), but consistent with unique_ptr + } + if (QTest::currentTestFailed()) + return; + } + + // comparison with unique_ptr: + { + struct CheckingDeleter; + using UP = std::unique_ptr<int, CheckingDeleter>; + // unique_ptr handles stateful deleters, but be consistent with QScopedPointer test + static const UP *instance = nullptr; + static const int *expected = nullptr; + + struct CheckingDeleter { + void operator()(int *p) const + { + const auto *value = instance->get(); + std::unique_ptr<int> deleter(p); + QT_TRY { QCOMPARE(value, expected); } QT_CATCH(...) {} // eat QTest failure exception, if any + } + }; + + // reset() + { + UP p(new int{42}); + instance = &p; + expected = nullptr; // https://eel.is/c++draft/unique.ptr#single.modifiers-3 ... 5 + p.reset(); + } + if (QTest::currentTestFailed()) + return; + // destructor +#ifdef Q_STL_LIBCPP + // This would fail on libc++ https://github.com/llvm/llvm-project/issues/108149 + if (false) +#endif + { + UP p(new int{48}); + instance = &p; + expected = p.get(); // https://eel.is/c++draft/unique.ptr#single.dtor + } + if (QTest::currentTestFailed()) + return; + + } +} + class AbstractClass { public: |