diff options
author | Liang Qi <liang.qi@qt.io> | 2016-06-13 09:01:02 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-06-13 12:46:46 +0200 |
commit | 511790fd1af1e2886a0e2e8dd4308099705cd815 (patch) | |
tree | b42aee537a6103cd064f9f41ae2889b09b79fd23 /src/corelib | |
parent | 1542d8881fc5ccbc5918cd4acbe4091ebbd24508 (diff) | |
parent | cbe332405aa22257d432f1797b325f5e57007c20 (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
config_help.txt
configure
mkspecs/features/uikit/sdk.prf
src/corelib/global/qhooks.cpp
src/corelib/io/qfilesystemwatcher.cpp
src/corelib/io/qlockfile_unix.cpp
src/corelib/tools/qalgorithms.h
src/gui/kernel/qwindowsysteminterface.h
src/gui/text/qtextdocument_p.cpp
src/network/access/access.pri
src/network/access/qnetworkaccessmanager.cpp
src/network/access/qnetworkreplynsurlconnectionimpl.mm
src/src.pro
src/testlib/qtestcase.cpp
src/widgets/kernel/qwidgetbackingstore_p.h
src/widgets/styles/qwindowscestyle.cpp
src/widgets/styles/qwindowsmobilestyle.cpp
tests/auto/corelib/io/qdiriterator/qdiriterator.pro
tests/auto/corelib/io/qfileinfo/qfileinfo.pro
tests/auto/gui/kernel/qwindow/BLACKLIST
tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
tools/configure/configureapp.cpp
Change-Id: Ibf7fb9c8cf263a810ade82f821345d0725c57c67
Diffstat (limited to 'src/corelib')
46 files changed, 545 insertions, 732 deletions
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index a5ed8b2ea3..f492148a50 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -46,6 +46,21 @@ if (NOT TARGET Qt5::rcc) ) endif() +if (NOT TARGET Qt5::qdoc) + add_executable(Qt5::qdoc IMPORTED) + +!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE) + set(imported_location \"${_qt5Core_install_prefix}/$${CMAKE_BIN_DIR}qdoc$$CMAKE_BIN_SUFFIX\") +!!ELSE + set(imported_location \"$${CMAKE_BIN_DIR}qdoc$$CMAKE_BIN_SUFFIX\") +!!ENDIF + _qt5_Core_check_file_exists(${imported_location}) + + set_target_properties(Qt5::qdoc PROPERTIES + IMPORTED_LOCATION ${imported_location} + ) +endif() + set(Qt5Core_QMAKE_EXECUTABLE Qt5::qmake) set(Qt5Core_MOC_EXECUTABLE Qt5::moc) set(Qt5Core_RCC_EXECUTABLE Qt5::rcc) diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index a783bcc31e..7117092c54 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -54,15 +54,13 @@ QT_BEGIN_NAMESPACE \class QVariantAnimation \inmodule QtCore \ingroup animation - \brief The QVariantAnimation class provides an abstract base class for animations. + \brief The QVariantAnimation class provides a base class for animations. \since 4.6 This class is part of \l{The Animation Framework}. It serves as a base class for property and item animations, with functions for shared functionality. - QVariantAnimation cannot be used directly as it is an abstract - class; it has a pure virtual method called updateCurrentValue(). The class performs interpolation over \l{QVariant}s, but leaves using the interpolated values to its subclasses. Currently, Qt provides QPropertyAnimation, which @@ -75,7 +73,7 @@ QT_BEGIN_NAMESPACE start the animation. QVariantAnimation will interpolate the property of the target object and emit valueChanged(). To react to a change in the current value you have to reimplement the - updateCurrentValue() virtual function. + updateCurrentValue() virtual function or connect to said signal. It is also possible to set values at specified steps situated between the start and end value. The interpolation will then diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc index 02eb5a97c6..4e71ed4268 100644 --- a/src/corelib/doc/src/animation.qdoc +++ b/src/corelib/doc/src/animation.qdoc @@ -118,11 +118,12 @@ \section1 Animating Qt Properties - As mentioned in the previous section, the QPropertyAnimation class - can interpolate over Qt properties. It is this class that should - be used for animation of values; in fact, its superclass, - QVariantAnimation, is an abstract class, and cannot be used - directly. + As mentioned in the previous section, the QPropertyAnimation class can + interpolate over Qt properties. It is often this class that should be used + for animation of values; in fact, its superclass, QVariantAnimation, has an + empty implementation of \l{QAbstractAnimation::}{updateCurrentValue()}, and + does not change any value unless we change it ourselves on the + \l{QVariantAnimation::valueChanged()}{valueChanged signal}. A major reason we chose to animate Qt properties is that it presents us with freedom to animate already existing classes in diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index dd846955f6..6a8948822c 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -28,8 +28,9 @@ SOURCES += \ global/qmalloc.cpp \ global/qnumeric.cpp \ global/qlogging.cpp \ - global/qhooks.cpp \ - global/qversiontagging.cpp + global/qhooks.cpp + +VERSIONTAGGING_SOURCES = global/qversiontagging.cpp # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global @@ -63,3 +64,21 @@ journald { syslog { DEFINES += QT_USE_SYSLOG } + +gcc:ltcg { + versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH) + + # Disable LTO, as the symbols disappear somehow under GCC + versiontagging_compiler.commands += -fno-lto + + versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} + versiontagging_compiler.dependency_type = TYPE_C + versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + versiontagging_compiler.input = VERSIONTAGGING_SOURCES + versiontagging_compiler.variable_out = OBJECTS + versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN} + silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands + QMAKE_EXTRA_COMPILERS += versiontagging_compiler +} else { + SOURCES += $$VERSIONTAGGING_SOURCES +} diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 1ebf37d610..c5424be035 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -748,7 +748,9 @@ # define Q_COMPILER_TEMPLATE_ALIAS # endif # if __has_feature(cxx_thread_local) -# define Q_COMPILER_THREAD_LOCAL +# if !defined(__FreeBSD__) /* FreeBSD clang fails on __cxa_thread_atexit */ +# define Q_COMPILER_THREAD_LOCAL +# endif # endif # if __has_feature(cxx_user_literals) # define Q_COMPILER_UDL @@ -1108,7 +1110,8 @@ # define Q_DECL_NOTHROW Q_DECL_NOEXCEPT #endif -#if defined(Q_COMPILER_ALIGNOF) && !defined(Q_ALIGNOF) +#if defined(Q_COMPILER_ALIGNOF) +# undef Q_ALIGNOF # define Q_ALIGNOF(x) alignof(x) #endif diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index c5ff82c10a..34bb015a2f 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -49,6 +49,11 @@ QT_BEGIN_NAMESPACE +#ifdef __has_builtin +# define QT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define QT_HAS_BUILTIN(x) 0 +#endif /* * ENDIAN FUNCTIONS @@ -71,18 +76,29 @@ template <typename T> inline void qbswap(const T src, uchar *dest) // Used to implement a type-safe and alignment-safe copy operation // If you want to avoid the memcpy, you must write specializations for these functions -template <typename T> inline void qToUnaligned(const T src, uchar *dest) +template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, uchar *dest) { // Using sizeof(T) inside memcpy function produces internal compiler error with // MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T. const size_t size = sizeof(T); - memcpy(dest, &src, size); +#if QT_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy +#else + memcpy +#endif + (dest, &src, size); } -template <typename T> inline T qFromUnaligned(const uchar *src) + +template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const uchar *src) { T dest; const size_t size = sizeof(T); - memcpy(&dest, src, size); +#if QT_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy +#else + memcpy +#endif + (&dest, src, size); return dest; } diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc index 63d924211f..3b22dcec87 100644 --- a/src/corelib/global/qendian.qdoc +++ b/src/corelib/global/qendian.qdoc @@ -34,6 +34,29 @@ */ /*! + \internal + \fn T qFromUnaligned(const uchar *ptr) + \since 5.5 + + Loads a \c{T} from address \a ptr, which may be misaligned. + + Use of this function avoids the undefined behavior that the C++ standard + otherwise attributes to unaligned loads. +*/ + +/*! + \internal + \fn void qToUnaligned(T t, uchar *ptr) + \since 4.5 + + Stores \a t to address \a ptr, which may be misaligned. + + Use of this function avoids the undefined behavior that the C++ standard + otherwise attributes to unaligned stores. +*/ + + +/*! \fn T qFromBigEndian(const uchar *src) \since 4.3 \relates <QtEndian> diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp index 2ec1714cd2..7b9a3db30d 100644 --- a/src/corelib/global/qhooks.cpp +++ b/src/corelib/global/qhooks.cpp @@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = { // The required sizes and offsets are tested in tests/auto/other/toolsupport. // When this fails and the change was intentional, adjust the test and // adjust this value here. - 14 + 15 }; Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0])); diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 10f9068d0a..ccf5851d18 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -66,6 +66,7 @@ NETBSD - NetBSD OPENBSD - OpenBSD BSDI - BSD/OS + INTERIX - Interix IRIX - SGI Irix OSF - HP Tru64 UNIX SCO - SCO OpenServer 5 @@ -172,6 +173,9 @@ #elif defined(__bsdi__) # define Q_OS_BSDI # define Q_OS_BSD4 +#elif defined(__INTERIX) +# define Q_OS_INTERIX +# define Q_OS_BSD4 #elif defined(__sgi) # define Q_OS_IRIX #elif defined(__osf__) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index eb9471b502..ab345e9aae 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -144,7 +144,6 @@ win32 { !nacl:mac: { SOURCES += io/qsettings_mac.cpp } - freebsd: LIBS_PRIVATE += -lutil # qlockfile_unix.cpp requires this mac { SOURCES += io/qstorageinfo_mac.cpp OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 0d9fdb3453..fa919e9f10 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -166,16 +166,15 @@ void QDebug::putUcs4(uint ucs4) { maybeQuote('\''); if (ucs4 < 0x20) { - stream->ts << hex << "\\x" << ucs4 << reset; + stream->ts << "\\x" << hex << ucs4 << reset; } else if (ucs4 < 0x80) { stream->ts << char(ucs4); } else { - stream->ts << hex << qSetPadChar(QLatin1Char('0')); if (ucs4 < 0x10000) - stream->ts << qSetFieldWidth(4) << "\\u"; + stream->ts << "\\u" << qSetFieldWidth(4); else - stream->ts << qSetFieldWidth(8) << "\\U"; - stream->ts << ucs4 << reset; + stream->ts << "\\U" << qSetFieldWidth(8); + stream->ts << hex << qSetPadChar(QLatin1Char('0')) << ucs4 << reset; } maybeQuote('\''); } diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 76b56f4699..6366c5120c 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -820,7 +820,7 @@ QString QFileInfo::completeBaseName() const } /*! - Returns the complete suffix of the file. + Returns the complete suffix (extension) of the file. The complete suffix consists of all characters in the file after (but not including) the first '.'. @@ -839,7 +839,7 @@ QString QFileInfo::completeSuffix() const } /*! - Returns the suffix of the file. + Returns the suffix (extension) of the file. The suffix consists of all characters in the file after (but not including) the last '.'. diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 1e22252217..55f4bddd17 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -58,7 +58,7 @@ # include "qfilesystemwatcher_win_p.h" #elif defined(USE_INOTIFY) # include "qfilesystemwatcher_inotify_p.h" -#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(QT_PLATFORM_UIKIT) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT) # include "qfilesystemwatcher_kqueue_p.h" #elif defined(Q_OS_OSX) # include "qfilesystemwatcher_fsevents_p.h" @@ -74,7 +74,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject // there is a chance that inotify may fail on Linux pre-2.6.13 (August // 2005), so we can't just new inotify directly. return QInotifyFileSystemWatcherEngine::create(parent); -#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(QT_PLATFORM_UIKIT) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT) return QKqueueFileSystemWatcherEngine::create(parent); #elif defined(Q_OS_OSX) return QFseventsFileSystemWatcherEngine::create(parent); diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 264973d556..4f6c83ebcf 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -172,7 +172,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths QStringList *files, QStringList *directories) { - bool isEmpty; QStringList p = paths; if (pathToID.isEmpty()) return p; @@ -193,7 +192,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths else files->removeAll(path); } - isEmpty = pathToID.isEmpty(); return p; } diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index ba59ea8341..79141d1e8f 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -71,14 +71,12 @@ #elif defined(Q_OS_HAIKU) # include <kernel/OS.h> #elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT) +# if !defined(Q_OS_NETBSD) # include <sys/user.h> -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) +# endif # include <sys/cdefs.h> # include <sys/param.h> # include <sys/sysctl.h> -# else -# include <libutil.h> -# endif #endif QT_BEGIN_NAMESPACE @@ -286,30 +284,33 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) return QString(); return QFile::decodeName(info.name); #elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT) -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - size_t len = 0; - if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) - return QString(); - kinfo_proc *proc = static_cast<kinfo_proc *>(malloc(len)); +# if defined(Q_OS_NETBSD) + struct kinfo_proc2 kp; + int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc2), 1 }; +# elif defined(Q_OS_OPENBSD) + struct kinfo_proc kp; + int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc), 1 }; # else - kinfo_proc *proc = kinfo_getproc(pid); + struct kinfo_proc kp; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid }; # endif - if (!proc) + size_t len = sizeof(kp); + u_int mib_len = sizeof(mib)/sizeof(u_int); + + if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0) return QString(); -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) - if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) { - free(proc); + +# if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) + if (kp.p_pid != pid) return QString(); - } - if (proc->ki_pid != pid) { - free(proc); + QString name = QFile::decodeName(kp.p_comm); +# else + if (kp.ki_pid != pid) return QString(); - } + QString name = QFile::decodeName(kp.ki_comm); # endif - QString name = QFile::decodeName(proc->ki_comm); - free(proc); return name; + #else Q_UNUSED(pid); return QString(); diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index ba4a091965..baaff8da17 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -143,9 +143,11 @@ bool QLockFilePrivate::isApparentlyStale() const if (!procHandle) return true; // We got a handle but check if process is still alive - DWORD dwR = ::WaitForSingleObject(procHandle, 0); + DWORD exitCode = 0; + if (!::GetExitCodeProcess(procHandle, &exitCode)) + exitCode = 0; ::CloseHandle(procHandle); - if (dwR == WAIT_TIMEOUT) + if (exitCode != STILL_ACTIVE) return true; const QString processName = processNameByPid(pid); if (!processName.isEmpty() && processName != appname) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 227241b208..ebafd6b524 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2087,10 +2087,7 @@ void QProcess::start(const QString &program, const QStringList &arguments, OpenM return; } if (program.isEmpty()) { - Q_D(QProcess); - d->processError = QProcess::FailedToStart; - setErrorString(tr("No program defined")); - emit error(d->processError); + d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); return; } @@ -2117,10 +2114,7 @@ void QProcess::start(OpenMode mode) return; } if (d->program.isEmpty()) { - Q_D(QProcess); - d->processError = QProcess::FailedToStart; - setErrorString(tr("No program defined")); - emit error(d->processError); + d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); return; } diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 3a9f74bf59..0daf041954 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -84,7 +84,7 @@ # if !defined(ST_RDONLY) # define ST_RDONLY MNT_RDONLY # endif -# if !defined(_STATFS_F_FLAGS) +# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD) # define _STATFS_F_FLAGS 1 # endif #elif defined(Q_OS_ANDROID) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 64c9692e23..3ab2c70c75 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -205,6 +205,8 @@ bool QWindowsPipeWriter::write(const QByteArray &ba) void QWindowsPipeWriter::stop() { stopped = true; + bytesWrittenPending = false; + pendingBytesWrittenValue = 0; if (writeSequenceStarted) { if (!CancelIoEx(handle, &overlapped)) { const DWORD dwError = GetLastError(); diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index d16b6e5b00..f2fcb767d5 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -410,7 +410,7 @@ public: // pack with itself, we'll discard the high part anyway chunk = _mm_packus_epi16(chunk, chunk); // unaligned 64-bit store - qUnalignedStore(l + i, _mm_cvtsi128_si64(chunk)); + qToUnaligned(_mm_cvtsi128_si64(chunk), l + i); i += 8; } # endif @@ -684,6 +684,8 @@ public: bool operator >=(const Entry &other) const; }; +inline bool operator!=(const Entry &lhs, const Entry &rhs) { return !(lhs == rhs); } + inline bool Entry::operator >=(const QString &key) const { if (value.latinKey) diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index b5b6f36bc6..fb651f0f24 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -599,8 +599,8 @@ bool QJsonObject::operator==(const QJsonObject &other) const for (uint i = 0; i < o->length; ++i) { QJsonPrivate::Entry *e = o->entryAt(i); - QJsonValue v(d, o, e->value); - if (other.value(e->key()) != v) + QJsonPrivate::Entry *oe = other.o->entryAt(i); + if (*e != *oe || QJsonValue(d, o, e->value) != QJsonValue(other.d, other.o, oe->value)) return false; } diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index b21f59ae35..718dfa43b3 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -275,25 +275,11 @@ QJsonValue::QJsonValue(const QJsonValue &other) */ QJsonValue &QJsonValue::operator =(const QJsonValue &other) { - if (t == String && stringData && !stringData->ref.deref()) - free(stringData); - - t = other.t; - dbl = other.dbl; - - if (d != other.d) { - - if (d && !d->ref.deref()) - delete d; - d = other.d; - if (d) - d->ref.ref(); - - } - - if (t == String && stringData) - stringData->ref.ref(); - + QJsonValue copy(other); + // swap(copy); + qSwap(dbl, copy.dbl); + qSwap(d, copy.d); + qSwap(t, copy.t); return *this; } diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 93af957d95..2042964427 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -41,16 +41,6 @@ #include "qcore_unix_p.h" #include "qelapsedtimer.h" -#ifdef Q_OS_NACL -#elif !defined (Q_OS_VXWORKS) -# if !defined(Q_OS_HPUX) || defined(__ia64) -# include <sys/select.h> -# endif -# include <sys/time.h> -#else -# include <selectLib.h> -#endif - #include <stdlib.h> #ifdef Q_OS_MAC diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index b08571223f..6ed316254b 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -65,6 +65,16 @@ #include <sys/stat.h> #include <unistd.h> +#ifdef Q_OS_NACL +#elif !defined (Q_OS_VXWORKS) +# if !defined(Q_OS_HPUX) || defined(__ia64) +# include <sys/select.h> +# endif +# include <sys/time.h> +#else +# include <selectLib.h> +#endif + #include <sys/wait.h> #include <errno.h> #include <fcntl.h> diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 9b421d6a78..ffb50ddac3 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4699,7 +4699,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection) { + if (type & Qt::UniqueConnection && slot) { QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (connectionLists && connectionLists->count() > signal_index) { const QObjectPrivate::Connection *c2 = diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 87d006bdc6..3cec9802dc 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -302,7 +302,6 @@ public: connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { -#if defined (Q_COMPILER_VARIADIC_TEMPLATES) typedef QtPrivate::FunctionPointer<Func1> SignalType; const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value; @@ -310,28 +309,6 @@ public: "Signal and slot arguments are not compatible."); const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0; typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType; -#else - // Without variadic template, we don't detect the best overload of operator(). We just - // assume there is only one simple operator() and connect to &Func2::operator() - - /* If you get an error such as: - couldn't deduce template parameter 'Func2Operator' - or - cannot resolve address of overloaded function - It means the functor does not have a single operator(). - Functors with overloaded or templated operator() are only supported if the compiler supports - C++11 variadic templates - */ - typedef QtPrivate::FunctionPointer<decltype(&Func2::operator())> SlotType ; - typedef QtPrivate::FunctionPointer<Func1> SignalType; - typedef typename SlotType::ReturnType SlotReturnType; - const int SlotArgumentCount = SlotType::ArgumentCount; - - Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= SlotArgumentCount, - "The slot requires more arguments than the signal provides."); - Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value), - "Signal and slot arguments are not compatible."); -#endif Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value), "Return type of the slot is not compatible with the return type of the signal."); @@ -446,8 +423,7 @@ protected: QScopedPointer<QObjectData> d_ptr; static const QMetaObject staticQtMetaObject; - friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT - { return &staticQtMetaObject; } + friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT; friend struct QMetaObject; friend struct QMetaObjectPrivate; @@ -478,6 +454,9 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch const char *amember, Qt::ConnectionType atype) const { return connect(asender, asignal, this, amember, atype); } +inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT +{ return &QObject::staticQtMetaObject; } + #ifndef QT_NO_USERDATA class Q_CORE_EXPORT QObjectUserData { public: diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index b4091a4f1c..d7ae63a98c 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -62,34 +62,6 @@ namespace QtPrivate { If one of the type is not declared, the function return 0 and the signal cannot be used in queued connection. */ -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template <typename ArgList> struct TypesAreDeclaredMetaType { enum { Value = false }; }; - template <> struct TypesAreDeclaredMetaType<void> { enum { Value = true }; }; - template <typename Arg, typename Tail> struct TypesAreDeclaredMetaType<List<Arg, Tail> > { enum { Value = QMetaTypeId2<Arg>::Defined && TypesAreDeclaredMetaType<Tail>::Value }; }; - - template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes - { static const int *types() { return 0; } }; - template <> struct ConnectionTypes<void, true> - { static const int *types() { static const int t[1] = { 0 }; return t; } }; - template <typename Arg1> struct ConnectionTypes<List<Arg1, void>, true> - { static const int *types() { static const int t[2] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), 0 }; return t; } }; - template <typename Arg1, typename Arg2> struct ConnectionTypes<List<Arg1, List<Arg2, void> >, true> - { static const int *types() { static const int t[3] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), 0 }; return t; } }; - template <typename Arg1, typename Arg2, typename Arg3> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, void> > >, true> - { static const int *types() { static const int t[4] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), 0 }; return t; } }; - template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > >, true> - { static const int *types() { static const int t[5] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg4>::qt_metatype_id(), 0 }; return t; } }; - template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > >, true> - { static const int *types() { static const int t[6] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg4>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg5>::qt_metatype_id(), 0 }; return t; } }; - template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> - struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > >, true> - { static const int *types() { static const int t[7] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg4>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg5>::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper<Arg6>::qt_metatype_id(), 0 }; return t; } }; -#else template <typename ArgList> struct TypesAreDeclaredMetaType { enum { Value = false }; }; template <> struct TypesAreDeclaredMetaType<List<>> { enum { Value = true }; }; template <typename Arg, typename... Tail> struct TypesAreDeclaredMetaType<List<Arg, Tail...> > @@ -101,7 +73,6 @@ namespace QtPrivate { { static const int *types() { return Q_NULLPTR; } }; template <typename... Args> struct ConnectionTypes<List<Args...>, true> { static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } }; -#endif // internal base class (interface) containing functions required to call a slot managed by a pointer to function. class QSlotObjectBase { diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 6ef83a6eb5..5eae70ecc5 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -65,11 +65,6 @@ namespace QtPrivate { List_Left<L,N> take a list and a number as a parameter and returns (via the Value typedef, the list composed of the first N element of the list */ -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template <typename Head, typename Tail> struct List { typedef Head Car; typedef Tail Cdr; }; - template <typename L, int N> struct List_Left { typedef List<typename L::Car, typename List_Left<typename L::Cdr, N - 1>::Value > Value; }; - template <typename L> struct List_Left<L,0> { typedef void Value; }; -#else // With variadic template, lists are represented using a variadic template argument instead of the lisp way template <typename...> struct List {}; template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; }; @@ -79,7 +74,6 @@ namespace QtPrivate { typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value; }; template <typename L> struct List_Left<L, 0> { typedef List<> Value; }; -#endif // List_Select<L,N> returns (via typedef Value) the Nth element of the list L template <typename L, int N> struct List_Select { typedef typename List_Select<typename L::Cdr, N - 1>::Value Value; }; template <typename L> struct List_Select<L,0> { typedef typename L::Car Value; }; @@ -100,13 +94,11 @@ namespace QtPrivate { if (container.data) *reinterpret_cast<U*>(container.data) = value; } -#ifdef Q_COMPILER_RVALUE_REFS template<typename T, typename U> void operator,(T &&value, const ApplyReturnValue<U> &container) { if (container.data) *reinterpret_cast<U*>(container.data) = value; } -#endif template<typename T> void operator,(T, const ApplyReturnValue<void> &) {} @@ -127,364 +119,6 @@ namespace QtPrivate { The Functor<Func,N> struct is the helper to call a functor of N argument. its call function is the same as the FunctionPointer::call function. */ -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; }; - //Pointers to member functions - template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) ()> - { - typedef Obj Object; - typedef void Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (); - enum {ArgumentCount = 0, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); } - }; - template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1)> - { - typedef Obj Object; - typedef List<Arg1, void> Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1); - enum {ArgumentCount = 1, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, void> > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2); - enum {ArgumentCount = 2, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3); - enum {ArgumentCount = 3, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> - struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]); - } - }; - - //Pointers to const member functions - template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) () const> - { - typedef Obj Object; - typedef void Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) () const; - enum {ArgumentCount = 0, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); } - }; - template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1) const> - { - typedef Obj Object; - typedef List<Arg1, void> Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1) const; - enum {ArgumentCount = 1, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2) const> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, void> > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2) const; - enum {ArgumentCount = 2, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3) const> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const; - enum {ArgumentCount = 3, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4) const> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const; - enum {ArgumentCount = 4, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5) const> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const; - enum {ArgumentCount = 5, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> - struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const; - enum {ArgumentCount = 6, IsPointerToMemberFunction = true}; - template <typename Args, typename R> - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]); - } - }; - - //Static functions - template<typename Ret> struct FunctionPointer<Ret (*) ()> - { - typedef void Arguments; - typedef Ret (*Function) (); - typedef Ret ReturnType; - enum {ArgumentCount = 0, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); } - }; - template<typename Ret, typename Arg1> struct FunctionPointer<Ret (*) (Arg1)> - { - typedef List<Arg1, void> Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1); - enum {ArgumentCount = 1, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) - { f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]); } - }; - template<typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (*) (Arg1, Arg2)> - { - typedef List<Arg1, List<Arg2, void> > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2); - enum {ArgumentCount = 2, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) { - f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); } - }; - template<typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3)> - { - typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3); - enum {ArgumentCount = 3, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4)> - { - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5)> - { - typedef List<Arg1, List<Arg2, List<Arg3, - List<Arg4, List<Arg5, void > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> - { - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6, IsPointerToMemberFunction = false}; - template <typename Args, typename R> - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]); - } - }; - - //Functors - template<typename F, int N> struct Functor; - template<typename Function> struct Functor<Function, 0> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); } - }; - template<typename Function> struct Functor<Function, 1> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { - f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 2> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 3> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 4> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 5> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 6> - { - template <typename Args, typename R> - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]); - } - }; -#else template <int...> struct IndexesList {}; template <typename IndexList, int Right> struct IndexesAppend; template <int... Left, int Right> struct IndexesAppend<IndexesList<Left...>, Right> @@ -558,7 +192,6 @@ namespace QtPrivate { FunctorCall<typename Indexes<N>::Value, SignalArgs, R, Function>::call(f, arg); } }; -#endif /* Logic that check if the arguments of the slot matches the argument of the signal. @@ -578,16 +211,6 @@ namespace QtPrivate { template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; }; template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; }; -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; - template <> struct CheckCompatibleArguments<void, void> { enum { value = true }; }; - template <typename List1> struct CheckCompatibleArguments<List1, void> { enum { value = true }; }; - template <typename Arg1, typename Arg2, typename Tail1, typename Tail2> struct CheckCompatibleArguments<List<Arg1, Tail1>, List<Arg2, Tail2> > - { - enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value - && CheckCompatibleArguments<Tail1, Tail2>::value }; - }; -#else template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; }; template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; }; @@ -597,9 +220,7 @@ namespace QtPrivate { enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value && CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value }; }; -#endif -#if defined(Q_COMPILER_VARIADIC_TEMPLATES) /* Find the maximum number of arguments a functor object can take and be still compatible with the arguments from the signal. @@ -631,8 +252,6 @@ namespace QtPrivate { template <typename D> static D dummy(); typedef decltype(dummy<Functor>().operator()((dummy<ArgList>())...)) Value; }; -#endif - } QT_END_NAMESPACE diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 0db3407b7b..8461bf7130 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -48,7 +48,6 @@ #include <QtCore/QList> #include <QtCore/QDebug> #include <qendian.h> -#include <private/qsimd_p.h> // for qUnalignedLoad QT_BEGIN_NAMESPACE @@ -164,7 +163,7 @@ bool QMimeMagicRule::matchNumber(const QByteArray &data) const const char *p = data.constData() + m_startPos; const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos + 1); for ( ; p <= e; ++p) { - if ((qUnalignedLoad<T>(p) & mask) == (value & mask)) + if ((qFromUnaligned<T>(reinterpret_cast<const uchar *>(p)) & mask) == (value & mask)) return true; } diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp index 25444ffff6..17072f44d4 100644 --- a/src/corelib/thread/qmutex_linux.cpp +++ b/src/corelib/thread/qmutex_linux.cpp @@ -57,7 +57,7 @@ #endif #ifndef FUTEX_PRIVATE_FLAG -# define FUTEX_PRIVATE_FLAG 128 +# define FUTEX_PRIVATE_FLAG 0 #endif diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 36f1997a6c..55af7256be 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -87,29 +88,20 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, if (!(options & RawData)) headerSize += (alignment - Q_ALIGNOF(QArrayData)); - // Allocate additional space if array is growing - if (options & Grow) { - - // Guard against integer overflow when multiplying. - if (capacity > std::numeric_limits<size_t>::max() / objectSize) - return 0; - - size_t alloc; - if (mul_overflow(objectSize, capacity, &alloc)) - return 0; - - // Make sure qAllocMore won't overflow qAllocMore. - if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize) - return 0; - - capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize); - } + if (headerSize > size_t(MaxAllocSize)) + return 0; + // Calculate the byte size + // allocSize = objectSize * capacity + headerSize, but checked for overflow + // plus padded to grow in size size_t allocSize; - if (mul_overflow(objectSize, capacity, &allocSize)) - return 0; - if (add_overflow(allocSize, headerSize, &allocSize)) - return 0; + if (options & Grow) { + auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize); + capacity = r.elementCount; + allocSize = r.size; + } else { + allocSize = qCalculateBlockSize(capacity, objectSize, headerSize); + } QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize)); if (header) { diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index 446e09b1c0..12e4687b3c 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -42,6 +42,7 @@ #include <qalgorithms.h> #include <qdatastream.h> #include <qdebug.h> +#include <qendian.h> #include <string.h> QT_BEGIN_NAMESPACE @@ -169,25 +170,6 @@ QBitArray::QBitArray(int size, bool value) Same as size(). */ -template <typename T> T qUnalignedLoad(const uchar *ptr) -{ - /* - * Testing with different compilers shows that they all optimize the memcpy - * call away and replace with direct loads whenever possible. On x86 and PPC, - * GCC does direct unaligned loads; on MIPS, it generates a pair of load-left - * and load-right instructions. ICC and Clang do the same on x86. This is both - * 32- and 64-bit. - * - * On ARM cores without unaligned loads, the compiler leaves a call to - * memcpy. - */ - - T u; - memcpy(&u, ptr, sizeof(u)); - return u; -} - - /*! If \a on is true, this function returns the number of 1-bits stored in the bit array; otherwise the number @@ -203,17 +185,17 @@ int QBitArray::count(bool on) const const quint8 *const end = reinterpret_cast<const quint8 *>(d.end()); while (bits + 7 <= end) { - quint64 v = qUnalignedLoad<quint64>(bits); + quint64 v = qFromUnaligned<quint64>(bits); bits += 8; numBits += int(qPopulationCount(v)); } if (bits + 3 <= end) { - quint32 v = qUnalignedLoad<quint32>(bits); + quint32 v = qFromUnaligned<quint32>(bits); bits += 4; numBits += int(qPopulationCount(v)); } if (bits + 1 < end) { - quint16 v = qUnalignedLoad<quint16>(bits); + quint16 v = qFromUnaligned<quint16>(bits); bits += 2; numBits += int(qPopulationCount(v)); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index a256b44b1f..266c2e9b57 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -46,6 +46,7 @@ #include "qlocale.h" #include "qlocale_p.h" #include "qlocale_tools_p.h" +#include "private/qnumeric_p.h" #include "qstringalgorithms_p.h" #include "qscopedpointer.h" #include "qbytearray_p.h" @@ -128,17 +129,104 @@ int qFindByteArray( const char *haystack0, int haystackLen, int from, const char *needle0, int needleLen); +/* + * This pair of functions is declared in qtools_p.h and is used by the Qt + * containers to allocate memory and grow the memory block during append + * operations. + * + * They take size_t parameters and return size_t so they will change sizes + * according to the pointer width. However, knowing Qt containers store the + * container size and element indexes in ints, these functions never return a + * size larger than INT_MAX. This is done by casting the element count and + * memory block size to int in several comparisons: the check for negative is + * very fast on most platforms as the code only needs to check the sign bit. + * + * These functions return SIZE_MAX on overflow, which can be passed to malloc() + * and will surely cause a NULL return (there's no way you can allocate a + * memory block the size of your entire VM space). + */ + +/*! + \internal + \since 5.7 -int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW + Returns the memory block size for a container containing \a elementCount + elements, each of \a elementSize bytes, plus a header of \a headerSize + bytes. That is, this function returns \c + {elementCount * elementSize + headerSize} + + but unlike the simple calculation, it checks for overflows during the + multiplication and the addition. + + Both \a elementCount and \a headerSize can be zero, but \a elementSize + cannot. + + This function returns SIZE_MAX (~0) on overflow or if the memory block size + would not fit an int. +*/ +size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW { - Q_ASSERT(alloc >= 0 && extra >= 0 && extra <= MaxAllocSize); - Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!"); + unsigned count = unsigned(elementCount); + unsigned size = unsigned(elementSize); + unsigned header = unsigned(headerSize); + Q_ASSERT(elementSize); + Q_ASSERT(size == elementSize); + Q_ASSERT(header == headerSize); + + if (Q_UNLIKELY(count != elementCount)) + return std::numeric_limits<size_t>::max(); + + unsigned bytes; + if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) || + Q_UNLIKELY(add_overflow(bytes, header, &bytes))) + return std::numeric_limits<size_t>::max(); + if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB + return std::numeric_limits<size_t>::max(); + + return bytes; +} + +/*! + \internal + \since 5.7 - unsigned nalloc = qNextPowerOfTwo(alloc + extra); + Returns the memory block size and the number of elements that will fit in + that block for a container containing \a elementCount elements, each of \a + elementSize bytes, plus a header of \a headerSize bytes. This function + assumes the container will grow and pre-allocates a growth factor. - Q_ASSERT(nalloc > unsigned(alloc + extra)); + Both \a elementCount and \a headerSize can be zero, but \a elementSize + cannot. + + This function returns SIZE_MAX (~0) on overflow or if the memory block size + would not fit an int. + + \note The memory block may contain up to \a elementSize - 1 bytes more than + needed. +*/ +CalculateGrowingBlockSizeResult +qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW +{ + CalculateGrowingBlockSizeResult result = { + std::numeric_limits<size_t>::max(),std::numeric_limits<size_t>::max() + }; + + unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize)); + if (int(bytes) < 0) // catches std::numeric_limits<size_t>::max() + return result; + + unsigned morebytes = qNextPowerOfTwo(bytes); + if (Q_UNLIKELY(int(morebytes) < 0)) { + // catches morebytes == 2GB + // grow by half the difference between bytes and morebytes + bytes += (morebytes - bytes) / 2; + } else { + bytes = morebytes; + } - return nalloc - extra; + result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize); + result.size = bytes; + return result; } /***************************************************************************** @@ -1618,12 +1706,16 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { + size_t blockSize; if (options & Data::Grow) { - if (alloc > MaxByteArraySize) - qBadAlloc(); - alloc = qAllocMore(alloc, sizeof(Data)); + auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); + blockSize = r.size; + alloc = uint(r.elementCount); + } else { + blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); } - Data *x = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc)); + + Data *x = static_cast<Data *>(::realloc(d, blockSize)); Q_CHECK_PTR(x); x->alloc = alloc; x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0; diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 3cb3606013..08f89d2f02 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -95,9 +95,29 @@ static SHA3Final * const sha3Final = Final; available on all platforms (MSVC 2008, for example), we #define them to the Qt equivalents. */ + +#ifdef uint64_t +#undef uint64_t +#endif + #define uint64_t QT_PREPEND_NAMESPACE(quint64) + +#ifdef uint32_t +#undef uint32_t +#endif + #define uint32_t QT_PREPEND_NAMESPACE(quint32) + +#ifdef uint8_t +#undef uint8_t +#endif + #define uint8_t QT_PREPEND_NAMESPACE(quint8) + +#ifdef int_least16_t +#undef int_least16_t +#endif + #define int_least16_t QT_PREPEND_NAMESPACE(qint16) // Header from rfc6234 with 1 modification: diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 02afacb861..2ebf7c7977 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2158,7 +2158,7 @@ static int qt_timezone() // number of seconds west of UTC. // - It also takes DST into account, so we need to adjust it to always // get the Standard Time offset. - return -t.tm_gmtoff + (t.tm_isdst ? SECS_PER_HOUR : 0L); + return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L); #elif defined(Q_OS_INTEGRITY) return 0; #else diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index cc8c08d5b1..9c9009d636 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -708,17 +708,18 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } const int sectionmaxsize = sectionMaxSize(sectionIndex); - QString sectiontext = text.mid(index, sectionmaxsize); - int sectiontextSize = sectiontext.size(); + QStringRef sectionTextRef = text.midRef(index, sectionmaxsize); + int sectiontextSize = sectionTextRef.size(); QDTPDEBUG << "sectionValue for" << sn.name() - << "with text" << text << "and st" << sectiontext + << "with text" << text << "and st" << sectionTextRef << text.midRef(index, sectionmaxsize) << index; int used = 0; switch (sn.type) { case AmPmSection: { + QString sectiontext = sectionTextRef.toString(); const int ampm = findAmPm(sectiontext, sectionIndex, &used); switch (ampm) { case AM: // sectiontext == AM @@ -750,6 +751,7 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde case DayOfWeekSectionShort: case DayOfWeekSectionLong: if (sn.count >= 3) { + QString sectiontext = sectionTextRef.toString(); if (sn.type == MonthSection) { int min = 1; const QDate minDate = getMinimum().date(); @@ -788,7 +790,7 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde int last = -1; used = -1; - QString digitsStr(sectiontext); + QStringRef digitsStr = sectionTextRef; for (int i = 0; i < sectiontextSize; ++i) { if (digitsStr.at(i).isSpace()) { sectiontextSize = i; @@ -809,7 +811,7 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } } if (ok && tmp <= absMax) { - QDTPDEBUG << sectiontext.leftRef(digits) << tmp << digits; + QDTPDEBUG << sectionTextRef.left(digits) << tmp << digits; last = tmp; used = digits; break; @@ -817,13 +819,13 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } if (last == -1) { - QChar first(sectiontext.at(0)); + QChar first(sectionTextRef.at(0)); if (separators.at(sectionIndex + 1).startsWith(first)) { used = 0; state = Intermediate; } else { state = Invalid; - QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok; + QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok; } } else { num += last; @@ -1565,7 +1567,7 @@ QString QDateTimeParser::SectionNode::format() const number that is within min and max. */ -bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index, +bool QDateTimeParser::potentialValue(const QStringRef &str, int min, int max, int index, const QDateTime ¤tValue, int insert) const { if (str.isEmpty()) { @@ -1592,8 +1594,7 @@ bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int i if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) { return true; } else if (insert >= 0) { - QString tmp = str; - tmp.insert(insert, QLatin1Char('0' + j)); + const QString tmp = str.left(insert) + QLatin1Char('0' + j) + str.mid(insert); if (potentialValue(tmp, min, max, index, currentValue, insert)) return true; } @@ -1603,7 +1604,7 @@ bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int i return false; } -bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const +bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QStringRef &text) const { Q_ASSERT(current >= getMinimum() && current <= getMaximum()); diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index 9689d88616..01a2f20802 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -214,9 +214,19 @@ public: QString *dayName = 0, int *used = 0) const; #endif AmPmFinder findAmPm(QString &str, int index, int *used = 0) const; - bool potentialValue(const QString &str, int min, int max, int index, + bool potentialValue(const QStringRef &str, int min, int max, int index, const QDateTime ¤tValue, int insert) const; - bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const; + bool potentialValue(const QString &str, int min, int max, int index, + const QDateTime ¤tValue, int insert) const + { + return potentialValue(QStringRef(&str), min, max, index, currentValue, insert); + } + + bool skipToNextSection(int section, const QDateTime ¤t, const QStringRef §ionText) const; + bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const + { + return skipToNextSection(section, current, QStringRef(§ionText)); + } QString stateName(State s) const; diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 2f0886edce..593a87e65d 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -58,6 +58,7 @@ #include <qbytearray.h> #include <qdatetime.h> #include <qbasicatomic.h> +#include <qendian.h> #include <private/qsimd_p.h> #ifndef QT_BOOTSTRAPPED @@ -112,24 +113,24 @@ static uint crc32(const Char *ptr, size_t len, uint h) p += 8; for ( ; p <= e; p += 8) - h2 = _mm_crc32_u64(h2, qUnalignedLoad<qlonglong>(p - 8)); + h2 = _mm_crc32_u64(h2, qFromUnaligned<qlonglong>(p - 8)); h = h2; p -= 8; len = e - p; if (len & 4) { - h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p)); + h = _mm_crc32_u32(h, qFromUnaligned<uint>(p)); p += 4; } # else p += 4; for ( ; p <= e; p += 4) - h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p - 4)); + h = _mm_crc32_u32(h, qFromUnaligned<uint>(p - 4)); p -= 4; len = e - p; # endif if (len & 2) { - h = _mm_crc32_u16(h, qUnalignedLoad<ushort>(p)); + h = _mm_crc32_u16(h, qFromUnaligned<ushort>(p)); p += 2; } if (sizeof(Char) == 1 && len & 1) diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 7dd02bf954..1762da2c8f 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -60,15 +60,6 @@ QT_BEGIN_NAMESPACE const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } }; -static int grow(int size) -{ - if (size_t(size) > (MaxAllocSize - QListData::DataHeaderSize) / sizeof(void *)) - qBadAlloc(); - // dear compiler: don't optimize me out. - volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *); - return x; -} - /*! * Detaches the QListData by allocating new memory for a list which will be bigger * than the copied one and is expected to grow further. @@ -84,12 +75,12 @@ QListData::Data *QListData::detach_grow(int *idx, int num) Data *x = d; int l = x->end - x->begin; int nl = l + num; - int alloc = grow(nl); - Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *))); + auto blockInfo = qCalculateGrowingBlockSize(nl, sizeof(void *), DataHeaderSize); + Data* t = static_cast<Data *>(::malloc(blockInfo.size)); Q_CHECK_PTR(t); + t->alloc = int(uint(blockInfo.elementCount)); t->ref.initializeOwned(); - t->alloc = alloc; // The space reservation algorithm's optimization is biased towards appending: // Something which looks like an append will put the data at the beginning, // while something which looks like a prepend will put it in the middle @@ -99,12 +90,12 @@ QListData::Data *QListData::detach_grow(int *idx, int num) int bg; if (*idx < 0) { *idx = 0; - bg = (alloc - nl) >> 1; + bg = (t->alloc - nl) >> 1; } else if (*idx > l) { *idx = l; bg = 0; } else if (*idx < (l >> 1)) { - bg = (alloc - nl) >> 1; + bg = (t->alloc - nl) >> 1; } else { bg = 0; } @@ -126,7 +117,7 @@ QListData::Data *QListData::detach_grow(int *idx, int num) QListData::Data *QListData::detach(int alloc) { Data *x = d; - Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *))); + Data* t = static_cast<Data *>(::malloc(qCalculateBlockSize(alloc, sizeof(void*), DataHeaderSize))); Q_CHECK_PTR(t); t->ref.initializeOwned(); @@ -146,7 +137,7 @@ QListData::Data *QListData::detach(int alloc) void QListData::realloc(int alloc) { Q_ASSERT(!d->ref.isShared()); - Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + Data *x = static_cast<Data *>(::realloc(d, qCalculateBlockSize(alloc, sizeof(void *), DataHeaderSize))); Q_CHECK_PTR(x); d = x; @@ -158,12 +149,12 @@ void QListData::realloc(int alloc) void QListData::realloc_grow(int growth) { Q_ASSERT(!d->ref.isShared()); - int alloc = grow(d->alloc + growth); - Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + auto r = qCalculateGrowingBlockSize(d->alloc + growth, sizeof(void *), DataHeaderSize); + Data *x = static_cast<Data *>(::realloc(d, r.size)); Q_CHECK_PTR(x); d = x; - d->alloc = alloc; + d->alloc = int(uint(r.elementCount)); } void QListData::dispose(Data *d) diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp index 9b91474283..9a84191452 100644 --- a/src/corelib/tools/qmessageauthenticationcode.cpp +++ b/src/corelib/tools/qmessageauthenticationcode.cpp @@ -46,9 +46,29 @@ available on all platforms (MSVC 2008, for example), we #define them to the Qt equivalents. */ + +#ifdef uint64_t +#undef uint64_t +#endif + #define uint64_t QT_PREPEND_NAMESPACE(quint64) + +#ifdef uint32_t +#undef uint32_t +#endif + #define uint32_t QT_PREPEND_NAMESPACE(quint32) + +#ifdef uint8_t +#undef uint8_t +#endif + #define uint8_t QT_PREPEND_NAMESPACE(quint8) + +#ifdef int_least16_t +#undef int_least16_t +#endif + #define int_least16_t QT_PREPEND_NAMESPACE(qint16) // Header from rfc6234 with 1 modification: diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 7b1d94c501..d4edf459de 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -724,26 +724,4 @@ void qDumpCPUFeatures() puts(""); } -/*! - \internal - \fn T qUnalignedLoad(const void *ptr) - \since 5.6.1 - - Loads a \c{T} from address \a ptr, which may be misaligned. - - Use of this function avoid the undefined behavior that the C++ standard - otherwise attributes to unaligned loads. -*/ - -/*! - \internal - \fn void qUnalignedStore(void *ptr, T t) - \since 5.6.1 - - Stores \a t to address \a ptr, which may be misaligned. - - Use of this function avoid the undefined behavior that the C++ standard - otherwise attributes to unaligned stores. -*/ - QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 6c1ee25234..c79bced52e 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -581,7 +581,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l) // we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes) if (uc + offset + 7 < e) { // same, but we're using an 8-byte load - __m128i chunk = _mm_cvtsi64_si128(qUnalignedLoad<long long>(c + offset)); + __m128i chunk = _mm_cvtsi64_si128(qFromUnaligned<long long>(c + offset)); __m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask); __m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset)); @@ -1757,10 +1757,13 @@ void QString::resize(int size, QChar fillChar) void QString::reallocData(uint alloc, bool grow) { + size_t blockSize; if (grow) { - if (alloc > (uint(MaxAllocSize) - sizeof(Data)) / sizeof(QChar)) - qBadAlloc(); - alloc = qAllocMore(alloc * sizeof(QChar), sizeof(Data)) / sizeof(QChar); + auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); + blockSize = r.size; + alloc = uint(r.elementCount); + } else { + blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); } if (d->ref.isShared() || IS_RAW_DATA(d)) { @@ -1774,7 +1777,7 @@ void QString::reallocData(uint alloc, bool grow) Data::deallocate(d); d = x; } else { - Data *p = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Data *p = static_cast<Data *>(::realloc(d, blockSize)); Q_CHECK_PTR(p); d = p; d->alloc = alloc; @@ -2343,8 +2346,7 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs) */ QString &QString::replace(int pos, int len, const QString &after) { - QString copy = after; - return replace(pos, len, copy.constData(), copy.length()); + return replace(pos, len, after.constData(), after.length()); } /*! diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 8040365581..c2630c8593 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -47,6 +47,8 @@ #include <qdebug.h> +#include "qlocale_tools_p.h" + #include <algorithm> QT_BEGIN_NAMESPACE @@ -376,39 +378,126 @@ static QDate calculatePosixDate(const QByteArray &dateRule, int year) } } -static QTime parsePosixTime(const QByteArray &timeRule) +// returns the time in seconds, INT_MIN if we failed to parse +static int parsePosixTime(const char *begin, const char *end) { - // Format "HH:mm:ss", put check parts count just in case - QList<QByteArray> parts = timeRule.split(':'); - int count = parts.count(); - if (count == 3) - return QTime(parts.at(0).toInt(), parts.at(1).toInt(), parts.at(2).toInt()); - else if (count == 2) - return QTime(parts.at(0).toInt(), parts.at(1).toInt(), 0); - else if (count == 1) - return QTime(parts.at(0).toInt(), 0, 0); - return QTime(2, 0, 0); + // Format "hh[:mm[:ss]]" + int hour, min = 0, sec = 0; + + // Note that the calls to qstrtoll do *not* check the end pointer, which + // means they proceed until they find a non-digit. We check that we're + // still in range at the end, but we may have read from past end. It's the + // caller's responsibility to ensure that begin is part of a + // null-terminated string. + + bool ok = false; + hour = qstrtoll(begin, &begin, 10, &ok); + if (!ok || hour < 0) + return INT_MIN; + if (begin < end && *begin == ':') { + // minutes + ++begin; + min = qstrtoll(begin, &begin, 10, &ok); + if (!ok || min < 0) + return INT_MIN; + + if (begin < end && *begin == ':') { + // seconds + ++begin; + sec = qstrtoll(begin, &begin, 10, &ok); + if (!ok || sec < 0) + return INT_MIN; + } + } + + // we must have consumed everything + if (begin != end) + return INT_MIN; + + return (hour * 60 + min) * 60 + sec; } -static int parsePosixOffset(const QByteArray &timeRule) +static QTime parsePosixTransitionTime(const QByteArray &timeRule) +{ + // Format "hh[:mm[:ss]]" + int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd()); + if (value == INT_MIN) { + // if we failed to parse, return 02:00 + return QTime(2, 0, 0); + } + return QTime::fromMSecsSinceStartOfDay(value * 1000); +} + +static int parsePosixOffset(const char *begin, const char *end) { // Format "[+|-]hh[:mm[:ss]]" - QList<QByteArray> parts = timeRule.split(':'); - int count = parts.count(); - if (count == 3) { - int hour = parts.at(0).toInt(); - int sign = hour >= 0 ? -1 : 1; - return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60) + parts.at(2).toInt()); - } else if (count == 2) { - int hour = parts.at(0).toInt(); - int sign = hour >= 0 ? -1 : 1; - return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60)); - } else if (count == 1) { - int hour = parts.at(0).toInt(); - int sign = hour >= 0 ? -1 : 1; - return sign * (qAbs(hour) * 60 * 60); - } - return 0; + // note that the sign is inverted because POSIX counts in hours West of GMT + bool negate = true; + if (*begin == '+') { + ++begin; + } else if (*begin == '-') { + negate = false; + ++begin; + } + + int value = parsePosixTime(begin, end); + if (value == INT_MIN) + return value; + return negate ? -value : value; +} + +static inline bool asciiIsLetter(char ch) +{ + ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch + return ch >= 'a' && ch <= 'z'; +} + +// Returns the zone name, the offset (in seconds) and advances \a begin to +// where the parsing ended. Returns a zone of INT_MIN in case an offset +// couldn't be read. +static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const char *end) +{ + static const char offsetChars[] = "0123456789:"; + QPair<QString, int> result = qMakePair(QString(), INT_MIN); + + const char *nameBegin = pos; + const char *nameEnd; + Q_ASSERT(pos < end); + + if (*pos == '<') { + nameBegin = pos + 1; // skip the '<' + nameEnd = nameBegin; + while (nameEnd < end && *nameEnd != '>') { + // POSIX says only alphanumeric, but we allow anything + ++nameEnd; + } + pos = nameEnd + 1; // skip the '>' + } else { + nameBegin = pos; + nameEnd = nameBegin; + while (nameEnd < end && asciiIsLetter(*nameEnd)) + ++nameEnd; + pos = nameEnd; + } + if (nameEnd - nameBegin < 3) + return result; // name must be at least 3 characters long + + // zone offset, form [+-]hh:mm:ss + const char *zoneBegin = pos; + const char *zoneEnd = pos; + if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-')) + ++zoneEnd; + while (zoneEnd < end) { + if (strchr(offsetChars, char(*zoneEnd)) == NULL) + break; + ++zoneEnd; + } + + result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin); + if (zoneEnd > zoneBegin) + result.second = parsePosixOffset(zoneBegin, zoneEnd); + pos = zoneEnd; + return result; } static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule, @@ -425,58 +514,45 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra // POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00" // i.e. "std offset dst [offset],start[/time],end[/time]" - // See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + // See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html QList<QByteArray> parts = posixRule.split(','); - QString name = QString::fromUtf8(parts.at(0)); - QString stdName; - QString stdOffsetString; - QString dstName; - QString dstOffsetString; - bool parsedStdName = false; - bool parsedStdOffset = false; - for (int i = 0; i < name.size(); ++i) { - if (name.at(i).isLetter()) { - if (parsedStdName) { - parsedStdOffset = true; - dstName.append(name.at(i)); - } else { - stdName.append(name.at(i)); + QPair<QString, int> stdZone, dstZone; + { + const QByteArray &zoneinfo = parts.at(0); + const char *begin = zoneinfo.constBegin(); + + stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); + if (stdZone.second == INT_MIN) { + stdZone.second = 0; // reset to UTC if we failed to parse + } else if (begin < zoneinfo.constEnd()) { + dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); + if (dstZone.second == INT_MIN) { + // if the dst offset isn't provided, it is 1 hour ahead of the standard offset + dstZone.second = stdZone.second + (60 * 60); } - } else { - parsedStdName = true; - if (parsedStdOffset) - dstOffsetString.append(name.at(i)); - else - stdOffsetString.append(name.at(i)); } } - int utcOffset = parsePosixOffset(stdOffsetString.toUtf8()); - // If only the name part then no transitions if (parts.count() == 1) { QTimeZonePrivate::Data data; data.atMSecsSinceEpoch = lastTranMSecs; - data.offsetFromUtc = utcOffset; - data.standardTimeOffset = utcOffset; + data.offsetFromUtc = stdZone.second; + data.standardTimeOffset = stdZone.second; data.daylightTimeOffset = 0; - data.abbreviation = stdName; + data.abbreviation = stdZone.first; result << data; return result; } - // If not populated the total dst offset is 1 hour - int dstOffset = utcOffset + (60 * 60); - if (!dstOffsetString.isEmpty()) - dstOffset = parsePosixOffset(dstOffsetString.toUtf8()); // Get the std to dst transtion details QList<QByteArray> dstParts = parts.at(1).split('/'); QByteArray dstDateRule = dstParts.at(0); QTime dstTime; if (dstParts.count() > 1) - dstTime = parsePosixTime(dstParts.at(1)); + dstTime = parsePosixTransitionTime(dstParts.at(1)); else dstTime = QTime(2, 0, 0); @@ -485,25 +561,25 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra QByteArray stdDateRule = stdParts.at(0); QTime stdTime; if (stdParts.count() > 1) - stdTime = parsePosixTime(stdParts.at(1)); + stdTime = parsePosixTransitionTime(stdParts.at(1)); else stdTime = QTime(2, 0, 0); for (int year = startYear; year <= endYear; ++year) { QTimeZonePrivate::Data dstData; QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC); - dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (utcOffset * 1000); - dstData.offsetFromUtc = dstOffset; - dstData.standardTimeOffset = utcOffset; - dstData.daylightTimeOffset = dstOffset - utcOffset; - dstData.abbreviation = dstName; + dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000); + dstData.offsetFromUtc = dstZone.second; + dstData.standardTimeOffset = stdZone.second; + dstData.daylightTimeOffset = dstZone.second - stdZone.second; + dstData.abbreviation = dstZone.first; QTimeZonePrivate::Data stdData; QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC); - stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstOffset * 1000); - stdData.offsetFromUtc = utcOffset; - stdData.standardTimeOffset = utcOffset; + stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000); + stdData.offsetFromUtc = stdZone.second; + stdData.standardTimeOffset = stdZone.second; stdData.daylightTimeOffset = 0; - stdData.abbreviation = stdName; + stdData.abbreviation = stdZone.first; // Part of the high year will overflow if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) { if (dstData.atMSecsSinceEpoch > 0) { diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index 5ec153c818..09adee5586 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -52,7 +52,7 @@ // #include "QtCore/qglobal.h" -#include <limits> +#include <limits.h> QT_BEGIN_NAMESPACE @@ -88,11 +88,19 @@ Q_DECL_CONSTEXPR inline int fromOct(uint c) Q_DECL_NOTHROW // We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. enum { - MaxAllocSize = (1 << (std::numeric_limits<int>::digits - 1)) - 1 + MaxAllocSize = INT_MAX +}; + +struct CalculateGrowingBlockSizeResult { + size_t size; + size_t elementCount; }; // implemented in qbytearray.cpp -int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW; +size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION +qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW; +CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION +qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW ; QT_END_NAMESPACE diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index fea50f4c34..b68ca87063 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -736,7 +736,7 @@ typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend) const int itemsUntouched = abegin - d->begin(); // FIXME we could do a proper realloc, which copy constructs only needed data. - // FIXME we ara about to delete data maybe it is good time to shrink? + // FIXME we are about to delete data - maybe it is good time to shrink? // FIXME the shrink is also an issue in removeLast, that is just a copy + reduce of this. if (d->alloc) { detach(); @@ -756,7 +756,11 @@ typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend) } } else { destruct(abegin, aend); - memmove(abegin, aend, (d->size - itemsToErase - itemsUntouched) * sizeof(T)); + // QTBUG-53605: static_cast<void *> masks clang errors of the form + // error: destination for this 'memmove' call is a pointer to class containing a dynamic class + // FIXME maybe use std::is_polymorphic (as soon as allowed) to avoid the memmove + memmove(static_cast<void *>(abegin), static_cast<void *>(aend), + (d->size - itemsToErase - itemsUntouched) * sizeof(T)); } d->size -= itemsToErase; } diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 8e62804025..3949d2c3ac 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3025,10 +3025,14 @@ void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec() { #ifndef QT_NO_TEXTCODEC Q_ASSERT(encoder); - // assumes ASCII-compatibility for all 8-bit encodings - QChar space = QLatin1Char(' '); - const QByteArray bytes = encoder->fromUnicode(&space, 1); - isCodecASCIICompatible = (bytes.count() == 1); + // test ASCII-compatibility using the letter 'a' + QChar letterA = QLatin1Char('a'); + const QByteArray bytesA = encoder->fromUnicode(&letterA, 1); + const bool isCodecASCIICompatibleA = (bytesA.count() == 1) && (bytesA[0] == 0x61) ; + QChar letterLess = QLatin1Char('<'); + const QByteArray bytesLess = encoder->fromUnicode(&letterLess, 1); + const bool isCodecASCIICompatibleLess = (bytesLess.count() == 1) && (bytesLess[0] == 0x3C) ; + isCodecASCIICompatible = isCodecASCIICompatibleA && isCodecASCIICompatibleLess ; #else isCodecASCIICompatible = true; #endif @@ -3790,7 +3794,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version) #ifdef QT_NO_TEXTCODEC d->write("iso-8859-1"); #else - d->write(d->codec->name().constData(), d->codec->name().length()); + const QByteArray name = d->codec->name(); + d->write(name.constData(), name.length()); #endif } d->write("\"?>"); @@ -3813,7 +3818,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalon #ifdef QT_NO_TEXTCODEC d->write("iso-8859-1"); #else - d->write(d->codec->name().constData(), d->codec->name().length()); + const QByteArray name = d->codec->name(); + d->write(name.constData(), name.length()); #endif } if (standalone) |