summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2021-10-11 12:02:27 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2021-10-16 13:48:27 +0200
commitb6cbd9c43afc7e005c1f78e1d0f700524930ed71 (patch)
tree6991cf9c004861c46cc29b9518e3f07eea07b342
parent0220484329029fc7598dfe11ba35ea10c3126477 (diff)
QList: deprecate iterator<->pointer implicit conversions (2/3)
The constructor from a raw pointer should be 1) constexpr, 2) explicit, and 3) *private*. We can do 1) without too much trouble. 2) is a (easy to fix) SIC in case of implicit conversions accidentally relied upon from somewhere. 3) cannot be "easily" fixed by user code (they have to refactor), and also, it's a BIC on Windows which encodes class members' access in symbols. Someone may have been exporting some QList subclass, in turn exporting the iterator classes, and therefore that someone now has the constructors' symbols with a given access. So, don't do 2+3 _just yet_ for user code, but set a deadline: Qt 6.5 is the last that will support this. On Qt 6.6, we switch. All of this on non-Windows, againt to avoid an ABI break. One can opt-in at any time via a suitable define. Given we have this define, use it to guard the other way around as well: conversions from an iterator to a raw pointer should never be explicit (there's std::to_address for this). [ChangeLog][QtCore][QList] Converting a QList's iterator from and to a raw pointer is deprecated, and will get removed in Qt 6.6. User code can prepare for the change by defining QT_STRICT_QLIST_ITERATORS. Change-Id: I0f34bfa3ac055c02af5a3ca159180304660dfc11 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--cmake/QtInternalTargets.cmake7
-rw-r--r--src/corelib/tools/qlist.h24
2 files changed, 27 insertions, 4 deletions
diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake
index c4bc90247a..a6c77d10cb 100644
--- a/cmake/QtInternalTargets.cmake
+++ b/cmake/QtInternalTargets.cmake
@@ -111,6 +111,13 @@ endif()
target_compile_definitions(PlatformCommonInternal INTERFACE QT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
target_compile_definitions(PlatformCommonInternal INTERFACE $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>)
+if(FEATURE_developer_build)
+ # This causes an ABI break on Windows, so we cannot unconditionally
+ # enable it. Keep it for developer builds only for now.
+ ### Qt 7: remove the if.
+ target_compile_definitions(PlatformCommonInternal INTERFACE QT_STRICT_QLIST_ITERATORS)
+endif()
+
function(qt_internal_apply_bitcode_flags target)
# See mkspecs/features/uikit/bitcode.prf
set(release_flags "-fembed-bitcode")
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index e7dbb294b0..fe8d36a9c7 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -92,6 +92,10 @@ public:
template <> struct QListSpecialMethods<QByteArray>;
template <> struct QListSpecialMethods<QString>;
+#if !defined(QT_STRICT_QLIST_ITERATORS) && (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) && !defined(Q_OS_WIN)
+#define QT_STRICT_QLIST_ITERATORS
+#endif
+
#ifdef Q_QDOC // define QVector for QDoc
template<typename T> class QVector : public QList<T> {};
#endif
@@ -134,6 +138,10 @@ public:
friend class QList<T>;
friend class const_iterator;
T *i = nullptr;
+#ifdef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit iterator(T *n) : i(n) {}
+#endif
+
public:
using difference_type = qsizetype;
using value_type = T;
@@ -149,7 +157,9 @@ public:
using reference = T &;
inline constexpr iterator() = default;
- inline iterator(T *n) : i(n) {}
+#ifndef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit iterator(T *n) : i(n) {}
+#endif
inline T &operator*() const { return *i; }
inline T *operator->() const { return i; }
inline T &operator[](qsizetype j) const { return *(i + j); }
@@ -172,7 +182,7 @@ public:
inline iterator &operator--() { --i; return *this; }
inline iterator operator--(int) { auto copy = *this; --*this; return copy; }
inline qsizetype operator-(iterator j) const { return i - j.i; }
-#if QT_DEPRECATED_SINCE(6, 3)
+#if QT_DEPRECATED_SINCE(6, 3) && !defined(QT_STRICT_QLIST_ITERATORS)
QT_DEPRECATED_VERSION_X_6_3("Use operator* or operator-> rather than relying on "
"the implicit conversion between a QList/QVector::iterator "
"and a raw pointer")
@@ -195,6 +205,10 @@ public:
friend class QList<T>;
friend class iterator;
const T *i = nullptr;
+#ifdef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit const_iterator(const T *n) : i(n) {}
+#endif
+
public:
using difference_type = qsizetype;
using value_type = T;
@@ -209,7 +223,9 @@ public:
using reference = const T &;
inline constexpr const_iterator() = default;
- inline const_iterator(const T *n) : i(n) {}
+#ifndef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit const_iterator(const T *n) : i(n) {}
+#endif
inline constexpr const_iterator(iterator o): i(o.i) {}
inline const T &operator*() const { return *i; }
inline const T *operator->() const { return i; }
@@ -233,7 +249,7 @@ public:
inline const_iterator &operator--() { --i; return *this; }
inline const_iterator operator--(int) { auto copy = *this; --*this; return copy; }
inline qsizetype operator-(const_iterator j) const { return i - j.i; }
-#if QT_DEPRECATED_SINCE(6, 3)
+#if QT_DEPRECATED_SINCE(6, 3) && !defined(QT_STRICT_QLIST_ITERATORS)
QT_DEPRECATED_VERSION_X_6_3("Use operator* or operator-> rather than relying on "
"the implicit conversion between a QList/QVector::const_iterator "
"and a raw pointer")