diff options
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--[-rwxr-xr-x] | src/corelib/tools/qalgorithms.h | 10 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 4 | ||||
-rw-r--r-- | src/corelib/tools/qchar.cpp | 10 | ||||
-rw-r--r-- | src/corelib/tools/qcommandlineoption.cpp | 4 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 29 | ||||
-rw-r--r-- | src/corelib/tools/qelapsedtimer_mac.cpp | 5 | ||||
-rw-r--r-- | src/corelib/tools/qhash.cpp | 50 | ||||
-rw-r--r-- | src/corelib/tools/qhash.h | 3 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 4 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_win.cpp | 6 | ||||
-rw-r--r-- | src/corelib/tools/qrect.cpp | 4 | ||||
-rw-r--r-- | src/corelib/tools/qregexp.cpp | 6 | ||||
-rw-r--r-- | src/corelib/tools/qregularexpression.cpp | 45 | ||||
-rw-r--r-- | src/corelib/tools/qsimd.cpp | 292 | ||||
-rw-r--r-- | src/corelib/tools/qsimd_p.h | 178 | ||||
-rw-r--r-- | src/corelib/tools/qstring.cpp | 15 | ||||
-rw-r--r-- | src/corelib/tools/qstringbuilder.h | 2 | ||||
-rw-r--r-- | src/corelib/tools/qtimezone.cpp | 1 |
18 files changed, 483 insertions, 185 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index 57fbdf0eba..ffa3082d5e 100755..100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -649,7 +649,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) Q_D return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clz(v) : 32U; @@ -664,7 +664,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clz(v)-24U : 8U; @@ -676,7 +676,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clz(v)-16U : 16U; @@ -689,7 +689,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clzll(v) : 64U; @@ -704,7 +704,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW { return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 241c255b5d..ac191ef265 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -489,8 +489,8 @@ quint16 qChecksum(const char *data, uint len) \overload - Compresses the first \a nbytes of \a data and returns the - compressed data in a new byte array. + Compresses the first \a nbytes of \a data at compression level + \a compressionLevel and returns the compressed data in a new byte array. */ #ifndef QT_NO_COMPRESS diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index e6c246e8e6..5469eee14d 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -598,12 +598,22 @@ QT_BEGIN_NAMESPACE \fn QChar::QChar(char ch) Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. + + \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII + is defined. + + \sa QT_NO_CAST_FROM_ASCII */ /*! \fn QChar::QChar(uchar ch) Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. + + \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII + is defined. + + \sa QT_NO_CAST_FROM_ASCII */ /*! diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index eb50cee5bb..8c0ba8cb2b 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -284,7 +284,7 @@ QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList) else nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()), nameList.end()); - return qMove(nameList); + return nameList; } /*! @@ -391,7 +391,7 @@ QStringList QCommandLineOption::defaultValues() const /*! Sets whether to hide this option in the user-visible help output. - All options are visible by default. Setting \a hidden to true for + All options are visible by default. Setting \a hide to true for a particular option makes it internal, i.e. not listed in the help output. \since 5.6 diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index e445055e1d..0d7225eea0 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1681,6 +1681,7 @@ bool QTime::setHMS(int h, int m, int s, int ms) QTime QTime::addSecs(int s) const { + s %= SECS_PER_DAY; return addMSecs(s * 1000); } @@ -4791,23 +4792,21 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime) // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec dateAndTime = dateTime.d->getDateTime(); out << dateAndTime; - if (out.version() >= QDataStream::Qt_4_0) { - switch (dateTime.timeSpec()) { - case Qt::UTC: - out << (qint8)QDateTimePrivate::UTC; - break; - case Qt::OffsetFromUTC: - out << (qint8)QDateTimePrivate::OffsetFromUTC; - break; - case Qt::TimeZone: + switch (dateTime.timeSpec()) { + case Qt::UTC: + out << (qint8)QDateTimePrivate::UTC; + break; + case Qt::OffsetFromUTC: + out << (qint8)QDateTimePrivate::OffsetFromUTC; + break; + case Qt::TimeZone: #ifndef QT_BOOTSTRAPPED - out << (qint8)QDateTimePrivate::TimeZone; - break; + out << (qint8)QDateTimePrivate::TimeZone; + break; #endif // QT_BOOTSTRAPPED - case Qt::LocalTime: - out << (qint8)QDateTimePrivate::LocalUnknown; - break; - } + case Qt::LocalTime: + out << (qint8)QDateTimePrivate::LocalUnknown; + break; } } else { // version < QDataStream::Qt_4_0 diff --git a/src/corelib/tools/qelapsedtimer_mac.cpp b/src/corelib/tools/qelapsedtimer_mac.cpp index a355bf03e8..e946ac096f 100644 --- a/src/corelib/tools/qelapsedtimer_mac.cpp +++ b/src/corelib/tools/qelapsedtimer_mac.cpp @@ -59,8 +59,13 @@ static qint64 absoluteToNSecs(qint64 cpuTime) { if (info.denom == 0) mach_timebase_info(&info); +#ifdef __LP64__ + __uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom; + return static_cast<qint64>(nsecs); +#else qint64 nsecs = cpuTime * info.numer / info.denom; return nsecs; +#endif } static qint64 absoluteToMSecs(qint64 cpuTime) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 1f3ea36121..b334a697a9 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -290,6 +290,53 @@ static void qt_initialize_qhash_seed() } } +/*! \relates QHash + \since 5.6 + + Returns the current global QHash seed. + + The seed is set in any newly created QHash. See \l{qHash} about how this seed + is being used by QHash. + + \sa qSetGlobalQHashSeed + */ +int qGlobalQHashSeed() +{ + return qt_qhash_seed.load(); +} + +/*! \relates QHash + \since 5.6 + + Sets the global QHash seed. + + Manually setting the global QHash seed value should be done only for testing + and debugging purposes, when deterministic and reproducible behavior on a QHash + is needed. We discourage to do it in production code as it can make your + application susceptible to \l{algorithmic complexity attacks}. + + The seed is set in any newly created QHash. See \l{qHash} about how this seed + is being used by QHash. + + If the environment variable \c QT_HASH_SEED is set, calling this function will + result in a no-op. + + Passing the value -1 will reinitialize the global QHash seed to a random value. + + \sa qGlobalQHashSeed + */ +void qSetGlobalQHashSeed(int newSeed) +{ + if (qEnvironmentVariableIsSet("QT_HASH_SEED")) + return; + if (newSeed == -1) { + int x(qt_create_qhash_seed() & INT_MAX); + qt_qhash_seed.store(x); + } else { + qt_qhash_seed.store(newSeed & INT_MAX); + } +} + /*! \internal @@ -1132,7 +1179,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW where you temporarily need deterministic behavior, for example for debugging or regression testing. To disable the randomization, define the environment variable \c QT_HASH_SEED. The contents of that variable, interpreted as a - decimal value, will be used as the seed for qHash(). + decimal value, will be used as the seed for qHash(). Alternatively, you can + call the qSetGlobalQHashSeed() function. \sa QHashIterator, QMutableHashIterator, QMap, QSet */ diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index e367cc0068..8d65a018ae 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -1037,6 +1037,9 @@ Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value) return n; } +Q_CORE_EXPORT int qGlobalQHashSeed(); +Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed); + Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash) Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 703341cc36..181daa04e4 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2742,9 +2742,9 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q const QChar exponential, const QChar group, const QChar decimal, double d, int precision, DoubleForm form, int width, unsigned flags) { - if (precision == -1) + if (precision < 0) precision = 6; - if (width == -1) + if (width < 0) width = 0; bool negative = false; diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp index 1cad9b32e3..4781bab172 100644 --- a/src/corelib/tools/qlocale_win.cpp +++ b/src/corelib/tools/qlocale_win.cpp @@ -51,9 +51,7 @@ #include <wrl.h> #include <windows.foundation.h> #include <windows.foundation.collections.h> -#ifndef Q_OS_WINPHONE #include <windows.globalization.h> -#endif #endif // Q_OS_WINRT QT_BEGIN_NAMESPACE @@ -639,7 +637,6 @@ QVariant QSystemLocalePrivate::uiLanguages() return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage()))); #else // !Q_OS_WINRT QStringList result; -#ifndef Q_OS_WINPHONE ComPtr<ABI::Windows::Globalization::IApplicationLanguagesStatics> appLanguagesStatics; if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), &appLanguagesStatics))) { qWarning("Could not obtain ApplicationLanguagesStatic"); @@ -661,9 +658,6 @@ QVariant QSystemLocalePrivate::uiLanguages() PCWSTR rawString = language.GetRawBuffer(&length); result << QString::fromWCharArray(rawString, length); } -#else // !Q_OS_WINPHONE - result << QString::fromWCharArray(lcName); -#endif // Q_OS_WINPHONE return result; #endif // Q_OS_WINRT diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index b2174745e4..847f650a70 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -2403,7 +2403,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::marginsAdded(const QMarginsF &margins) const - \relates QRectF \since 5.3 Returns a rectangle grown by the \a margins. @@ -2413,7 +2412,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::marginsRemoved(const QMarginsF &margins) const - \relates QRectF \since 5.3 Removes the \a margins from the rectangle, shrinking it. @@ -2423,7 +2421,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::operator+=(const QMarginsF &margins) - \relates QRectF \since 5.3 Adds the \a margins to the rectangle, growing it. @@ -2433,7 +2430,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::operator-=(const QMarginsF &margins) - \relates QRectF \since 5.3 Returns a rectangle shrunk by the \a margins. diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 8000dc8688..82de664a56 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -116,6 +116,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, A good text on regexps is \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4. + \note In Qt 5, the new QRegularExpression class provides a Perl + compatible implementation of regular expressions and is recommended + in place of QRegExp. + \tableofcontents \section1 Introduction @@ -488,7 +492,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, when it is followed by 'char'. \endtable - \keyword QRegExp wildcard matching + \target QRegExp wildcard matching \section1 Wildcard Matching Most command shells such as \e bash or \e cmd.exe support "file diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 88a048d826..d8b0bf6e9f 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>. -** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +** Copyright (C) 2015 Giuseppe D'Angelo <dangelog@gmail.com>. +** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -1326,48 +1326,45 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString int * const captureOffsets = priv->capturedOffsets.data(); const int captureOffsetsCount = priv->capturedOffsets.size(); - int realOffset = offset + subjectStart; - const int realSubjectLength = subjectLength + subjectStart; - - const unsigned short * const subjectUtf16 = subject.utf16(); + const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart; int result; if (!previousMatchWasEmpty) { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions, + subjectUtf16, subjectLength, + offset, pcreOptions, captureOffsets, captureOffsetsCount); } else { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, + subjectUtf16, subjectLength, + offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, captureOffsets, captureOffsetsCount); if (result == PCRE_ERROR_NOMATCH) { - ++realOffset; + ++offset; if (usingCrLfNewlines - && realOffset < realSubjectLength - && subjectUtf16[realOffset - 1] == QLatin1Char('\r') - && subjectUtf16[realOffset] == QLatin1Char('\n')) { - ++realOffset; - } else if (realOffset < realSubjectLength - && QChar::isLowSurrogate(subjectUtf16[realOffset])) { - ++realOffset; + && offset < subjectLength + && subjectUtf16[offset - 1] == QLatin1Char('\r') + && subjectUtf16[offset] == QLatin1Char('\n')) { + ++offset; + } else if (offset < subjectLength + && QChar::isLowSurrogate(subjectUtf16[offset])) { + ++offset; } result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions, + subjectUtf16, subjectLength, + offset, pcreOptions, captureOffsets, captureOffsetsCount); } } #ifdef QREGULAREXPRESSION_DEBUG qDebug() << "Matching" << pattern << "against" << subject - << "starting at" << subjectStart << "len" << subjectLength << "real len" << realSubjectLength - << "offset" << offset << "real offset" << realOffset + << "starting at" << subjectStart << "len" << subjectLength + << "offset" << offset << matchType << matchOptions << previousMatchWasEmpty << "result" << result; #endif @@ -2057,7 +2054,7 @@ QString QRegularExpressionMatch::captured(int nth) const if (start == -1) // didn't capture return QString(); - return d->subject.mid(start, capturedLength(nth)); + return d->subject.mid(start + d->subjectStart, capturedLength(nth)); } /*! @@ -2078,7 +2075,7 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const if (start == -1) // didn't capture return QStringRef(); - return d->subject.midRef(start, capturedLength(nth)); + return d->subject.midRef(start + d->subjectStart, capturedLength(nth)); } /*! diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index e7917ffdac..d0c65a04b1 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -78,28 +78,28 @@ static inline uint detectProcessorFeatures() return 0; } #elif defined (Q_OS_WINCE) -static inline uint detectProcessorFeatures() +static inline quint64 detectProcessorFeatures() { - uint features = 0; + quint64 features = 0; #if defined (ARM) # ifdef PF_ARM_NEON if (IsProcessorFeaturePresent(PF_ARM_NEON)) - features |= ARM_NEON; + features |= Q_UINT64_C(1) << CpuFeatureNEON; # endif #elif defined(_X86_) if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) - features |= SSE2; + features |= Q_UINT64_C(1) << CpuFeatureSSE2; if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) - features |= SSE3; + features |= Q_UINT64_C(1) << CpuFeatureSSE3; #endif return features; } #elif defined(Q_PROCESSOR_ARM) -static inline uint detectProcessorFeatures() +static inline quint64 detectProcessorFeatures() { - uint features = 0; + quint64 features = 0; #if defined(Q_OS_LINUX) int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY); @@ -117,7 +117,7 @@ static inline uint detectProcessorFeatures() for (int i = 0; i < max; i += 2) if (vector[i] == AT_HWCAP) { if (vector[i+1] & HWCAP_NEON) - features |= NEON; + features |= Q_UINT64_C(1) << CpuFeatureNEON; break; } } @@ -129,7 +129,7 @@ static inline uint detectProcessorFeatures() #endif #if defined(__ARM_NEON__) - features = NEON; + features = Q_UINT64_C(1) << CpuFeatureNEON; #endif return features; @@ -205,21 +205,24 @@ static void cpuidFeatures01(uint &ecx, uint &edx) inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));} #endif -static void cpuidFeatures07_00(uint &ebx) +static void cpuidFeatures07_00(uint &ebx, uint &ecx) { #if defined(Q_CC_GNU) qregisteruint rbx; // in case it's 64-bit + qregisteruint rcx = 0; asm ("xchg " PICreg", %0\n" "cpuid\n" "xchg " PICreg", %0\n" - : "=&r" (rbx) - : "a" (7), "c" (0) + : "=&r" (rbx), "+&c" (rcx) + : "a" (7) : "%edx"); ebx = rbx; + ecx = rcx; #elif defined(Q_OS_WIN) int info[4]; __cpuidex(info, 7, 0); ebx = info[1]; + ecx = info[2]; #endif } @@ -240,7 +243,7 @@ static void xgetbv(uint in, uint &eax, uint &edx) #endif } -static inline uint detectProcessorFeatures() +static quint64 detectProcessorFeatures() { // Flags from the CR0 / XCR0 state register enum XCR0Flags { @@ -257,8 +260,15 @@ static inline uint detectProcessorFeatures() AVXState = XMM0_15 | YMM0_15Hi128, AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 }; - - uint features = 0; + static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) | + (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) | + (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) | + (Q_UINT64_C(1) << CpuFeatureAVX512VL) | + (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI); + static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512; + static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2; + + quint64 features = 0; int cpuidLevel = maxBasicCpuidSupported(); #if Q_PROCESSOR_X86 < 5 if (cpuidLevel < 1) @@ -269,28 +279,23 @@ static inline uint detectProcessorFeatures() uint cpuid01ECX = 0, cpuid01EDX = 0; cpuidFeatures01(cpuid01ECX, cpuid01EDX); + + // the low 32-bits of features is cpuid01ECX + // note: we need to check OS support for saving the AVX register state + features = cpuid01ECX; + #if defined(Q_PROCESSOR_X86_32) // x86 might not have SSE2 support if (cpuid01EDX & (1u << 26)) - features |= SSE2; + features |= Q_UINT64_C(1) << CpuFeatureSSE2; + else + features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2); // we should verify that the OS enabled saving of the SSE state... #else // x86-64 or x32 - features = SSE2; + features |= Q_UINT64_C(1) << CpuFeatureSSE2; #endif - // common part between 32- and 64-bit - if (cpuid01ECX & (1u)) - features |= SSE3; - if (cpuid01ECX & (1u << 9)) - features |= SSSE3; - if (cpuid01ECX & (1u << 19)) - features |= SSE4_1; - if (cpuid01ECX & (1u << 20)) - features |= SSE4_2; - if (cpuid01ECX & (1u << 25)) - features |= 0; // AES, enable if needed - uint xgetbvA = 0, xgetbvD = 0; if (cpuid01ECX & (1u << 27)) { // XGETBV enabled @@ -298,22 +303,27 @@ static inline uint detectProcessorFeatures() } uint cpuid0700EBX = 0; - if (cpuidLevel >= 7) - cpuidFeatures07_00(cpuid0700EBX); + uint cpuid0700ECX = 0; + if (cpuidLevel >= 7) { + cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX); - if ((xgetbvA & AVXState) == AVXState) { - // support for YMM and XMM registers is enabled - if (cpuid01ECX & (1u << 28)) - features |= AVX; - - if (cpuid0700EBX & (1u << 5)) - features |= AVX2; + // the high 32-bits of features is cpuid0700EBX + features |= quint64(cpuid0700EBX) << 32; } - if (cpuid0700EBX & (1u << 4)) - features |= HLE; // Hardware Lock Ellision - if (cpuid0700EBX & (1u << 11)) - features |= RTM; // Restricted Transactional Memory + if ((xgetbvA & AVXState) != AVXState) { + // support for YMM registers is disabled, disable all AVX + features &= ~AllAVX; + } else if ((xgetbvA & AVX512State) != AVX512State) { + // support for ZMM registers or mask registers is disabled, disable all AVX512 + features &= ~AllAVX512; + } else { + // this feature is out of order + if (cpuid0700ECX & (1u << 1)) + features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI; + else + features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI); + } return features; } @@ -430,24 +440,24 @@ static bool procCpuinfoContains(const char *prefix, const char *string) } #endif -static inline uint detectProcessorFeatures() +static inline quint64 detectProcessorFeatures() { // NOTE: MIPS 74K cores are the only ones supporting DSPr2. - uint flags = 0; + quint64 flags = 0; #if defined __mips_dsp - flags |= DSP; + flags |= Q_UINT64_C(1) << CpuFeatureDSP; # if defined __mips_dsp_rev && __mips_dsp_rev >= 2 - flags |= DSPR2; + flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; # elif defined(Q_OS_LINUX) if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) - flags |= DSPR2; + flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; # endif #elif defined(Q_OS_LINUX) if (procCpuinfoContains("ASEs implemented", "dsp")) { - flags |= DSP; + flags |= Q_UINT64_C(1) << CpuFeatureDSP; if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) - flags |= DSPR2; + flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; } #endif @@ -462,70 +472,179 @@ static inline uint detectProcessorFeatures() #endif /* - * Use kdesdk/scripts/generate_string_table.pl to update the table below. - * Here's the data (don't forget the ONE leading space): + * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note + * that the x86 version has a lot of blanks that must be kept and that the + * offset table's type is changed to make the table smaller. We also remove the + * terminating -1 that the script adds. + */ +// begin generated +#if defined(Q_PROCESSOR_ARM) +/* Data: neon - sse2 + */ +static const char features_string[] = " neon\0"; +static const int features_indices[] = { 0 }; +#elif defined(Q_PROCESSOR_MIPS) +/* Data: + dsp + dspr2 +*/ +static const char features_string[] = + " dsp\0" + " dspr2\0" + "\0"; + +static const int features_indices[] = { + 0, 5 +}; +#elif defined(Q_PROCESSOR_X86) +/* Data: sse3 + sse2 + avx512vbmi + + + + + + ssse3 + + + fma + cmpxchg16b + + + + + sse4.1 sse4.2 + + movbe + popcnt + + aes + + avx - avx2 + f16c + rdrand + + + + + bmi hle + avx2 + + + bmi2 + + rtm - dsp - dspr2 - */ -// begin generated + + + + avx512f + avx512dq + rdseed + + + avx512ifma + + + + + avx512pf + avx512er + avx512cd + sha + avx512bw + avx512vl + */ static const char features_string[] = - "\0" - " neon\0" - " sse2\0" " sse3\0" + " sse2\0" + " avx512vbmi\0" " ssse3\0" + " fma\0" + " cmpxchg16b\0" " sse4.1\0" " sse4.2\0" + " movbe\0" + " popcnt\0" + " aes\0" " avx\0" - " avx2\0" + " f16c\0" + " rdrand\0" + " bmi\0" " hle\0" + " avx2\0" + " bmi2\0" " rtm\0" - " dsp\0" - " dspr2\0" + " avx512f\0" + " avx512dq\0" + " rdseed\0" + " avx512ifma\0" + " avx512pf\0" + " avx512er\0" + " avx512cd\0" + " sha\0" + " avx512bw\0" + " avx512vl\0" "\0"; -static const int features_indices[] = { - 0, 1, 7, 13, 19, 26, 34, 42, - 47, 53, 58, 63, 68, -1 +static const quint8 features_indices[] = { + 0, 6, 12, 5, 5, 5, 5, 5, + 5, 24, 5, 5, 31, 36, 5, 5, + 5, 5, 5, 48, 56, 5, 64, 71, + 5, 79, 5, 5, 84, 89, 95, 5, + 5, 5, 5, 103, 108, 113, 5, 5, + 119, 5, 5, 125, 5, 5, 5, 5, + 130, 139, 149, 5, 5, 157, 5, 5, + 5, 5, 169, 179, 189, 199, 204, 214 }; +#else +static const char features_string[] = ""; +static const int features_indices[] = { }; +#endif // end generated -static const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]); +static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]); // record what CPU features were enabled by default in this Qt build -static const uint minFeature = qCompilerCpuFeatures; +static const quint64 minFeature = qCompilerCpuFeatures; #ifdef Q_OS_WIN #if defined(Q_CC_GNU) -# define ffs __builtin_ffs +# define ffsll __builtin_ffsll #else -int ffs(int i) +int ffsll(quint64 i) { -#ifndef Q_OS_WINCE +#if defined(Q_OS_WIN64) unsigned long result; - return _BitScanForward(&result, i) ? result : 0; + return _BitScanForward64(&result, i) ? result : 0; +#elif !defined(Q_OS_WINCE) + unsigned long result; + return _BitScanForward(&result, i) ? result : + _BitScanForward(&result, i >> 32) ? result + 32 : 0; #else return 0; #endif } #endif -#elif defined(Q_OS_ANDROID) -# define ffs __builtin_ffs +#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) +# define ffsll __builtin_ffsll #endif -QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0); +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; +#else +Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) }; +#endif void qDetectCpuFeatures() { @@ -547,11 +666,11 @@ void qDetectCpuFeatures() // contains all the features that the code required. Qt 4 ran for years // like that, so it shouldn't be a problem. - qt_cpu_features.store(minFeature | QSimdInitialized); + qt_cpu_features.store(minFeature | quint32(QSimdInitialized)); return; # endif #endif - uint f = detectProcessorFeatures(); + quint64 f = detectProcessorFeatures(); QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); if (!disable.isEmpty()) { disable.prepend(' '); @@ -567,29 +686,32 @@ void qDetectCpuFeatures() bool runningOnValgrind = false; #endif if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) { - uint missing = minFeature & ~f; + quint64 missing = minFeature & ~f; fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n "); for (int i = 0; i < features_count; ++i) { - if (missing & (1 << i)) + if (missing & (Q_UINT64_C(1) << i)) fprintf(stderr, "%s", features_string + features_indices[i]); } fprintf(stderr, "\n"); fflush(stderr); - qFatal("Aborted. Incompatible processor: missing feature 0x%x -%s.", missing, - features_string + features_indices[ffs(missing) - 1]); + qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing, + features_string + features_indices[ffsll(missing) - 1]); } - qt_cpu_features.store(f | QSimdInitialized); + qt_cpu_features[0].store(f | quint32(QSimdInitialized)); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + qt_cpu_features[1].store(f >> 32); +#endif } void qDumpCPUFeatures() { - uint features = qCpuFeatures(); + quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized); printf("Processor features: "); for (int i = 0; i < features_count; ++i) { - if (features & (1 << i)) + if (features & (Q_UINT64_C(1) << i)) printf("%s%s", features_string + features_indices[i], - minFeature & (1 << i) ? "[required]" : ""); + minFeature & (Q_UINT64_C(1) << i) ? "[required]" : ""); } puts(""); } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index dd93b4fd26..be003f6c6d 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -54,9 +54,9 @@ * for the x86 and ARM intrinsics: * - GCC: the -mXXX or march=YYY flag is necessary before #include * up to 4.8; GCC >= 4.9 can include unconditionally + * - Clang: same as GCC, with unconditional inclusion with version 3.7 * - Intel CC: #include can happen unconditionally * - MSVC: #include can happen unconditionally - * - RVCT: ??? * * We will try to include all headers possible under this configuration. * @@ -138,7 +138,8 @@ #define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0) #if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \ - || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \ + || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409) \ + || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 307)) \ && !defined(QT_BOOTSTRAPPED) # define QT_COMPILER_SUPPORTS_SIMD_ALWAYS # define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x) @@ -217,6 +218,23 @@ # endif #endif +#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f" +#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd" +#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er" +#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf" +#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw" +#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq" +#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl" +#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma" +#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi" + +#define QT_FUNCTION_TARGET_STRING_F16C "f16c" +#define QT_FUNCTION_TARGET_STRING_RDRAND "rdrnd" +#define QT_FUNCTION_TARGET_STRING_BMI "bmi" +#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2" +#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed" +#define QT_FUNCTION_TARGET_STRING_SHA "sha" + // other x86 intrinsics #if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \ || (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \ @@ -244,74 +262,170 @@ QT_BEGIN_NAMESPACE enum CPUFeatures { - NEON = 0x2, ARM_NEON = NEON, - SSE2 = 0x4, - SSE3 = 0x8, - SSSE3 = 0x10, - SSE4_1 = 0x20, - SSE4_2 = 0x40, - AVX = 0x80, - AVX2 = 0x100, - HLE = 0x200, - RTM = 0x400, - DSP = 0x800, - DSPR2 = 0x1000, +#if defined(Q_PROCESSOR_ARM) + CpuFeatureNEON = 0, + CpuFeatureARM_NEON = CpuFeatureNEON, +#elif defined(Q_PROCESSOR_MIPS) + CpuFeatureDSP = 0, + CpuFeatureDSPR2 = 1, +#elif defined(Q_PROCESSOR_X86) + // The order of the flags is jumbled so it matches most closely the bits in CPUID + // Out of order: + CpuFeatureSSE2 = 1, // uses the bit for PCLMULQDQ + // in level 1, ECX + CpuFeatureSSE3 = (0 + 0), + CpuFeatureSSSE3 = (0 + 9), + CpuFeatureSSE4_1 = (0 + 19), + CpuFeatureSSE4_2 = (0 + 20), + CpuFeatureMOVBE = (0 + 22), + CpuFeaturePOPCNT = (0 + 23), + CpuFeatureAES = (0 + 25), + CpuFeatureAVX = (0 + 28), + CpuFeatureF16C = (0 + 29), + CpuFeatureRDRAND = (0 + 30), + // 31 is always zero and we've used it for the QSimdInitialized + + // in level 7, leaf 0, EBX + CpuFeatureBMI = (32 + 3), + CpuFeatureHLE = (32 + 4), + CpuFeatureAVX2 = (32 + 5), + CpuFeatureBMI2 = (32 + 8), + CpuFeatureRTM = (32 + 11), + CpuFeatureAVX512F = (32 + 16), + CpuFeatureAVX512DQ = (32 + 17), + CpuFeatureRDSEED = (32 + 18), + CpuFeatureAVX512IFMA = (32 + 21), + CpuFeatureAVX512PF = (32 + 26), + CpuFeatureAVX512ER = (32 + 27), + CpuFeatureAVX512CD = (32 + 28), + CpuFeatureSHA = (32 + 29), + CpuFeatureAVX512BW = (32 + 30), + CpuFeatureAVX512VL = (32 + 31), + + // in level 7, leaf 0, ECX (out of order, for now) + CpuFeatureAVX512VBMI = 2, // uses the bit for DTES64 +#endif // used only to indicate that the CPU detection was initialised QSimdInitialized = 0x80000000 }; -static const uint qCompilerCpuFeatures = 0 +static const quint64 qCompilerCpuFeatures = 0 +#if defined __SHA__ + | (Q_UINT64_C(1) << CpuFeatureSHA) +#endif +#if defined __AES__ + | (Q_UINT64_C(1) << CpuFeatureAES) +#endif #if defined __RTM__ - | RTM + | (Q_UINT64_C(1) << CpuFeatureRTM) +#endif +#ifdef __RDRND__ + | (Q_UINT64_C(1) << CpuFeatureRDRAND) +#endif +#ifdef __RDSEED__ + | (Q_UINT64_C(1) << CpuFeatureRDSEED) +#endif +#if defined __BMI__ + | (Q_UINT64_C(1) << CpuFeatureBMI) +#endif +#if defined __BMI2__ + | (Q_UINT64_C(1) << CpuFeatureBMI2) +#endif +#if defined __F16C__ + | (Q_UINT64_C(1) << CpuFeatureF16C) +#endif +#if defined __POPCNT__ + | (Q_UINT64_C(1) << CpuFeaturePOPCNT) +#endif +#if defined __MOVBE__ // GCC and Clang don't seem to define this + | (Q_UINT64_C(1) << CpuFeatureMOVBE) +#endif +#if defined __AVX512F__ + | (Q_UINT64_C(1) << CpuFeatureAVX512F) +#endif +#if defined __AVX512CD__ + | (Q_UINT64_C(1) << CpuFeatureAVX512CD) +#endif +#if defined __AVX512ER__ + | (Q_UINT64_C(1) << CpuFeatureAVX512ER) +#endif +#if defined __AVX512PF__ + | (Q_UINT64_C(1) << CpuFeatureAVX512PF) +#endif +#if defined __AVX512BW__ + | (Q_UINT64_C(1) << CpuFeatureAVX512BW) +#endif +#if defined __AVX512DQ__ + | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) +#endif +#if defined __AVX512VL__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VL) +#endif +#if defined __AVX512IFMA__ + | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) +#endif +#if defined __AVX512VBMI__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI) #endif #if defined __AVX2__ - | AVX2 + | (Q_UINT64_C(1) << CpuFeatureAVX2) #endif #if defined __AVX__ - | AVX + | (Q_UINT64_C(1) << CpuFeatureAVX) #endif #if defined __SSE4_2__ - | SSE4_2 + | (Q_UINT64_C(1) << CpuFeatureSSE4_2) #endif #if defined __SSE4_1__ - | SSE4_1 + | (Q_UINT64_C(1) << CpuFeatureSSE4_1) #endif #if defined __SSSE3__ - | SSSE3 + | (Q_UINT64_C(1) << CpuFeatureSSSE3) #endif #if defined __SSE3__ - | SSE3 + | (Q_UINT64_C(1) << CpuFeatureSSE3) #endif #if defined __SSE2__ - | SSE2 + | (Q_UINT64_C(1) << CpuFeatureSSE2) #endif #if defined __ARM_NEON__ - | NEON + | (Q_UINT64_C(1) << CpuFeatureNEON) #endif #if defined __mips_dsp - | DSP + | (Q_UINT64_C(1) << CpuFeatureDSP) #endif #if defined __mips_dspr2 - | DSPR2 + | (Q_UINT64_C(1) << CpuFeatureDSPR2) #endif ; -extern Q_CORE_EXPORT QBasicAtomicInt qt_cpu_features; +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1]; +#else +extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2]; +#endif Q_CORE_EXPORT void qDetectCpuFeatures(); -static inline uint qCpuFeatures() +static inline quint64 qCpuFeatures() { - int features = qt_cpu_features.load(); + quint64 features = qt_cpu_features[0].load(); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + features |= quint64(qt_cpu_features[1].load()) << 32; +#endif if (Q_UNLIKELY(features == 0)) { qDetectCpuFeatures(); - features = qt_cpu_features.load(); + features = qt_cpu_features[0].load(); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + features |= quint64(qt_cpu_features[1].load()) << 32; +#endif Q_ASSUME(features != 0); } - return uint(features); + return features; } -#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature))) +#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (Q_UINT64_C(1) << CpuFeature ## feature)) \ + || (qCpuFeatures() & (Q_UINT64_C(1) << CpuFeature ## feature))) #ifdef Q_PROCESSOR_X86 // Bit scan functions for x86 diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 8bb8953dde..e3a3cc79c6 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2680,6 +2680,8 @@ bool operator==(const QString &s1, const QString &s2) /*! \overload operator==() + Returns \c true if this string is equal to \a other; otherwise + returns \c false. */ bool QString::operator==(QLatin1String other) const { @@ -2738,7 +2740,7 @@ bool operator<(const QString &s1, const QString &s2) } /*! \overload operator<() - \relates QString + Returns \c true if this string is lexically less than the parameter string called \a other; otherwise returns \c false. */ @@ -2843,7 +2845,7 @@ bool QString::operator<(QLatin1String other) const /*! \overload operator>() - \relates QString + Returns \c true if this string is lexically greater than the parameter string \a other; otherwise returns \c false. */ @@ -3614,9 +3616,14 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const } /*! - \overload count() + \overload count() - Returns the number of occurrences of character \a ch in the string. + Returns the number of occurrences of character \a ch in the string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa contains(), indexOf() */ int QString::count(QChar ch, Qt::CaseSensitivity cs) const diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 1dbc005bca..3d41aeee18 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -421,7 +421,7 @@ QString &operator+=(QString &a, const QStringBuilder<A, B> &b) a.reserve(len); QChar *it = a.data() + a.size(); QConcatenable< QStringBuilder<A, B> >::appendTo(b, it); - a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8 + a.resize(int(it - a.constData())); //may be smaller than len if there was conversion from utf8 return a; } diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 45ae23cdf5..900c8ff14e 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -310,7 +310,6 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); /*! \typedef QTimeZone::OffsetDataList - \relates QTimeZone Synonym for QVector<OffsetData>. */ |