diff options
Diffstat (limited to 'src/corelib')
38 files changed, 545 insertions, 452 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 8b503233a0..8067ca70f1 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -251,6 +251,18 @@ ] } }, + "cxx11_future": { + "label": "C++11 <future>", + "type": "compile", + "test": { + "include": "future", + "main": [ + "std::future<int> f = std::async([]() { return 42; });", + "(void)f.get();" + ], + "qmake": "unix:LIBS += -lpthread" + } + }, "cxx11_random": { "label": "C++11 <random>", "type": "compile", @@ -442,10 +454,10 @@ "condition": "features.doubleconversion && libs.doubleconversion", "output": [ "privateFeature" ] }, - "cxx11_random": { - "label": "C++11 <random>", - "condition": "tests.cxx11_random", - "output": [ "privateFeature" ] + "cxx11_future": { + "label": "C++11 <future>", + "condition": "tests.cxx11_future", + "output": [ "publicFeature" ] }, "eventfd": { "label": "eventfd", @@ -815,10 +827,16 @@ }, "timezone": { "label": "QTimeZone", - "purpose": "Provides support for timezone handling.", + "purpose": "Provides support for time-zone handling.", "section": "Utilities", "output": [ "publicFeature" ] }, + "datetimeparser": { + "label": "QDateTimeParser", + "purpose": "Provides support for parsing date-time texts.", + "section": "Utilities", + "output": [ "privateFeature" ] + }, "commandlineparser": { "label": "QCommandlineParser", "purpose": "Provides support for command line parsing.", @@ -846,9 +864,9 @@ ensure that the IDEs they use either set QT_LOGGING_TO_CONSOLE to 1 or are able to read the logged output from journald, syslog or slog2." }, { - "type": "warning", - "condition": "!config.win32 && !config.darwin && !config.bsd && !features.cxx11_random", - "message": "No high-quality PRNG available for QRandomGenerator fallback.\nIf the HW or OS RNG fails, Qt will abort execution." + "type": "error", + "condition": "!tests.cxx11_random", + "message": "C++11 <random> is required and is missing or failed to compile." }, { "type": "error", diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp index 1169ad5536..8d4bd36beb 100644 --- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp @@ -617,7 +617,7 @@ template<> class QTypeInfo<A> : public QTypeInfoMerger<A, B, C, D> {}; void overloadedFunction(int, QString); void overloadedFunction(int, QString) const; }; - ... qConstOverload<>(&Foo::overloadedFunction) + ... qConstOverload<int, QString>(&Foo::overloadedFunction) ... qNonConstOverload<int, QString>(&Foo::overloadedFunction) //! [54] diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 95095f4b76..2164d7f21f 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -66,8 +66,7 @@ #define QT_NO_USING_NAMESPACE #define QT_NO_DEPRECATED -#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1 -#define QT_NO_DATASTREAM +// Keep feature-test macros in alphabetic order by feature name: #define QT_FEATURE_alloca 1 #define QT_FEATURE_alloca_h -1 #ifdef _WIN32 @@ -75,9 +74,13 @@ #else # define QT_FEATURE_alloca_malloc_h -1 #endif +#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1 #define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1) +#define QT_NO_DATASTREAM +#define QT_FEATURE_datetimeparser -1 #define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1) #define QT_FEATURE_getentropy -1 +#define QT_NO_GEOM_VARIANT #define QT_FEATURE_iconv -1 #define QT_FEATURE_icu -1 #define QT_FEATURE_journald -1 @@ -86,20 +89,19 @@ #define QT_FEATURE_library -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 -#define QT_NO_SYSTEMLOCALE #define QT_FEATURE_renameat2 -1 +#define QT_FEATURE_sharedmemory -1 #define QT_FEATURE_slog2 -1 #define QT_FEATURE_statx -1 #define QT_FEATURE_syslog -1 +#define QT_NO_SYSTEMLOCALE +#define QT_FEATURE_systemsemaphore -1 #define QT_FEATURE_temporaryfile 1 #define QT_NO_THREAD #define QT_FEATURE_timezone -1 #define QT_FEATURE_topleveldomain -1 #define QT_NO_TRANSLATION #define QT_FEATURE_translation -1 -#define QT_NO_GEOM_VARIANT -#define QT_FEATURE_sharedmemory -1 -#define QT_FEATURE_systemsemaphore -1 #ifdef QT_BUILD_QMAKE #define QT_FEATURE_commandlineparser -1 diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index c9ec46c67f..e49bace002 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -357,7 +357,7 @@ typedef double qreal; #if !defined(QT_NAMESPACE) && defined(__cplusplus) && !defined(Q_QDOC) extern "C" #endif -Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion() Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOTHROW; #if defined(__cplusplus) diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h index b1d2836783..0f092e9006 100644 --- a/src/corelib/global/qglobal_p.h +++ b/src/corelib/global/qglobal_p.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -59,5 +60,77 @@ #include <QtCore/private/qtcore-config_p.h> #endif +#if defined(__cplusplus) +#if !QT_HAS_BUILTIN(__builtin_available) +#include <initializer_list> +#include <QtCore/qoperatingsystemversion.h> +#include <QtCore/qversionnumber.h> + +QT_BEGIN_NAMESPACE + +struct qt_clang_builtin_available_os_version_data { + QOperatingSystemVersion::OSType type; + const char *version; +}; + +static inline bool qt_clang_builtin_available( + const std::initializer_list<qt_clang_builtin_available_os_version_data> &versions) +{ + for (auto it = versions.begin(); it != versions.end(); ++it) { + if (QOperatingSystemVersion::currentType() == it->type) { + const auto current = QOperatingSystemVersion::current(); + return QVersionNumber( + current.majorVersion(), + current.minorVersion(), + current.microVersion()) >= QVersionNumber::fromString( + QString::fromLatin1(it->version)); + } + } + + // Result is true if the platform is not any of the checked ones; this matches behavior of + // LLVM __builtin_available and @available constructs + return true; +} + +QT_END_NAMESPACE + +#define QT_AVAILABLE_OS_VER(os, ver) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available_os_version_data){\ + QT_PREPEND_NAMESPACE(QOperatingSystemVersion)::os, #ver} +#define QT_AVAILABLE_CAT(L, R) QT_AVAILABLE_CAT_(L, R) +#define QT_AVAILABLE_CAT_(L, R) L ## R +#define QT_AVAILABLE_EXPAND(...) QT_AVAILABLE_OS_VER(__VA_ARGS__) +#define QT_AVAILABLE_SPLIT(os_ver) QT_AVAILABLE_EXPAND(QT_AVAILABLE_CAT(QT_AVAILABLE_SPLIT_, os_ver)) +#define QT_AVAILABLE_SPLIT_macOS MacOS, +#define QT_AVAILABLE_SPLIT_iOS IOS, +#define QT_AVAILABLE_SPLIT_tvOS TvOS, +#define QT_AVAILABLE_SPLIT_watchOS WatchOS, +#define QT_BUILTIN_AVAILABLE0(e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({}) +#define QT_BUILTIN_AVAILABLE1(a, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a)}) +#define QT_BUILTIN_AVAILABLE2(a, b, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \ + QT_AVAILABLE_SPLIT(b)}) +#define QT_BUILTIN_AVAILABLE3(a, b, c, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \ + QT_AVAILABLE_SPLIT(b), \ + QT_AVAILABLE_SPLIT(c)}) +#define QT_BUILTIN_AVAILABLE4(a, b, c, d, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \ + QT_AVAILABLE_SPLIT(b), \ + QT_AVAILABLE_SPLIT(c), \ + QT_AVAILABLE_SPLIT(d)}) +#define QT_BUILTIN_AVAILABLE_ARG(arg0, arg1, arg2, arg3, arg4, arg5, ...) arg5 +#define QT_BUILTIN_AVAILABLE_CHOOSER(...) QT_BUILTIN_AVAILABLE_ARG(__VA_ARGS__, \ + QT_BUILTIN_AVAILABLE4, \ + QT_BUILTIN_AVAILABLE3, \ + QT_BUILTIN_AVAILABLE2, \ + QT_BUILTIN_AVAILABLE1, \ + QT_BUILTIN_AVAILABLE0, ) +#define __builtin_available(...) QT_BUILTIN_AVAILABLE_CHOOSER(__VA_ARGS__)(__VA_ARGS__) +#endif // !QT_HAS_BUILTIN(__builtin_available) +#endif // defined(__cplusplus) + #endif // QGLOBAL_P_H diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index e74ba4026a..e64fb221d3 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2959,10 +2959,10 @@ This enum specifies the coordinate system. - \value DeviceCoordinates Coordinates are relative to the upper-left corner + \value DeviceCoordinates Coordinates are relative to the top-left corner of the object's paint device. - \value LogicalCoordinates Coordinates are relative to the upper-left corner + \value LogicalCoordinates Coordinates are relative to the top-left corner of the object. */ diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 22d23ae6fa..d77ec8075a 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -46,16 +46,15 @@ #include <qthreadstorage.h> #include <private/qsimd_p.h> +#include <random> + #include <errno.h> #if QT_CONFIG(getentropy) # include <sys/random.h> -#else -# if QT_CONFIG(cxx11_random) -# include <random> -# include "qdeadlinetimer.h" -# include "qhashfunctions.h" -# endif +#elif !defined(Q_OS_BSD4) && !defined(Q_OS_WIN) +# include "qdeadlinetimer.h" +# include "qhashfunctions.h" # if QT_CONFIG(getauxval) # include <sys/auxv.h> @@ -95,7 +94,7 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando QT_BEGIN_NAMESPACE #if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) -static qssize_t qt_random_cpu(void *buffer, qssize_t count); +static qssize_t qt_random_cpu(void *buffer, qssize_t count) Q_DECL_NOTHROW; # ifdef Q_PROCESSOR_X86_64 # define _rdrandXX_step _rdrand64_step @@ -103,7 +102,7 @@ static qssize_t qt_random_cpu(void *buffer, qssize_t count); # define _rdrandXX_step _rdrand32_step # endif -static QT_FUNCTION_TARGET(RDRND) qssize_t qt_random_cpu(void *buffer, qssize_t count) +static QT_FUNCTION_TARGET(RDRND) qssize_t qt_random_cpu(void *buffer, qssize_t count) Q_DECL_NOTHROW { unsigned *ptr = reinterpret_cast<unsigned *>(buffer); unsigned *end = ptr + count; @@ -215,7 +214,7 @@ class SystemRandom { public: enum { EfficientBufferFill = true }; - static qssize_t fillBuffer(void *buffer, qssize_t count) + static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { auto RtlGenRandom = SystemFunction036; return RtlGenRandom(buffer, ULONG(count)) ? count: 0; @@ -226,7 +225,7 @@ class SystemRandom { public: enum { EfficientBufferFill = false }; - static qssize_t fillBuffer(void *, qssize_t) + static qssize_t fillBuffer(void *, qssize_t) Q_DECL_NOTHROW { // always use the fallback return 0; @@ -260,7 +259,7 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW // BSDs have arc4random(4) and these work even in chroot(2) arc4random_buf(ptr, left * sizeof(*ptr)); } -#elif QT_CONFIG(cxx11_random) +#else static QBasicAtomicInteger<unsigned> seed = Q_BASIC_ATOMIC_INITIALIZER(0U); static void fallback_update_seed(unsigned value) { @@ -314,7 +313,7 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW // (other ELF-based systems don't seem to have AT_RANDOM) ulong auxvSeed = getauxval(AT_RANDOM); if (auxvSeed) { - memcpy(scratch, reinterpret_cast<void *>(auxvSeed), 16); + memcpy(end, reinterpret_cast<void *>(auxvSeed), 16); end += 4; // 7 to 10 } # endif @@ -345,15 +344,9 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW fallback_update_seed(*ptr); } -#else -static void fallback_update_seed(unsigned) {} -static Q_NORETURN void fallback_fill(quint32 *, qssize_t) -{ - qFatal("Random number generator failed and no high-quality backup available"); -} #endif -static qssize_t fill_cpu(quint32 *buffer, qssize_t count) +static qssize_t fill_cpu(quint32 *buffer, qssize_t count) Q_DECL_NOTHROW { #if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) if (qCpuHasFeature(RDRND) && (uint(qt_randomdevice_control) & SkipHWRNG) == 0) @@ -366,6 +359,7 @@ static qssize_t fill_cpu(quint32 *buffer, qssize_t count) } static void fill_internal(quint32 *buffer, qssize_t count) + Q_DECL_NOEXCEPT_EXPR(noexcept(SystemRandom::fillBuffer(buffer, count))) { if (Q_UNLIKELY(uint(qt_randomdevice_control) & SetRandomData)) { uint value = uint(qt_randomdevice_control) & RandomDataMask; @@ -389,6 +383,7 @@ static void fill_internal(quint32 *buffer, qssize_t count) } static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) + Q_DECL_NOEXCEPT_EXPR(noexcept(fill_internal(static_cast<quint32 *>(buffer), 1))) { struct ThreadState { enum { @@ -461,7 +456,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) The class can generate 32-bit or 64-bit quantities, or fill an array of those. The most common way of generating new values is to call the generate(), - get64() or fillRange() functions. One would use it as: + generate64() or fillRange() functions. One would use it as: \code quint32 value = QRandomGenerator::generate(); @@ -626,7 +621,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) quantities, one can write: \code - std::generate(begin, end, []() { return get64(); }); + std::generate(begin, end, []() { return QRandomGenerator::generate64(); }); \endcode If the range refers to contiguous memory (such as an array or the data from @@ -678,14 +673,14 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) QRandomGenerator::fillRange(array); \endcode - It would have also been possible to make one call to get64() and then split + It would have also been possible to make one call to generate64() and then split the two halves of the 64-bit value. \sa generate() */ /*! - \fn qreal QRandomGenerator::generateReal() + \fn qreal QRandomGenerator::generateDouble() Generates one random qreal in the canonical range [0, 1) (that is, inclusive of zero and exclusive of 1). @@ -700,7 +695,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{std::uniform_real_distribution}} with parameters 0 and 1. - \sa generate(), get64(), bounded() + \sa generate(), generate64(), bounded() */ /*! @@ -738,7 +733,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) Note that this function cannot be used to obtain values in the full 32-bit range of quint32. Instead, use generate(). - \sa generate(), get64(), generateDouble() + \sa generate(), generate64(), generateDouble() */ /*! @@ -751,7 +746,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) Note that this function cannot be used to obtain values in the full 32-bit range of int. Instead, use generate() and cast to int. - \sa generate(), get64(), generateDouble() + \sa generate(), generate64(), generateDouble() */ /*! @@ -775,7 +770,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) Note that this function cannot be used to obtain values in the full 32-bit range of quint32. Instead, use generate(). - \sa generate(), get64(), generateDouble() + \sa generate(), generate64(), generateDouble() */ /*! @@ -788,7 +783,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) Note that this function cannot be used to obtain values in the full 32-bit range of int. Instead, use generate() and cast to int. - \sa generate(), get64(), generateDouble() + \sa generate(), generate64(), generateDouble() */ /*! @@ -896,7 +891,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) int value = QRandomGenerator::generate() & std::numeric_limits<int>::max(); \endcode - \sa get64(), generateDouble() + \sa generate64(), generateDouble() */ quint32 QRandomGenerator::generate() { diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 73a2e37a38..7abdf90bf5 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -86,8 +86,6 @@ QString QFileSystemEngine::slowCanonicalized(const QString &path) fi.setFile(prefix); if (fi.isSymLink()) { QString target = fi.symLinkTarget(); - if(QFileInfo(target).isRelative()) - target = fi.absolutePath() + slash + target; if (separatorPos != -1) { if (fi.isDir() && !target.endsWith(slash)) target.append(slash); diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 9fb3855472..52512c5e13 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -412,8 +412,11 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data) int ret = qt_fstatx(fd, &statxBuffer); if (ret != -ENOSYS) { - data.fillFromStatxBuf(statxBuffer); - return ret == 0; + if (ret == 0) { + data.fillFromStatxBuf(statxBuffer); + return true; + } + return false; } if (QT_FSTAT(fd, &statBuffer) == 0) { @@ -635,13 +638,8 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, } ret += QFile::decodeName(s); - if (!ret.startsWith(QLatin1Char('/'))) { - const QString linkPath = link.path(); - if (linkPath.startsWith(QLatin1Char('/'))) - ret.prepend(linkPath + QLatin1Char('/')); - else - ret.prepend(QDir::currentPath() + QLatin1Char('/') + linkPath + QLatin1Char('/')); - } + if (!ret.startsWith(QLatin1Char('/'))) + ret.prepend(absoluteName(link).path() + QLatin1Char('/')); ret = QDir::cleanPath(ret); if (ret.size() > 1 && ret.endsWith(QLatin1Char('/'))) ret.chop(1); @@ -1234,11 +1232,7 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { #if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000) - const auto current = QOperatingSystemVersion::current(); - if (current >= QOperatingSystemVersion::MacOSSierra || - current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) { + if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) { if (::clonefile(source.nativeFilePath().constData(), target.nativeFilePath().constData(), 0) == 0) return true; @@ -1273,11 +1267,7 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy } #endif #if defined(Q_OS_DARWIN) && defined(RENAME_EXCL) - const auto current = QOperatingSystemVersion::current(); - if (current >= QOperatingSystemVersion::MacOSSierra || - current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) || - current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) { + if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) { if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0) return true; if (errno != ENOTSUP) { diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp index 48317d07e0..129cf01b63 100644 --- a/src/corelib/io/qlockfile.cpp +++ b/src/corelib/io/qlockfile.cpp @@ -2,6 +2,7 @@ ** ** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org> ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,12 +43,34 @@ #include "qlockfile_p.h" #include <QtCore/qthread.h> +#include <QtCore/qcoreapplication.h> #include <QtCore/qdeadlinetimer.h> #include <QtCore/qdatetime.h> #include <QtCore/qfileinfo.h> QT_BEGIN_NAMESPACE +namespace { +struct LockFileInfo +{ + qint64 pid; + QString appname; + QString hostname; +}; +} + +static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info); + +static QString machineName() +{ +#ifdef Q_OS_WIN + // we don't use QSysInfo because it tries to do name resolution + return qEnvironmentVariable("COMPUTERNAME"); +#else + return QSysInfo::machineHostName(); +#endif +} + /*! \class QLockFile \inmodule QtCore @@ -291,10 +314,27 @@ bool QLockFile::tryLock(int timeout) bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const { Q_D(const QLockFile); - return d->getLockInfo(pid, hostname, appname); + LockFileInfo info; + if (!getLockInfo_helper(d->fileName, &info)) + return false; + if (pid) + *pid = info.pid; + if (hostname) + *hostname = info.hostname; + if (appname) + *appname = info.appname; + return true; } -bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const +QByteArray QLockFilePrivate::lockFileContents() const +{ + // Use operator% from the fast builder to avoid multiple memory allocations. + return QByteArray::number(QCoreApplication::applicationPid()) % '\n' + % processNameByPid(QCoreApplication::applicationPid()).toUtf8() % '\n' + % machineName().toUtf8() % '\n'; +} + +static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info) { QFile reader(fileName); if (!reader.open(QIODevice::ReadOnly)) @@ -309,14 +349,25 @@ bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appn QByteArray hostNameLine = reader.readLine(); hostNameLine.chop(1); - qint64 thePid = pidLine.toLongLong(); - if (pid) - *pid = thePid; - if (appname) - *appname = QString::fromUtf8(appNameLine); - if (hostname) - *hostname = QString::fromUtf8(hostNameLine); - return thePid > 0; + bool ok; + info->appname = QString::fromUtf8(appNameLine); + info->hostname = QString::fromUtf8(hostNameLine); + info->pid = pidLine.toLongLong(&ok); + return ok && info->pid > 0; +} + +bool QLockFilePrivate::isApparentlyStale() const +{ + LockFileInfo info; + if (getLockInfo_helper(fileName, &info)) { + if (info.hostname.isEmpty() || info.hostname == machineName()) { + if (!isProcessRunning(info.pid, info.appname)) + return true; + } + } + + const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTimeUtc()); + return staleLockTime > 0 && qAbs(age) > staleLockTime; } /*! diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h index 86a606ec00..b41dfb38ad 100644 --- a/src/corelib/io/qlockfile_p.h +++ b/src/corelib/io/qlockfile_p.h @@ -78,16 +78,14 @@ public: } QLockFile::LockError tryLock_sys(); bool removeStaleLock(); - bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const; + QByteArray lockFileContents() const; // Returns \c true if the lock belongs to dead PID, or is old. // The attempt to delete it will tell us if it was really stale or not, though. bool isApparentlyStale() const; + // used in dbusmenu Q_CORE_EXPORT static QString processNameByPid(qint64 pid); - -#ifdef Q_OS_UNIX - static int checkFcntlWorksAfterFlock(const QString &fn); -#endif + static bool isProcessRunning(qint64 pid, const QString &appname); QString fileName; #ifdef Q_OS_WIN diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 1ee8ce889c..fc01f83e80 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org> -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** @@ -42,7 +42,6 @@ #include "private/qlockfile_p.h" #include "QtCore/qtemporaryfile.h" -#include "QtCore/qcoreapplication.h" #include "QtCore/qfileinfo.h" #include "QtCore/qdebug.h" #include "QtCore/qdatetime.h" @@ -94,91 +93,59 @@ static qint64 qt_write_loop(int fd, const char *data, qint64 len) return pos; } -int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) -{ -#ifndef QT_NO_TEMPORARYFILE - QTemporaryFile file(fn); - if (!file.open()) - return 0; - const int fd = file.d_func()->engine()->handle(); -#if defined(LOCK_EX) && defined(LOCK_NB) - if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs - return 0; -#endif - struct flock flockData; - flockData.l_type = F_WRLCK; - flockData.l_whence = SEEK_SET; - flockData.l_start = 0; - flockData.l_len = 0; // 0 = entire file - flockData.l_pid = getpid(); - if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems - return 0; - return 1; -#else - Q_UNUSED(fn); - return 0; -#endif -} - -// Cache the result of checkFcntlWorksAfterFlock for each directory a lock -// file is created in because in some filesystems, like NFS, both locks -// are the same. This does not take into account a filesystem changing. -// QCache is set to hold a maximum of 10 entries, this is to avoid unbounded -// growth, this is caching directories of files and it is assumed a low number -// will be sufficient. -typedef QCache<QString, bool> CacheType; -Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10)); -static QBasicMutex fcntlLock; +/* + * Details about file locking on Unix. + * + * There are three types of advisory locks on Unix systems: + * 1) POSIX process-wide locks using fcntl(F_SETLK) + * 2) BSD flock(2) system call + * 3) Linux-specific file descriptor locks using fcntl(F_OFD_SETLK) + * There's also a mandatory locking feature by POSIX, which is deprecated on + * Linux and users are advised not to use it. + * + * The first problem is that the POSIX API is braindead. POSIX.1-2008 says: + * + * All locks associated with a file for a given process shall be removed when + * a file descriptor for that file is closed by that process or the process + * holding that file descriptor terminates. + * + * The Linux manpage is clearer: + * + * * If a process closes _any_ file descriptor referring to a file, then all + * of the process's locks on that file are released, regardless of the file + * descriptor(s) on which the locks were obtained. This is bad: [...] + * + * * The threads in a process share locks. In other words, a multithreaded + * program can't use record locking to ensure that threads don't + * simultaneously access the same region of a file. + * + * So in order to use POSIX locks, we'd need a global mutex that stays locked + * while the QLockFile is locked. For that reason, Qt does not use POSIX + * advisory locks anymore. + * + * The next problem is that POSIX leaves undefined the relationship between + * locks with fcntl(), flock() and lockf(). In some systems (like the BSDs), + * all three use the same record set, while on others (like Linux) the locks + * are independent, except if locking over NFS mounts, in which case they're + * actually the same. Therefore, it's a very bad idea to mix them in the same + * process. + * + * We therefore use only flock(2). + */ -/*! - \internal - Checks that the OS isn't using POSIX locks to emulate flock(). - \macos is one of those. -*/ -static bool fcntlWorksAfterFlock(const QString &fn) -{ - QMutexLocker lock(&fcntlLock); - if (fcntlOK.isDestroyed()) - return QLockFilePrivate::checkFcntlWorksAfterFlock(fn); - bool *worksPtr = fcntlOK->object(fn); - if (worksPtr) - return *worksPtr; - - const bool val = QLockFilePrivate::checkFcntlWorksAfterFlock(fn); - worksPtr = new bool(val); - fcntlOK->insert(fn, worksPtr); - - return val; -} - -static bool setNativeLocks(const QString &fileName, int fd) +static bool setNativeLocks(int fd) { #if defined(LOCK_EX) && defined(LOCK_NB) if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs return false; +#else + Q_UNUSED(fd); #endif - struct flock flockData; - flockData.l_type = F_WRLCK; - flockData.l_whence = SEEK_SET; - flockData.l_start = 0; - flockData.l_len = 0; // 0 = entire file - flockData.l_pid = getpid(); - if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/')) - && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems - return false; - } return true; } QLockFile::LockError QLockFilePrivate::tryLock_sys() { - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - // Use operator% from the fast builder to avoid multiple memory allocations. - QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n' - % QCoreApplication::applicationName().toUtf8() % '\n' - % QSysInfo::machineHostName().toUtf8() % '\n'; - const QByteArray lockFileName = QFile::encodeName(fileName); const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd < 0) { @@ -193,11 +160,12 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() } } // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fileName, fd)) { + if (!setNativeLocks(fd)) { const int errnoSaved = errno; qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); } + QByteArray fileData = lockFileContents(); if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { qt_safe_close(fd); if (!QFile::remove(fileName)) @@ -224,31 +192,26 @@ bool QLockFilePrivate::removeStaleLock() const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0666); if (fd < 0) // gone already? return false; - bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0); + bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); close(fd); return success; } -bool QLockFilePrivate::isApparentlyStale() const +bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname) { - qint64 pid; - QString hostname, appname; - if (getLockInfo(&pid, &hostname, &appname)) { - if (hostname.isEmpty() || hostname == QSysInfo::machineHostName()) { - if (::kill(pid, 0) == -1 && errno == ESRCH) - return true; // PID doesn't exist anymore - const QString processName = processNameByPid(pid); - if (!processName.isEmpty()) { - QFileInfo fi(appname); - if (fi.isSymLink()) - fi.setFile(fi.symLinkTarget()); - if (processName != fi.fileName()) - return true; // PID got reused by a different application. - } - } + if (::kill(pid, 0) == -1 && errno == ESRCH) + return false; // PID doesn't exist anymore + + const QString processName = processNameByPid(pid); + if (!processName.isEmpty()) { + QFileInfo fi(appname); + if (fi.isSymLink()) + fi.setFile(fi.symLinkTarget()); + if (processName != fi.fileName()) + return false; // PID got reused by a different application. } - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && qAbs(age) > staleLockTime; + + return true; } QString QLockFilePrivate::processNameByPid(qint64 pid) diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index 4b43181686..de64ec0432 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -2,6 +2,7 @@ ** ** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org> ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,7 +43,6 @@ #include "private/qfilesystementry_p.h" #include <qt_windows.h> -#include "QtCore/qcoreapplication.h" #include "QtCore/qfileinfo.h" #include "QtCore/qdatetime.h" #include "QtCore/qdebug.h" @@ -50,11 +50,6 @@ QT_BEGIN_NAMESPACE -static inline QByteArray localHostName() -{ - return qgetenv("COMPUTERNAME"); -} - static inline bool fileExists(const wchar_t *fileName) { WIN32_FILE_ATTRIBUTE_DATA data; @@ -107,15 +102,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // We hold the lock, continue. fileHandle = fh; - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - QByteArray fileData; - fileData += QByteArray::number(QCoreApplication::applicationPid()); - fileData += '\n'; - fileData += QCoreApplication::applicationName().toUtf8(); - fileData += '\n'; - fileData += localHostName(); - fileData += '\n'; + QByteArray fileData = lockFileContents(); DWORD bytesWritten = 0; QLockFile::LockError error = QLockFile::NoError; if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh)) @@ -129,38 +116,33 @@ bool QLockFilePrivate::removeStaleLock() return QFile::remove(fileName); } -bool QLockFilePrivate::isApparentlyStale() const +bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname) { - qint64 pid; - QString hostname, appname; - // On WinRT there seems to be no way of obtaining information about other // processes due to sandboxing #ifndef Q_OS_WINRT - if (getLockInfo(&pid, &hostname, &appname)) { - if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) { - HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!procHandle) - return true; - // We got a handle but check if process is still alive - DWORD exitCode = 0; - if (!::GetExitCodeProcess(procHandle, &exitCode)) - exitCode = 0; - ::CloseHandle(procHandle); - if (exitCode != STILL_ACTIVE) - return true; - const QString processName = processNameByPid(pid); - if (!processName.isEmpty() && processName != appname) - return true; // PID got reused by a different application. - } - } + HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!procHandle) + return false; + + // We got a handle but check if process is still alive + DWORD exitCode = 0; + if (!::GetExitCodeProcess(procHandle, &exitCode)) + exitCode = 0; + ::CloseHandle(procHandle); + if (exitCode != STILL_ACTIVE) + return false; + + const QString processName = processNameByPid(pid); + if (!processName.isEmpty() && processName != appname) + return false; // PID got reused by a different application. + #else // !Q_OS_WINRT Q_UNUSED(pid); - Q_UNUSED(hostname); Q_UNUSED(appname); #endif // Q_OS_WINRT - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && qAbs(age) > staleLockTime; + + return true; } QString QLockFilePrivate::processNameByPid(qint64 pid) diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index b4d83414ae..a886c9d1d2 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -139,7 +139,7 @@ public: static QString applicationDirPath(); static QString applicationFilePath(); - static qint64 applicationPid(); + static qint64 applicationPid() Q_DECL_CONST_FUNCTION; #if QT_CONFIG(library) static void setLibraryPaths(const QStringList &); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 569fbc2796..bbd442d570 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -942,7 +942,8 @@ void QEventDispatcherWin32::activateEventNotifiers() for (int i = d->winEventNotifierList.count(); --i >= 0;) { QWinEventNotifier *notifier = d->winEventNotifierList.at(i); QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); - if (WaitForSingleObject(nd->handleToEvent, 0) == WAIT_OBJECT_0) { + if (nd->signaledCount.load() != 0) { + --nd->signaledCount; nd->unregisterWaitObject(); d->activateEventNotifier(notifier); } diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index 1a65e6298d..d41573264f 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -165,37 +165,31 @@ Q_SIGNALS: public: #if QT_HAS_INCLUDE(<chrono>) || defined(Q_QDOC) - Q_ALWAYS_INLINE void setInterval(std::chrono::milliseconds value) { setInterval(int(value.count())); } - Q_ALWAYS_INLINE std::chrono::milliseconds intervalAsDuration() const { return std::chrono::milliseconds(interval()); } - Q_ALWAYS_INLINE std::chrono::milliseconds remainingTimeAsDuration() const { return std::chrono::milliseconds(remainingTime()); } - Q_ALWAYS_INLINE static void singleShot(std::chrono::milliseconds value, const QObject *receiver, const char *member) { singleShot(int(value.count()), receiver, member); } - Q_ALWAYS_INLINE static void singleShot(std::chrono::milliseconds value, Qt::TimerType timerType, const QObject *receiver, const char *member) { singleShot(int(value.count()), timerType, receiver, member); } - Q_ALWAYS_INLINE void start(std::chrono::milliseconds value) { start(int(value.count())); diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 6bfa6ca729..362111a2c8 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -157,6 +157,7 @@ void QWinEventNotifier::setHandle(HANDLE hEvent) Q_D(QWinEventNotifier); setEnabled(false); d->handleToEvent = hEvent; + d->signaledCount = 0; } /*! @@ -254,6 +255,7 @@ static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/) QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load(); QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get( static_cast<QEventDispatcherWin32 *>(eventDispatcher)); + ++nd->signaledCount; SetEvent(edp->winEventNotifierActivatedEvent); } diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h index bddeaaf134..8bb2c3159a 100644 --- a/src/corelib/kernel/qwineventnotifier_p.h +++ b/src/corelib/kernel/qwineventnotifier_p.h @@ -54,6 +54,7 @@ #include "qwineventnotifier.h" #include <private/qobject_p.h> +#include <QtCore/qatomic.h> #include <QtCore/qt_windows.h> QT_BEGIN_NAMESPACE @@ -73,6 +74,7 @@ public: HANDLE handleToEvent; HANDLE waitHandle = NULL; + QAtomicInt signaledCount; bool enabled; }; diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index e3ba1e4449..e92be64dfa 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -925,7 +925,7 @@ bool QThread::isInterruptionRequested() const \sa start() */ -#ifdef QTHREAD_HAS_CREATE +#if QT_CONFIG(cxx11_future) class QThreadCreateThread : public QThread { public: @@ -947,7 +947,7 @@ QThread *QThread::createThreadImpl(std::future<void> &&future) { return new QThreadCreateThread(std::move(future)); } -#endif // QTHREAD_HAS_CREATE +#endif // QT_CONFIG(cxx11_future) /*! \class QDaemonThread diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index d18152a52d..1f98cb59af 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,17 +43,10 @@ #include <QtCore/qobject.h> -// The implementation of QThread::create uses various C++14/C++17 facilities; -// we must check for their presence. Specifically for glibcxx bundled in MinGW -// with win32 threads, we check the condition found in its <future> header -// since _GLIBCXX_HAS_GTHREADS might then not be defined. -// For std::async (used in all codepaths) -// there is no SG10 feature macro; just test for the header presence. -// For the C++17 codepath do some more throughout checks for std::invoke and -// C++14 lambdas availability. -#if QT_HAS_INCLUDE(<future>) \ - && (!defined(__GLIBCXX__) || (defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1))) -# define QTHREAD_HAS_CREATE +// For QThread::create. The configure-time test just checks for the availability +// of std::future and std::async; for the C++17 codepath we perform some extra +// checks here (for std::invoke and C++14 lambdas). +#if QT_CONFIG(cxx11_future) # include <future> // for std::async # include <functional> // for std::invoke; no guard needed as it's a C++98 header @@ -125,16 +119,16 @@ public: template <typename Function> static QThread *create(Function &&f); #else -#ifdef QTHREAD_HAS_CREATE -#ifdef QTHREAD_HAS_VARIADIC_CREATE +# if QT_CONFIG(cxx11_future) +# ifdef QTHREAD_HAS_VARIADIC_CREATE template <typename Function, typename... Args> static QThread *create(Function &&f, Args &&... args); -#else +# else template <typename Function> static QThread *create(Function &&f); -#endif -#endif -#endif +# endif // QTHREAD_HAS_VARIADIC_CREATE +# endif // QT_CONFIG(cxx11_future) +#endif // Q_QDOC public Q_SLOTS: void start(Priority = InheritPriority); @@ -165,7 +159,7 @@ protected: private: Q_DECLARE_PRIVATE(QThread) -#ifdef QTHREAD_HAS_CREATE +#if QT_CONFIG(cxx11_future) static QThread *createThreadImpl(std::future<void> &&future); #endif @@ -173,9 +167,9 @@ private: friend class QThreadData; }; -#ifdef QTHREAD_HAS_CREATE +#if QT_CONFIG(cxx11_future) -#ifdef QTHREAD_HAS_VARIADIC_CREATE +#if defined(QTHREAD_HAS_VARIADIC_CREATE) // C++17: std::thread's constructor complying call template <typename Function, typename... Args> QThread *QThread::create(Function &&f, Args &&... args) @@ -243,7 +237,7 @@ QThread *QThread::create(Function &&f) } #endif // QTHREAD_HAS_VARIADIC_CREATE -#endif // QTHREAD_HAS_CREATE +#endif // QT_CONFIG(cxx11_future) #else // QT_NO_THREAD diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 38c1820685..300f795469 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -256,21 +256,21 @@ public: # define Q_REQUIRED_RESULT # define Q_REQUIRED_RESULT_pushed # endif - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray toLower() const & + Q_REQUIRED_RESULT QByteArray toLower() const & { return toLower_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray toLower() && + Q_REQUIRED_RESULT QByteArray toLower() && { return toLower_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray toUpper() const & + Q_REQUIRED_RESULT QByteArray toUpper() const & { return toUpper_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray toUpper() && + Q_REQUIRED_RESULT QByteArray toUpper() && { return toUpper_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray trimmed() const & + Q_REQUIRED_RESULT QByteArray trimmed() const & { return trimmed_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray trimmed() && + Q_REQUIRED_RESULT QByteArray trimmed() && { return trimmed_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray simplified() const & + Q_REQUIRED_RESULT QByteArray simplified() const & { return simplified_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QByteArray simplified() && + Q_REQUIRED_RESULT QByteArray simplified() && { return simplified_helper(*this); } # ifdef Q_REQUIRED_RESULT_pushed # pragma pop_macro("Q_REQUIRED_RESULT") diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index ffad2df053..a1b121f1ee 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -254,7 +254,9 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant \note In Qt versions before 5.9, when asked to generate a SHA3 hash sum, QCryptographicHash actually calculated Keccak. If you need compatibility with - SHA-3 hashes produced by those versions of Qt, use the \c{Keccak_} enumerators. + SHA-3 hashes produced by those versions of Qt, use the \c{Keccak_} + enumerators. Alternatively, if source compatibility is required, define the + macro \c QT_SHA3_KECCAK_COMPAT. \value Md4 Generate an MD4 hash sum \value Md5 Generate an MD5 hash sum @@ -267,10 +269,14 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant \value Sha3_256 Generate an SHA3-256 hash sum. Introduced in Qt 5.1 \value Sha3_384 Generate an SHA3-384 hash sum. Introduced in Qt 5.1 \value Sha3_512 Generate an SHA3-512 hash sum. Introduced in Qt 5.1 - \value Keccak_224 \deprecated Generate a Keccak-224 hash sum. Introduced in Qt 5.10 - \value Keccak_256 \deprecated Generate a Keccak-256 hash sum. Introduced in Qt 5.10 - \value Keccak_384 \deprecated Generate a Keccak-384 hash sum. Introduced in Qt 5.10 - \value Keccak_512 \deprecated Generate a Keccak-512 hash sum. Introduced in Qt 5.10 + \value Keccak_224 Generate a Keccak-224 hash sum. Introduced in Qt 5.9.2 + \value Keccak_256 Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2 + \value Keccak_384 Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2 + \value Keccak_512 Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2 + \omitvalue RealSha3_224 + \omitvalue RealSha3_256 + \omitvalue RealSha3_384 + \omitvalue RealSha3_512 */ /*! @@ -324,19 +330,19 @@ void QCryptographicHash::reset() case Sha512: SHA512Reset(&d->sha512Context); break; - case Sha3_224: + case RealSha3_224: case Keccak_224: sha3Init(&d->sha3Context, 224); break; - case Sha3_256: + case RealSha3_256: case Keccak_256: sha3Init(&d->sha3Context, 256); break; - case Sha3_384: + case RealSha3_384: case Keccak_384: sha3Init(&d->sha3Context, 384); break; - case Sha3_512: + case RealSha3_512: case Keccak_512: sha3Init(&d->sha3Context, 512); break; @@ -379,19 +385,19 @@ void QCryptographicHash::addData(const char *data, int length) case Sha512: SHA512Input(&d->sha512Context, reinterpret_cast<const unsigned char *>(data), length); break; - case Sha3_224: + case RealSha3_224: case Keccak_224: sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); break; - case Sha3_256: + case RealSha3_256: case Keccak_256: sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); break; - case Sha3_384: + case RealSha3_384: case Keccak_384: sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); break; - case Sha3_512: + case RealSha3_512: case Keccak_512: sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); break; @@ -491,19 +497,19 @@ QByteArray QCryptographicHash::result() const SHA512Result(©, reinterpret_cast<unsigned char *>(d->result.data())); break; } - case Sha3_224: { + case RealSha3_224: { d->sha3Finish(224, QCryptographicHashPrivate::Sha3Variant::Sha3); break; } - case Sha3_256: { + case RealSha3_256: { d->sha3Finish(256, QCryptographicHashPrivate::Sha3Variant::Sha3); break; } - case Sha3_384: { + case RealSha3_384: { d->sha3Finish(384, QCryptographicHashPrivate::Sha3Variant::Sha3); break; } - case Sha3_512: { + case RealSha3_512: { d->sha3Finish(512, QCryptographicHashPrivate::Sha3Variant::Sha3); break; } diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h index 20afab8b87..2f74d42405 100644 --- a/src/corelib/tools/qcryptographichash.h +++ b/src/corelib/tools/qcryptographichash.h @@ -65,15 +65,26 @@ public: Sha256, Sha384, Sha512, - Sha3_224, - Sha3_256, - Sha3_384, - Sha3_512, - // ### Qt 6: remove the Keccak enumerators - Keccak_224, + + Keccak_224 = 7, Keccak_256, Keccak_384, - Keccak_512 + Keccak_512, + RealSha3_224 = 11, + RealSha3_256, + RealSha3_384, + RealSha3_512, +# ifndef QT_SHA3_KECCAK_COMPAT + Sha3_224 = RealSha3_224, + Sha3_256 = RealSha3_256, + Sha3_384 = RealSha3_384, + Sha3_512 = RealSha3_512 +# else + Sha3_224 = Keccak_224, + Sha3_256 = Keccak_256, + Sha3_384 = Keccak_384, + Sha3_512 = Keccak_512 +# endif #endif }; Q_ENUM(Algorithm) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 056dff5442..f6fc672486 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -40,7 +40,9 @@ #include "qplatformdefs.h" #include "private/qdatetime_p.h" +#if QT_CONFIG(datetimeparser) #include "private/qdatetimeparser_p.h" +#endif #include "qdatastream.h" #include "qset.h" @@ -1337,7 +1339,7 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format) QDate QDate::fromString(const QString &string, const QString &format) { QDate date; -#if QT_CONFIG(timezone) +#if QT_CONFIG(datetimeparser) QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); // dt.setDefaultLocale(QLocale::c()); ### Qt 6 if (dt.parseFormat(format)) @@ -2055,7 +2057,7 @@ QTime QTime::fromString(const QString& string, Qt::DateFormat format) QTime QTime::fromString(const QString &string, const QString &format) { QTime time; -#if QT_CONFIG(timezone) +#if QT_CONFIG(datetimeparser) QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); // dt.setDefaultLocale(QLocale::c()); ### Qt 6 if (dt.parseFormat(format)) @@ -5055,7 +5057,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) QDateTime QDateTime::fromString(const QString &string, const QString &format) { -#if QT_CONFIG(timezone) +#if QT_CONFIG(datetimeparser) QTime time; QDate date; diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 3908e6710e..978b663444 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE -#ifndef QT_BOOTSTRAPPED - QDateTimeParser::~QDateTimeParser() { } @@ -1996,6 +1994,4 @@ bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::S return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count); } -#endif // QT_BOOTSTRAPPED - QT_END_NAMESPACE diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index f6f9ed5e24..75497f5c5a 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -63,6 +63,8 @@ #include "QtCore/qvector.h" #include "QtCore/qcoreapplication.h" +QT_REQUIRE_CONFIG(datetimeparser); + #define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0) #define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) #define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1) @@ -75,8 +77,6 @@ QT_BEGIN_NAMESPACE -#ifndef QT_BOOTSTRAPPED - class Q_CORE_EXPORT QDateTimeParser { Q_DECLARE_TR_FUNCTIONS(QDateTimeParser) @@ -305,8 +305,6 @@ Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDat Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections) Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo) -#endif // QT_BOOTSTRAPPED - QT_END_NAMESPACE #endif // QDATETIME_P_H diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h index 918b124d5c..586d26cbad 100644 --- a/src/corelib/tools/qiterator.h +++ b/src/corelib/tools/qiterator.h @@ -210,126 +210,6 @@ private: Iterator i; }; -/*! \class QKeyValueIterator - \inmodule QtCore - \since 5.10 - - \brief Iterator over the key/value pairs of an associative container. - - The QKeyValueIterator class provides an STL-style iterator for returning - key/value pairs from associative containers like QHash and QMap. It - supports the same API as the STL associative containers, i.e. getting a - key/value pair when iterating through the container. - - This will allow for better interoperability between QMap, QHash and friends - and STL-style algorithms. - - \warning Iterators on implicitly shared containers do not work - exactly like STL-iterators. You should avoid copying a container - while iterators are active on that container. For more information, - read \l{Implicit sharing iterator problem}. -*/ - -/*! \typedef QKeyValueIterator::iterator_category - \internal -*/ - -/*! \typedef QKeyValueIterator::difference_type - \internal -*/ - -/*! \typedef QKeyValueIterator::value_type - \internal -*/ - -/*! \typedef QKeyValueIterator::pointer - \internal -*/ - -/*! \typedef QKeyValueIterator::reference - \internal -*/ - -/*! \fn QKeyValueIterator() - - Constructs a default QKeyValueIterator. -*/ - -/*! \fn QKeyValueIterator(Iterator o) - - Constructs a QKeyValueIterator on top of \a o. -*/ - -/*! \fn const T &QKeyValueIterator::operator*() const - - Returns the current entry as a pair. -*/ - -/*! \fn bool QKeyValueIterator::operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) - - Returns \c true if \a rhs points to the same item as \a lhs otherwise returns - \c false. - - \sa operator!=() -*/ - -/*! \fn bool QKeyValueIterator::operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) const - - Returns \c true if \a rhs points to a different item than \a lhs otherwise - returns \c false. - - \sa operator==() -*/ - -/*! - \fn QKeyValueIterator &QKeyValueIterator::operator++() - - The prefix ++ operator (\c{++i}) advances the iterator to the - next item in the container and returns the iterator. - - \note Advancing the iterator past its container's end() constitutes - undefined behavior. - - \sa operator--() -*/ - -/*! \fn QKeyValueIterator QKeyValueIterator::operator++(int) - - \overload - - The postfix ++ operator (\c{i++}) advances the iterator to the - next item in the container and returns the iterator's prior value. - - \note Advancing the iterator past its container's end() constitutes - undefined behavior. -*/ - -/*! \fn QKeyValueIterator &QKeyValueIterator::operator--() - - The prefix -- operator (\c{--i}) backs the iterator up to the previous item - in the container and returns the iterator. - - \note Backing up an iterator to before its container's begin() constitutes - undefined behavior. - - \sa operator++() -*/ - -/*! \fn QKeyValueIterator QKeyValueIterator::operator--(int) - - \overload - - The postfix -- operator (\c{i--}) backs the iterator up to the previous item - in the container and returns the iterator's prior value. - - \note Backing up an iterator to before its container's begin() constitutes - undefined behavior. -*/ - -/*! \fn Iterator QKeyValueIterator::base() const - Returns the underlying iterator this QKeyValueIterator is based on. -*/ - QT_END_NAMESPACE #endif // QITERATOR_H diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc index 051d4896d9..77cc412602 100644 --- a/src/corelib/tools/qiterator.qdoc +++ b/src/corelib/tools/qiterator.qdoc @@ -1395,3 +1395,123 @@ \sa key(), value(), remove() */ + +/*! \class QKeyValueIterator + \inmodule QtCore + \since 5.10 + + \brief Iterator over the key/value pairs of an associative container. + + The QKeyValueIterator class provides an STL-style iterator for returning + key/value pairs from associative containers like QHash and QMap. It + supports the same API as the STL associative containers, i.e. getting a + key/value pair when iterating through the container. + + This will allow for better interoperability between QMap, QHash and friends + and STL-style algorithms. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. +*/ + +/*! \typedef QKeyValueIterator::iterator_category + \internal +*/ + +/*! \typedef QKeyValueIterator::difference_type + \internal +*/ + +/*! \typedef QKeyValueIterator::value_type + \internal +*/ + +/*! \typedef QKeyValueIterator::pointer + \internal +*/ + +/*! \typedef QKeyValueIterator::reference + \internal +*/ + +/*! \fn QKeyValueIterator::QKeyValueIterator() + + Constructs a default QKeyValueIterator. +*/ + +/*! \fn QKeyValueIterator::QKeyValueIterator(Iterator o) + + Constructs a QKeyValueIterator on top of \a o. +*/ + +/*! \fn const T &QKeyValueIterator::operator*() const + + Returns the current entry as a pair. +*/ + +/*! \fn bool QKeyValueIterator::operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) + + Returns \c true if \a rhs points to the same item as \a lhs otherwise returns + \c false. + + \sa operator!=() +*/ + +/*! \fn bool QKeyValueIterator::operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) const + + Returns \c true if \a rhs points to a different item than \a lhs otherwise + returns \c false. + + \sa operator==() +*/ + +/*! + \fn QKeyValueIterator &QKeyValueIterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the container and returns the iterator. + + \note Advancing the iterator past its container's end() constitutes + undefined behavior. + + \sa operator--() +*/ + +/*! \fn QKeyValueIterator QKeyValueIterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the container and returns the iterator's prior value. + + \note Advancing the iterator past its container's end() constitutes + undefined behavior. +*/ + +/*! \fn QKeyValueIterator &QKeyValueIterator::operator--() + + The prefix -- operator (\c{--i}) backs the iterator up to the previous item + in the container and returns the iterator. + + \note Backing up an iterator to before its container's begin() constitutes + undefined behavior. + + \sa operator++() +*/ + +/*! \fn QKeyValueIterator QKeyValueIterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) backs the iterator up to the previous item + in the container and returns the iterator's prior value. + + \note Backing up an iterator to before its container's begin() constitutes + undefined behavior. +*/ + +/*! \fn Iterator QKeyValueIterator::base() const + Returns the underlying iterator this QKeyValueIterator is based on. +*/ diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index ebda40bd8d..c85dcb4358 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -54,7 +54,9 @@ #include "qlocale.h" #include "qlocale_p.h" #include "qlocale_tools_p.h" +#if QT_CONFIG(datetimeparser) #include "qdatetimeparser_p.h" +#endif #include "qnamespace.h" #include "qdatetime.h" #include "qstringlist.h" @@ -2084,7 +2086,7 @@ QDateTime QLocale::toDateTime(const QString &string, FormatType format) const QTime QLocale::toTime(const QString &string, const QString &format) const { QTime time; -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(datetimeparser) QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); dt.setDefaultLocale(*this); if (dt.parseFormat(format)) @@ -2115,7 +2117,7 @@ QTime QLocale::toTime(const QString &string, const QString &format) const QDate QLocale::toDate(const QString &string, const QString &format) const { QDate date; -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(datetimeparser) QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); dt.setDefaultLocale(*this); if (dt.parseFormat(format)) @@ -2145,7 +2147,7 @@ QDate QLocale::toDate(const QString &string, const QString &format) const #ifndef QT_NO_DATESTRING QDateTime QLocale::toDateTime(const QString &string, const QString &format) const { -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(datetimeparser) QTime time; QDate date; diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp index 5dd9591bc6..40a1193622 100644 --- a/src/corelib/tools/qmessageauthenticationcode.cpp +++ b/src/corelib/tools/qmessageauthenticationcode.cpp @@ -99,16 +99,16 @@ static int qt_hash_block_size(QCryptographicHash::Algorithm method) return SHA384_Message_Block_Size; case QCryptographicHash::Sha512: return SHA512_Message_Block_Size; - case QCryptographicHash::Sha3_224: + case QCryptographicHash::RealSha3_224: case QCryptographicHash::Keccak_224: return 144; - case QCryptographicHash::Sha3_256: + case QCryptographicHash::RealSha3_256: case QCryptographicHash::Keccak_256: return 136; - case QCryptographicHash::Sha3_384: + case QCryptographicHash::RealSha3_384: case QCryptographicHash::Keccak_384: return 104; - case QCryptographicHash::Sha3_512: + case QCryptographicHash::RealSha3_512: case QCryptographicHash::Keccak_512: return 72; } diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 895b6b9701..40d6c8b7c3 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE \brief The QRect class defines a rectangle in the plane using integer precision. - A rectangle is normally expressed as an upper-left corner and a + A rectangle is normally expressed as a top-left corner and a size. The size (width and height) of a QRect is always equivalent to the mathematical rectangle that forms the basis for its rendering. @@ -1317,7 +1317,7 @@ QDebug operator<<(QDebug dbg, const QRect &r) \brief The QRectF class defines a rectangle in the plane using floating point precision. - A rectangle is normally expressed as an upper-left corner and a + A rectangle is normally expressed as a top-left corner and a size. The size (width and height) of a QRectF is always equivalent to the mathematical rectangle that forms the basis for its rendering. diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 08b38a08c2..7ded120ab7 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -340,13 +340,14 @@ Q_INLINE_TEMPLATE bool QSet<T>::intersects(const QSet<T> &other) const template <class T> Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other) { - QSet<T> copy1(*this); - QSet<T> copy2(other); - typename QSet<T>::const_iterator i = copy1.constEnd(); - while (i != copy1.constBegin()) { - --i; - if (copy2.contains(*i)) + if (&other == this) { + clear(); + } else { + auto i = other.constEnd(); + while (i != other.constBegin()) { + --i; remove(*i); + } } return *this; } diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index eeeff280ff..1f83eb2865 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -165,28 +165,37 @@ qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW qssize_t result = 0; #ifdef __SSE2__ - // progress until we get an aligned pointer - const ushort *ptr = str; - while (*ptr && quintptr(ptr) % 16) - ++ptr; - if (*ptr == 0) - return ptr - str; + // find the 16-byte alignment immediately prior or equal to str + quintptr misalignment = quintptr(str) & 0xf; + Q_ASSERT((misalignment & 1) == 0); + const ushort *ptr = str - (misalignment / 2); // load 16 bytes and see if we have a null // (aligned loads can never segfault) - int mask; const __m128i zeroes = _mm_setzero_si128(); + __m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr)); + __m128i comparison = _mm_cmpeq_epi16(data, zeroes); + quint32 mask = _mm_movemask_epi8(comparison); + + // ignore the result prior to the beginning of str + mask >>= misalignment; + + // Have we found something in the first block? Need to handle it now + // because of the left shift above. + if (mask) + return qCountTrailingZeroBits(quint32(mask)) / 2; + do { - __m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr)); ptr += 8; + data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr)); - __m128i comparison = _mm_cmpeq_epi16(data, zeroes); + comparison = _mm_cmpeq_epi16(data, zeroes); mask = _mm_movemask_epi8(comparison); } while (mask == 0); // found a null uint idx = qCountTrailingZeroBits(quint32(mask)); - return ptr - str - 8 + idx / 2; + return ptr - str + idx / 2; #endif if (sizeof(wchar_t) == sizeof(ushort)) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 1eca773c3e..6dd934263d 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -414,25 +414,25 @@ public: # define Q_REQUIRED_RESULT # define Q_REQUIRED_RESULT_pushed # endif - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString toLower() const & + Q_REQUIRED_RESULT QString toLower() const & { return toLower_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString toLower() && + Q_REQUIRED_RESULT QString toLower() && { return toLower_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString toUpper() const & + Q_REQUIRED_RESULT QString toUpper() const & { return toUpper_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString toUpper() && + Q_REQUIRED_RESULT QString toUpper() && { return toUpper_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString toCaseFolded() const & + Q_REQUIRED_RESULT QString toCaseFolded() const & { return toCaseFolded_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString toCaseFolded() && + Q_REQUIRED_RESULT QString toCaseFolded() && { return toCaseFolded_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString trimmed() const & + Q_REQUIRED_RESULT QString trimmed() const & { return trimmed_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString trimmed() && + Q_REQUIRED_RESULT QString trimmed() && { return trimmed_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString simplified() const & + Q_REQUIRED_RESULT QString simplified() const & { return simplified_helper(*this); } - Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString simplified() && + Q_REQUIRED_RESULT QString simplified() && { return simplified_helper(*this); } # ifdef Q_REQUIRED_RESULT_pushed # pragma pop_macro("Q_REQUIRED_RESULT") diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index d65563f76d..17f6bd8539 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -681,7 +681,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int \overload \since 5.0 - Returns the index position of the first match of \a re in + Returns the index position of the first exact match of \a re in the list, searching forward from index position \a from. Returns -1 if no item matched. diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index 876dc2d877..fa0dd87cfc 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -295,7 +295,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSec break; } if (prevSecs < endSecs) // i.e. we did make it into that while loop - return data(qint64(prevSecs) * 1000); + return data(qint64(prevSecs * 1e3)); // No transition data; or first transition later than requested time. return invalidData(); diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 521475c2dd..bcc1285472 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -272,8 +272,9 @@ static void parseTzLeapSeconds(QDataStream &ds, int tzh_leapcnt, bool longTran) { // Parse tzh_leapcnt x pairs of leap seconds // We don't use leap seconds, so only read and don't store - qint64 val; + qint32 val; if (longTran) { + // v2 file format, each entry is 12 bytes long qint64 time; for (int i = 0; i < tzh_leapcnt && ds.status() == QDataStream::Ok; ++i) { // Parse Leap Occurrence Time, 8 bytes @@ -283,6 +284,7 @@ static void parseTzLeapSeconds(QDataStream &ds, int tzh_leapcnt, bool longTran) ds >> val; } } else { + // v0 file format, each entry is 8 bytes long for (int i = 0; i < tzh_leapcnt && ds.status() == QDataStream::Ok; ++i) { // Parse Leap Occurrence Time, 4 bytes ds >> val; diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index aa545497a2..2c609098ea 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -21,7 +21,6 @@ HEADERS += \ tools/qcryptographichash.h \ tools/qdatetime.h \ tools/qdatetime_p.h \ - tools/qdatetimeparser_p.h \ tools/qdoublescanprint_p.h \ tools/qeasingcurve.h \ tools/qfreelist_p.h \ @@ -84,7 +83,6 @@ SOURCES += \ tools/qcollator.cpp \ tools/qcryptographichash.cpp \ tools/qdatetime.cpp \ - tools/qdatetimeparser.cpp \ tools/qeasingcurve.cpp \ tools/qfreelist.cpp \ tools/qhash.cpp \ @@ -173,6 +171,11 @@ qtConfig(timezone) { SOURCES += tools/qtimezoneprivate_icu.cpp } +qtConfig(datetimeparser) { + HEADERS += tools/qdatetimeparser_p.h + SOURCES += tools/qdatetimeparser.cpp +} + qtConfig(regularexpression) { QMAKE_USE_PRIVATE += pcre2 |