diff options
author | Liang Qi <liang.qi@qt.io> | 2018-05-24 16:27:08 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-05-24 16:29:14 +0200 |
commit | f82e5085169876e0ec7c1b744d021b068c281cfe (patch) | |
tree | a870e1f68ce62818a0793c4c78a67971e841e676 /src/corelib | |
parent | f74d4fb1dacc682e2e6f4a44e4240f642a2c3b70 (diff) | |
parent | ee47999333dde1d38b73d04e142e05f06f8c56ed (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Conflicts:
mkspecs/features/qt_common.prf
src/corelib/tools/qstring.cpp
src/plugins/platforms/windows/qwindowsmousehandler.cpp
src/widgets/widgets/qmainwindowlayout_p.h
Change-Id: I5df613008f6336f69b257d08e49a133d033a9d65
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/configure.json | 3 | ||||
-rw-r--r-- | src/corelib/global/qnamespace.qdoc | 9 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 1 | ||||
-rw-r--r-- | src/corelib/serialization/qjson.cpp | 43 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_unix.cpp | 34 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 11 | ||||
-rw-r--r-- | src/corelib/tools/qstring.cpp | 89 |
8 files changed, 140 insertions, 52 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json index b03cf2f9d5..18fc22f18f 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -562,7 +562,8 @@ }, "linkat": { "label": "linkat()", - "autoDetect": "config.linux", + "comment": "Currently only used by QTemporaryFile; linkat() exists on Android, but hardlink creation fails due to security rules", + "autoDetect": "config.linux && !config.android", "condition": "tests.linkat", "output": [ "privateFeature" ] }, diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 66a7a1e6b5..2fcc744092 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1334,7 +1334,14 @@ \omitvalue WA_WState_WindowOpacitySet \omitvalue WA_WState_AcceptedTouchBeginEvent \omitvalue WA_MacNoShadow - \omitvalue WA_ContentsMarginsRespectsSafeArea + \value WA_ContentsMarginsRespectsSafeArea A QWidget respects the safe + area margins of a window by incorporating the margins into its contents' + margins by default. This means, that a QLayout will use the content area + of a widget for its layout, unless the Qt::WA_LayoutOnEntireRect attribute + is set. This along with a contents margin of 0 can be used on the actual + layout, to allow for example a background image to underlay the status bar and other + system areas on an iOS device, while still allowing child widgets of + that background to be inset based on the safe area. */ /*! \typedef Qt::HANDLE diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 5cc3a5937e..0ffc4ca634 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -114,6 +114,8 @@ static int renameat2(int oldfd, const char *oldpath, int newfd, const char *newp # if !QT_CONFIG(statx) && defined(SYS_statx) static int statx(int dirfd, const char *pathname, int flag, unsigned mask, struct statx *statxbuf) { return syscall(SYS_statx, dirfd, pathname, flag, mask, statxbuf); } +# elif !QT_CONFIG(statx) && !defined(SYS_statx) +# undef STATX_BASIC_STATS # endif # endif // !Q_OS_ANDROID #endif diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 25d17ecd6b..6181bd579e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4429,6 +4429,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) /*! \macro Q_NAMESPACE + \relates QObject \since 5.8 The Q_NAMESPACE macro can be used to add QMetaObject capabilities diff --git a/src/corelib/serialization/qjson.cpp b/src/corelib/serialization/qjson.cpp index 592f6168dc..7912b5040c 100644 --- a/src/corelib/serialization/qjson.cpp +++ b/src/corelib/serialization/qjson.cpp @@ -326,38 +326,35 @@ int Value::usedStorage(const Base *b) const return alignedSize(s); } +inline bool isValidValueOffset(uint offset, uint tableOffset) +{ + return offset >= sizeof(Base) + && offset + sizeof(uint) <= tableOffset; +} + bool Value::isValid(const Base *b) const { - int offset = -1; switch (type) { + case QJsonValue::Null: + case QJsonValue::Bool: + return true; case QJsonValue::Double: - if (latinOrIntValue) - break; - Q_FALLTHROUGH(); + return latinOrIntValue || isValidValueOffset(value, b->tableOffset); case QJsonValue::String: + if (!isValidValueOffset(value, b->tableOffset)) + return false; + if (latinOrIntValue) + return asLatin1String(b).isValid(b->tableOffset - value); + return asString(b).isValid(b->tableOffset - value); case QJsonValue::Array: + return isValidValueOffset(value, b->tableOffset) + && static_cast<Array *>(base(b))->isValid(b->tableOffset - value); case QJsonValue::Object: - offset = value; - break; - case QJsonValue::Null: - case QJsonValue::Bool: + return isValidValueOffset(value, b->tableOffset) + && static_cast<Object *>(base(b))->isValid(b->tableOffset - value); default: - break; - } - - if (offset == -1) - return true; - if (offset + sizeof(uint) > b->tableOffset || offset < (int)sizeof(Base)) - return false; - - int s = usedStorage(b); - if (s < 0 || s > (int)b->tableOffset - offset) return false; - if (type == QJsonValue::Array) - return static_cast<Array *>(base(b))->isValid(s); - if (type == QJsonValue::Object) - return static_cast<Object *>(base(b))->isValid(s); - return true; + } } /*! diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp index 095001e0a3..1a9184bca9 100644 --- a/src/corelib/tools/qlocale_unix.cpp +++ b/src/corelib/tools/qlocale_unix.cpp @@ -107,8 +107,36 @@ Q_GLOBAL_STATIC(QSystemLocaleData, qSystemLocaleData) #ifndef QT_NO_SYSTEMLOCALE +static bool contradicts(const QByteArray &maybe, const QByteArray &known) +{ + if (maybe.isEmpty()) + return false; + + /* + If \a known (our current best shot at deciding which language to use) + provides more information (e.g. script, country) than \a maybe (a + candidate to replace \a known) and \a maybe agrees with \a known in what + it does provide, we keep \a known; this happens when \a maybe comes from + LANGUAGE (usually a simple language code) and LANG includes script and/or + country. A textual comparison won't do because, for example, bn (Bengali) + isn't a prefix of ben_IN, but the latter is a refinement of the former. + (Meanwhile, bn is a prefix of bnt, Bantu; and a prefix of ben is be, + Belarusian. There are many more such prefixings between two- and + three-letter codes.) + */ + QLocale::Language langm, langk; + QLocale::Script scriptm, scriptk; + QLocale::Country landm, landk; + QLocalePrivate::getLangAndCountry(maybe, langm, scriptm, landm); + QLocalePrivate::getLangAndCountry(known, langk, scriptk, landk); + return (langm != QLocale::AnyLanguage && langm != langk) + || (scriptm != QLocale::AnyScript && scriptm != scriptk) + || (landm != QLocale::AnyCountry && landm != landk); +} + QLocale QSystemLocale::fallbackUiLocale() const { + // See man 7 locale for precedence - LC_ALL beats LC_MESSAGES beats LANG: QByteArray lang = qgetenv("LC_ALL"); if (lang.isEmpty()) lang = qgetenv("LC_MESSAGES"); @@ -118,12 +146,12 @@ QLocale QSystemLocale::fallbackUiLocale() const if (lang.isEmpty() || lang == QByteArray("C") || lang == QByteArray("POSIX")) return QLocale(QString::fromLatin1(lang)); - // if the locale is not the "C" locale and LANGUAGE is not empty, return - // the first part of LANGUAGE if LANGUAGE is set and has a first part: + // ... otherwise, if the first part of LANGUAGE says more than or + // contradicts what we have, use that: QByteArray language = qgetenv("LANGUAGE"); if (!language.isEmpty()) { language = language.split(':').constFirst(); - if (!language.isEmpty()) + if (contradicts(language, lang)) return QLocale(QString::fromLatin1(language)); } diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index a0e408b94a..bccf8c5740 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -246,7 +246,8 @@ namespace QtSharedPointer { struct ExternalRefCountWithContiguousData: public ExternalRefCountData { typedef ExternalRefCountData Parent; - T data; + typedef typename std::remove_cv<T>::type NoCVType; + NoCVType data; static void deleter(ExternalRefCountData *self) { @@ -262,7 +263,7 @@ namespace QtSharedPointer { } static void noDeleter(ExternalRefCountData *) { } - static inline ExternalRefCountData *create(T **ptr, DestroyerFn destroy) + static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy) { ExternalRefCountWithContiguousData *d = static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData))); @@ -437,10 +438,12 @@ public: # endif typename Private::DestroyerFn noDestroy = &Private::noDeleter; QSharedPointer result(Qt::Uninitialized); - result.d = Private::create(&result.value, noDestroy); + typename std::remove_cv<T>::type *ptr; + result.d = Private::create(&ptr, noDestroy); // now initialize the data - new (result.data()) T(std::forward<Args>(arguments)...); + new (ptr) T(std::forward<Args>(arguments)...); + result.value = ptr; result.d->destroyer = destroy; result.d->setQObjectShared(result.value, true); # ifdef QT_SHAREDPOINTER_TRACK_POINTERS diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index f5accd0fec..a04b2f0d02 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -357,11 +357,20 @@ static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval) // character. Usually harmless. bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW { -#if defined(__AVX2__) - if (!simdTestMask(ptr, end, 0x80808080)) - return false; -#elif defined(__SSE2__) +#if defined(__SSE2__) // Testing for the high bit can be done efficiently with just PMOVMSKB +# if defined(__AVX2__) + while (ptr + 32 <= end) { + __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr)); + quint32 mask = _mm256_movemask_epi8(data); + if (mask) { + uint idx = qCountTrailingZeroBits(mask); + ptr += idx; + return false; + } + ptr += 32; + } +# endif while (ptr + 16 <= end) { __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); quint32 mask = _mm_movemask_epi8(data); @@ -778,30 +787,70 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l) } #endif // __mips_dsp #ifdef __SSE2__ - const char *ptr = reinterpret_cast<const char*>(a); - qptrdiff distance = reinterpret_cast<const char*>(b) - ptr; - a += l & ~7; - b += l & ~7; - l &= 7; - - // we're going to read ptr[0..15] (16 bytes) - for ( ; ptr + 15 < reinterpret_cast<const char *>(a); ptr += 16) { - __m128i a_data = _mm_loadu_si128((const __m128i*)ptr); - __m128i b_data = _mm_loadu_si128((const __m128i*)(ptr + distance)); + const QChar *end = a + l; + qptrdiff offset = 0; + + // we're going to read a[0..15] and b[0..15] (32 bytes) + for ( ; a + offset + 16 <= end; offset += 16) { +#ifdef __AVX2__ + __m256i a_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(a + offset)); + __m256i b_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(b + offset)); + __m256i result = _mm256_cmpeq_epi16(a_data, b_data); + uint mask = _mm256_movemask_epi8(result); +#else + __m128i a_data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(a + offset)); + __m128i a_data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(a + offset + 8)); + __m128i b_data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset)); + __m128i b_data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset + 8)); + __m128i result1 = _mm_cmpeq_epi16(a_data1, b_data1); + __m128i result2 = _mm_cmpeq_epi16(a_data2, b_data2); + uint mask = _mm_movemask_epi8(result1) | (_mm_movemask_epi8(result2) << 16); +#endif + mask = ~mask; + if (mask) { + // found a different character + uint idx = qCountTrailingZeroBits(mask); + return a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode(); + } + } + + // we're going to read a[0..7] and b[0..7] (16 bytes) + if (a + offset + 8 <= end) { + __m128i a_data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(a + offset)); + __m128i b_data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset)); __m128i result = _mm_cmpeq_epi16(a_data, b_data); uint mask = ~_mm_movemask_epi8(result); if (ushort(mask)) { - // found a different byte + // found a different character uint idx = qCountTrailingZeroBits(mask); - return reinterpret_cast<const QChar *>(ptr + idx)->unicode() - - reinterpret_cast<const QChar *>(ptr + distance + idx)->unicode(); + return a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode(); } + + offset += 8; } + + // we're going to read a[0..3] and b[0..3] (8 bytes) + if (a + offset + 4 <= end) { + __m128i a_data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(a + offset)); + __m128i b_data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(b + offset)); + __m128i result = _mm_cmpeq_epi16(a_data, b_data); + uint mask = ~_mm_movemask_epi8(result); + if (uchar(mask)) { + // found a different character + uint idx = qCountTrailingZeroBits(mask); + return a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode(); + } + + offset += 4; + } + + // reset l + l &= 3; + const auto lambda = [=](size_t i) -> int { - return reinterpret_cast<const QChar *>(ptr)[i].unicode() - - reinterpret_cast<const QChar *>(ptr + distance)[i].unicode(); + return a[offset + i].unicode() - b[offset + i].unicode(); }; - return UnrollTailLoop<7>::exec(l, 0, lambda, lambda); + return UnrollTailLoop<3>::exec(l, 0, lambda, lambda); #endif #if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64 if (l >= 8) { |