diff options
Diffstat (limited to 'src/corelib/tools')
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 2 | ||||
-rw-r--r-- | src/corelib/tools/qcontainertools_impl.h | 4 | ||||
-rw-r--r-- | src/corelib/tools/qeasingcurve.cpp | 12 | ||||
-rw-r--r-- | src/corelib/tools/qlist.cpp | 7 | ||||
-rw-r--r-- | src/corelib/tools/qlist.h | 20 | ||||
-rw-r--r-- | src/corelib/tools/qpair.qdoc | 1 | ||||
-rw-r--r-- | src/corelib/tools/qset.h | 70 | ||||
-rw-r--r-- | src/corelib/tools/qset.qdoc | 8 | ||||
-rw-r--r-- | src/corelib/tools/qsimd.cpp | 127 | ||||
-rw-r--r-- | src/corelib/tools/qsimd_p.h | 18 | ||||
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 2 |
11 files changed, 229 insertions, 42 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 234a44f6b6..36a221f728 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -143,7 +143,7 @@ qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t heade } result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize); - result.size = bytes; + result.size = result.elementCount * elementSize + headerSize; return result; } diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h index 86a16eb32b..3a0c4381f1 100644 --- a/src/corelib/tools/qcontainertools_impl.h +++ b/src/corelib/tools/qcontainertools_impl.h @@ -49,8 +49,6 @@ #include <QtCore/qglobal.h> #include <iterator> -#ifndef Q_QDOC - QT_BEGIN_NAMESPACE namespace QtPrivate @@ -131,6 +129,4 @@ using IfAssociativeIteratorHasFirstAndSecond = QT_END_NAMESPACE -#endif // Q_QDOC - #endif // QCONTAINERTOOLS_IMPL_H diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 8e00c46b41..d7f69d3e0a 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -583,6 +583,13 @@ struct BezierEase : public QEasingCurveFunction qWarning("QEasingCurve: Invalid bezier curve"); return x; } + + // The bezier computation is not always precise on the endpoints, so handle explicitly + if (!(x > 0)) + return 0; + if (!(x < 1)) + return 1; + SingleCubicBezier *singleCubicBezier = 0; getBezierSegment(singleCubicBezier, x); @@ -998,6 +1005,11 @@ struct BackEase : public QEasingCurveFunction qreal value(qreal t) override { + // The *Back() functions are not always precise on the endpoints, so handle explicitly + if (!(t > 0)) + return 0; + if (!(t < 1)) + return 1; qreal o = (_o < 0) ? qreal(1.70158) : _o; switch(_t) { case QEasingCurve::InBack: diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index dfebd57e34..3dc962236c 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -847,9 +847,10 @@ void **QListData::erase(void **xi) /*! \fn template <class T> void QList<T>::insert(int i, const T &value) - Inserts \a value at index position \a i in the list. If \a i <= 0, - the value is prepended to the list. If \a i >= size(), the - value is appended to the list. + Inserts \a value at index position \a i in the list. + + If \a i == 0, the value is prepended to the list. If \a i == size(), + the value is appended to the list. Example: \snippet code/src_corelib_tools_qlistdata.cpp 8 diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index be987c359b..ffd470efcd 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -580,8 +580,16 @@ inline T &QList<T>::operator[](int i) detach(); return reinterpret_cast<Node *>(p.at(i))->t(); } template <typename T> inline void QList<T>::removeAt(int i) -{ if(i >= 0 && i < p.size()) { detach(); - node_destruct(reinterpret_cast<Node *>(p.at(i))); p.remove(i); } } +{ +#if !QT_DEPRECATED_SINCE(5, 15) + Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::removeAt", "index out of range"); +#elif !defined(QT_NO_DEBUG) + if (i < 0 || i >= p.size()) + qWarning("QList::removeAt(): Index out of range."); +#endif + detach(); + node_destruct(reinterpret_cast<Node *>(p.at(i))); p.remove(i); +} template <typename T> inline T QList<T>::takeAt(int i) { Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::take", "index out of range"); @@ -676,6 +684,12 @@ inline void QList<T>::prepend(const T &t) template <typename T> inline void QList<T>::insert(int i, const T &t) { +#if !QT_DEPRECATED_SINCE(5, 15) + Q_ASSERT_X(i >= 0 && i <= p.size(), "QList<T>::insert", "index out of range"); +#elif !defined(QT_NO_DEBUG) + if (i < 0 || i > p.size()) + qWarning("QList::insert(): Index out of range."); +#endif if (d->ref.isShared()) { Node *n = detach_helper_grow(i, 1); QT_TRY { @@ -1051,7 +1065,7 @@ int lastIndexOf(const QList<T> &list, const U &u, int from) Node *n = reinterpret_cast<Node *>(list.p.at(from + 1)); while (n-- != b) { if (n->t() == u) - return typename QList<T>::difference_type(n - b); + return int(n - b); } } return -1; diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc index 59e6931995..65576ef2e6 100644 --- a/src/corelib/tools/qpair.qdoc +++ b/src/corelib/tools/qpair.qdoc @@ -28,6 +28,7 @@ /*! \class QPair \inmodule QtCore + \reentrant \brief The QPair class is a template class that stores a pair of items. \ingroup tools diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 6683188ad4..923411c34c 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -108,7 +108,11 @@ public: friend class QSet<T>; public: +#if QT_DEPRECATED_SINCE(5, 15) typedef std::bidirectional_iterator_tag iterator_category; +#else + typedef std::forward_iterator_tag iterator_category; +#endif typedef qptrdiff difference_type; typedef T value_type; typedef const T *pointer; @@ -128,13 +132,15 @@ public: { return i != o.i; } inline iterator &operator++() { ++i; return *this; } inline iterator operator++(int) { iterator r = *this; ++i; return r; } - inline iterator &operator--() { --i; return *this; } - inline iterator operator--(int) { iterator r = *this; --i; return r; } - inline iterator operator+(int j) const { return i + j; } - inline iterator operator-(int j) const { return i - j; } - friend inline iterator operator+(int j, iterator k) { return k + j; } - inline iterator &operator+=(int j) { i += j; return *this; } - inline iterator &operator-=(int j) { i -= j; return *this; } +#if QT_DEPRECATED_SINCE(5, 15) + inline QT_DEPRECATED iterator &operator--() { --i; return *this; } + inline QT_DEPRECATED iterator operator--(int) { iterator r = *this; --i; return r; } + inline QT_DEPRECATED iterator operator+(int j) const { return i + j; } + inline QT_DEPRECATED iterator operator-(int j) const { return i - j; } + friend inline QT_DEPRECATED iterator operator+(int j, iterator k) { return k + j; } + inline QT_DEPRECATED iterator &operator+=(int j) { i += j; return *this; } + inline QT_DEPRECATED iterator &operator-=(int j) { i -= j; return *this; } +#endif }; class const_iterator @@ -145,7 +151,11 @@ public: friend class QSet<T>; public: +#if QT_DEPRECATED_SINCE(5, 15) typedef std::bidirectional_iterator_tag iterator_category; +#else + typedef std::forward_iterator_tag iterator_category; +#endif typedef qptrdiff difference_type; typedef T value_type; typedef const T *pointer; @@ -163,19 +173,18 @@ public: inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline const_iterator &operator++() { ++i; return *this; } inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; } - inline const_iterator &operator--() { --i; return *this; } - inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; } - inline const_iterator operator+(int j) const { return i + j; } - inline const_iterator operator-(int j) const { return i - j; } - friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } - inline const_iterator &operator+=(int j) { i += j; return *this; } - inline const_iterator &operator-=(int j) { i -= j; return *this; } +#if QT_DEPRECATED_SINCE(5, 15) + inline QT_DEPRECATED const_iterator &operator--() { --i; return *this; } + inline QT_DEPRECATED const_iterator operator--(int) { const_iterator r = *this; --i; return r; } + inline QT_DEPRECATED const_iterator operator+(int j) const { return i + j; } + inline QT_DEPRECATED const_iterator operator-(int j) const { return i - j; } + friend inline QT_DEPRECATED const_iterator operator+(int j, const_iterator k) { return k + j; } + inline QT_DEPRECATED const_iterator &operator+=(int j) { i += j; return *this; } + inline QT_DEPRECATED const_iterator &operator-=(int j) { i -= j; return *this; } +#endif }; // STL style - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - inline iterator begin() { return q_hash.begin(); } inline const_iterator begin() const noexcept { return q_hash.begin(); } inline const_iterator cbegin() const noexcept { return q_hash.begin(); } @@ -185,12 +194,17 @@ public: inline const_iterator cend() const noexcept { return q_hash.end(); } inline const_iterator constEnd() const noexcept { return q_hash.constEnd(); } - reverse_iterator rbegin() { return reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } +#if QT_DEPRECATED_SINCE(5, 15) + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + reverse_iterator QT_DEPRECATED rbegin() { return reverse_iterator(end()); } + reverse_iterator QT_DEPRECATED rend() { return reverse_iterator(begin()); } + const_reverse_iterator QT_DEPRECATED rbegin() const noexcept { return const_reverse_iterator(end()); } + const_reverse_iterator QT_DEPRECATED rend() const noexcept { return const_reverse_iterator(begin()); } + const_reverse_iterator QT_DEPRECATED crbegin() const noexcept { return const_reverse_iterator(end()); } + const_reverse_iterator QT_DEPRECATED crend() const noexcept { return const_reverse_iterator(begin()); } +#endif iterator erase(iterator i) { return erase(m2c(i)); } @@ -399,17 +413,19 @@ public: inline bool hasNext() const { return c->constEnd() != i; } inline const T &next() { n = i++; return *n; } inline const T &peekNext() const { return *i; } - inline bool hasPrevious() const { return c->constBegin() != i; } - inline const T &previous() { n = --i; return *n; } - inline const T &peekPrevious() const { iterator p = i; return *--p; } inline void remove() { if (c->constEnd() != n) { i = c->erase(n); n = c->end(); } } inline const T &value() const { Q_ASSERT(item_exists()); return *n; } inline bool findNext(const T &t) { while (c->constEnd() != (n = i)) if (*i++ == t) return true; return false; } - inline bool findPrevious(const T &t) +#if QT_DEPRECATED_SINCE(5, 15) + inline QT_DEPRECATED bool hasPrevious() const { return c->constBegin() != i; } + inline QT_DEPRECATED const T &previous() { n = --i; return *n; } + inline QT_DEPRECATED const T &peekPrevious() const { iterator p = i; return *--p; } + inline QT_DEPRECATED bool findPrevious(const T &t) { while (c->constBegin() != i) if (*(n = --i) == t) return true; n = c->end(); return false; } +#endif }; #endif // QT_NO_JAVA_STYLE_ITERATORS diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index 084523ed4b..7c752d0318 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -906,8 +906,6 @@ Calling this function on QSet<T>::constEnd() leads to undefined results. - - \sa operator--() */ /*! @@ -924,6 +922,7 @@ /*! \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator--() \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator--() + \obsolete The prefix -- operator (\c{--it}) makes the preceding item current and returns an iterator to the new current item. @@ -937,6 +936,7 @@ /*! \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator--(int) \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator--(int) + \obsolete \overload @@ -947,6 +947,7 @@ /*! \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator+(int j) const \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator+(int j) const + \obsolete Returns an iterator to the item at \a j positions forward from this iterator. (If \a j is negative, the iterator goes backward.) @@ -959,6 +960,7 @@ /*! \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator-(int j) const \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator-(int j) const + \obsolete Returns an iterator to the item at \a j positions backward from this iterator. (If \a j is negative, the iterator goes forward.) @@ -971,6 +973,7 @@ /*! \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator+=(int j) \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator+=(int j) + \obsolete Advances the iterator by \a j items. (If \a j is negative, the iterator goes backward.) @@ -983,6 +986,7 @@ /*! \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator-=(int j) \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator-=(int j) + \obsolete Makes the iterator go back by \a j items. (If \a j is negative, the iterator goes forward.) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index ecf1822e42..d7c1d8c4a9 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -188,6 +188,8 @@ static inline quint64 detectProcessorFeatures() # define PICreg "%%rbx" #endif +static bool checkRdrndWorks() noexcept; + static int maxBasicCpuidSupported() { #if defined(Q_CC_EMSCRIPTEN) @@ -376,6 +378,9 @@ static quint64 detectProcessorFeatures() features &= ~AllAVX512; } + if (features & CpuFeatureRDRND && !checkRdrndWorks()) + features &= ~(CpuFeatureRDRND | CpuFeatureRDSEED); + return features; } @@ -590,4 +595,124 @@ void qDumpCPUFeatures() puts(""); } +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) + +# ifdef Q_PROCESSOR_X86_64 +# define _rdrandXX_step _rdrand64_step +# define _rdseedXX_step _rdseed64_step +# else +# define _rdrandXX_step _rdrand32_step +# define _rdseedXX_step _rdseed32_step +# endif + +# if QT_COMPILER_SUPPORTS_HERE(RDSEED) +static QT_FUNCTION_TARGET(RDSEED) unsigned *qt_random_rdseed(unsigned *ptr, unsigned *end) noexcept +{ + // Unlike for the RDRAND code below, the Intel whitepaper describing the + // use of the RDSEED instruction indicates we should not retry in a loop. + // If the independent bit generator used by RDSEED is out of entropy, it + // may take time to replenish. + // https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide + while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { + if (_rdseedXX_step(reinterpret_cast<qregisteruint *>(ptr)) == 0) + goto out; + ptr += sizeof(qregisteruint)/sizeof(*ptr); + } + + if (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { + if (_rdseed32_step(ptr) == 0) + goto out; + ++ptr; + } + +out: + return ptr; +} +# else +static unsigned *qt_random_rdseed(unsigned *ptr, unsigned *) +{ + return ptr; +} +# endif + +static QT_FUNCTION_TARGET(RDRND) unsigned *qt_random_rdrnd(unsigned *ptr, unsigned *end) noexcept +{ + int retries = 10; + while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { + if (_rdrandXX_step(reinterpret_cast<qregisteruint *>(ptr))) + ptr += sizeof(qregisteruint)/sizeof(*ptr); + else if (--retries == 0) + goto out; + } + + while (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { + bool ok = _rdrand32_step(ptr); + if (!ok && --retries) + continue; + if (ok) + ++ptr; + break; + } + +out: + return ptr; +} + +static QT_FUNCTION_TARGET(RDRND) Q_DECL_COLD_FUNCTION bool checkRdrndWorks() noexcept +{ + /* + * Some AMD CPUs (e.g. AMD A4-6250J and AMD Ryzen 3000-series) have a + * failing random generation instruction, which always returns + * 0xffffffff, even when generation was "successful". + * + * This code checks if hardware random generator generates four consecutive + * equal numbers. If it does, then we probably have a failing one and + * should disable it completely. + * + * https://bugreports.qt.io/browse/QTBUG-69423 + */ + constexpr qsizetype TestBufferSize = 4; + unsigned testBuffer[TestBufferSize] = {}; + + unsigned *end = qt_random_rdrnd(testBuffer, testBuffer + TestBufferSize); + if (end < testBuffer + 3) { + // Random generation didn't produce enough data for us to make a + // determination whether it's working or not. Assume it isn't, but + // don't print a warning. + return false; + } + + // Check the results for equality + if (testBuffer[0] == testBuffer[1] + && testBuffer[0] == testBuffer[2] + && end == testBuffer + TestBufferSize && testBuffer[0] == testBuffer[3]) { + fprintf(stderr, "WARNING: CPU random generator seem to be failing, " + "disabling hardware random number generation\n" + "WARNING: RDRND generated:"); + for (unsigned *ptr = testBuffer; ptr < end; ++ptr) + fprintf(stderr, " 0x%x", *ptr); + fprintf(stderr, "\n"); + return false; + } + + // We're good + return true; +} + +QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) noexcept +{ + unsigned *ptr = reinterpret_cast<unsigned *>(buffer); + unsigned *end = ptr + count; + + if (qCpuHasFeature(RDSEED)) + ptr = qt_random_rdseed(ptr, end); + + // fill the buffer with RDRND if RDSEED didn't + ptr = qt_random_rdrnd(ptr, end); + return ptr - reinterpret_cast<unsigned *>(buffer); +} +#elif defined(Q_PROCESSOR_X86) && !defined(Q_OS_NACL) && !defined(Q_PROCESSOR_ARM) +static bool checkRdrndWorks() noexcept { return false; } +#endif // Q_PROCESSOR_X86 && RDRND + QT_END_NAMESPACE diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index db2f546651..c28624a25e 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -346,6 +346,15 @@ extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2]; #endif Q_CORE_EXPORT quint64 qDetectCpuFeatures(); +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) +Q_CORE_EXPORT qsizetype qRandomCpu(void *, qsizetype) noexcept; +#else +static inline qsizetype qRandomCpu(void *, qsizetype) noexcept +{ + return 0; +} +#endif + static inline quint64 qCpuFeatures() { quint64 features = qt_cpu_features[0].loadRelaxed(); @@ -362,6 +371,15 @@ static inline quint64 qCpuFeatures() #define qCpuHasFeature(feature) (((qCompilerCpuFeatures & CpuFeature ## feature) == CpuFeature ## feature) \ || ((qCpuFeatures() & CpuFeature ## feature) == CpuFeature ## feature)) +inline bool qHasHwrng() +{ +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) + return qCpuHasFeature(RDRND); +#else + return false; +#endif +} + #define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \ for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i) diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 253d05ba2b..6be695e317 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -104,7 +104,7 @@ public: QVarLengthArray<T, Prealloc> &operator=(std::initializer_list<T> list) { - resize(list.size()); + resize(int(list.size())); // ### q6sizetype std::copy(list.begin(), list.end(), QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size())); return *this; |