From e91be71ef04c22e478a3e98256ded87b28d0d767 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 01:32:30 +0200 Subject: Add OpenBSD to list of BSD systems defines using kqueue too Besides FreeBSD and NetBSD, OpenBSD uses kqueue too, so add the according Q_OS_OPENBSD define here to make that work. Patch obtained via OpenBSD qt ports maintainer Vadim Zhukov from OpenBSD qt ports patches. Change-Id: Ib9e6f6303b661beb88666bd3c2bf36a77e929f9d Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemwatcher.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 354e4931b9..d8564c4c40 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -52,7 +52,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(Q_OS_IOS) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_IOS) # include "qfilesystemwatcher_kqueue_p.h" #elif defined(Q_OS_OSX) # include "qfilesystemwatcher_fsevents_p.h" @@ -68,7 +68,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(Q_OS_IOS) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_IOS) return QKqueueFileSystemWatcherEngine::create(parent); #elif defined(Q_OS_OSX) return QFseventsFileSystemWatcherEngine::create(parent); -- cgit v1.2.3 From 14ae00dd50ed4a75c2efa0b34da971b0e252e124 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 13:31:27 +0200 Subject: Compile fix: undefine types before defining them On NetBSD, the types uint64_t, uint32_t and uint8_t are already defined in sys/types.h which leads to compile errors. Those types need to be properly undefined before defining them with the Qt code. Change-Id: Icd58f421619f15b899cf5c5de1cfb22a519a4e4b Reviewed-by: Thiago Macieira --- src/corelib/tools/qcryptographichash.cpp | 20 ++++++++++++++++++++ src/corelib/tools/qmessageauthenticationcode.cpp | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 1c74a602c6..ab549f071e 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -89,9 +89,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/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp index 5e7f1fc431..f25a76d450 100644 --- a/src/corelib/tools/qmessageauthenticationcode.cpp +++ b/src/corelib/tools/qmessageauthenticationcode.cpp @@ -40,9 +40,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: -- cgit v1.2.3 From 9b153f989bcc40fed85d5cbd8a489c6e0eb5c9c7 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 13:59:27 +0200 Subject: Compile fix: convert argument to long to match parameter comparison GCC creates a warning "enumeral and non-enumeral type in conditional expression" as the types of the two arguments don't match. Fix the compile warning by converting the first argument to (long) to match the type of the second parameter. Fix confirmed to work on NetBSD and FreeBSD, obtained from Kamil Rytarowski , NetBSD qt ports maintainer. Change-Id: I777dd066a0a8cc8a46e34bd39b256882080a7773 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 491ed99301..29c8dbb2ea 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2159,7 +2159,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); #else return timezone; #endif // Q_OS_WIN -- cgit v1.2.3 From 725a9c27021bef1ac3828a4eafc013a2f50e6f22 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 14:06:08 +0200 Subject: Compile fix: add NetBSD define for ffsll usage On NetBSD, ffsll needs to be defined to compile. The fix adds the according Q_OS_NETBSD define to the list of operating systems needing the define. Fix obtained from NetBSD port maintainer Kamil Rytarowski via IRC. Change-Id: I966a7b3fba43fb56e72f19f6b7f7cacc19c3c6cf Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index a1ee5b6348..0e3359ab81 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -636,7 +636,7 @@ int ffsll(quint64 i) #endif } #endif -#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) +#elif defined(Q_OS_NETBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) # define ffsll __builtin_ffsll #endif -- cgit v1.2.3 From f8c3820de789a2c08dab2ddb7bf18728cdbd7028 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 15:04:01 +0200 Subject: Compile fix: remove unused variable bool isEmpty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The local variable isEmpty triggers a compile warning with GCC: variable ‘isEmpty’ set but not used [-Werror=unused-but-set-variable], so remove the variable assignment and declaration. Error is triggered on FreeBSD and NetBSD with gcc. Change-Id: I37bdb3408ad69093708f2d4bdb04392da66e04e5 Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemwatcher_kqueue.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 80cbcb26cc..9b574cbdfb 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -166,7 +166,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths QStringList *files, QStringList *directories) { - bool isEmpty; QStringList p = paths; if (pathToID.isEmpty()) return p; @@ -187,7 +186,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths else files->removeAll(path); } - isEmpty = pathToID.isEmpty(); return p; } -- cgit v1.2.3 From e3d1058ae9de6eee4d64ea1af66571497208d8c5 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 20:15:03 +0200 Subject: Compile fix for NetBSD: only BSD using statvfs, disable f_flags define Compile fix for NetBSD's use of statvfs having f_flags.All other BSDs use statfs instead of statvfs, so the f_flags define needs to be prevented on NetBSD. Fix obtained from Kamil Rytarowski , NetBSD qt ports maintainer. Change-Id: Ifbd7ba0cba7f6cf280f5984c64abd7649f667332 Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 1d1b2907b7..c02d82a711 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -78,7 +78,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) -- cgit v1.2.3 From f156c81d7fada47835f4ebce9f70f8b1bdb01201 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 10:30:45 -0700 Subject: Restore the -fno-lto build of qversiontagging.cpp I'm not sure how one of my machines has this problem and the other doesn't (same distribution and same compiler version). Must be operator error. But this is required to compile QtGui when QtCore was compiled in LTO mode. qversiontagging.cpp used to be built with -fno-lto before commit 629ceec208ad5fe9f5d201fc42fce611e55c567d. This commit restores that functionality, but not the clang "-no-integrated-as" part. Change-Id: Ie9fd7afe060b4e4a8052fffd144fb9c1a1166854 Reviewed-by: Oswald Buddenhagen --- src/corelib/global/global.pri | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/corelib') 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 +} -- cgit v1.2.3 From e9041c7fc1052167f1ec2df0ea9623059e55d00f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 28 Apr 2016 22:09:01 -0700 Subject: Fix parsing of tzfile(5) POSIX rule zone names with bracket quotes POSIX.1-2001 allows quoting a zone name so that it can contain other characters besides letters, by enclosing it in angle brackets ('<' and '>'). This hadn't been used until recently (tzdata2016b), when the Asia/Barnaul rule started using a zone name "+07" (the name variable contained the value "<+07>-7"). Thanks to Paul Eggert for reporting and investigating the root cause. Task-number: QTBUG-53071 Change-Id: Id5480807d25e49e78b79ffff1449bc410776cb66 Reviewed-by: Edward Welbourne Reviewed-by: Lars Knoll --- src/corelib/tools/qtimezoneprivate_tz.cpp | 176 ++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 56 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 85ed345869..cb9581ab63 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -41,6 +41,8 @@ #include +#include "qlocale_tools_p.h" + #include QT_BEGIN_NAMESPACE @@ -384,25 +386,100 @@ static QTime parsePosixTime(const QByteArray &timeRule) return QTime(2, 0, 0); } -static int parsePosixOffset(const QByteArray &timeRule) +static int parsePosixOffset(const char *begin, const char *end) { // Format "[+|-]hh[:mm[:ss]]" - QList 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; + int hour, min = 0, sec = 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; + } + + bool ok = false; + hour = qstrtoll(begin, &begin, 10, &ok); + if (!ok) + 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; + + int value = (hour * 60 + min) * 60 + sec; + 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 parsePosixZoneNameAndOffset(const char *&pos, const char *end) +{ + static const char offsetChars[] = "0123456789:"; + QPair 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 calculatePosixTransitions(const QByteArray &posixRule, @@ -419,51 +496,38 @@ static QVector 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 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 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 dstParts = parts.at(1).split('/'); @@ -486,18 +550,18 @@ static QVector calculatePosixTransitions(const QByteArra 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) { -- cgit v1.2.3 From cd25866f6533923c208f52d58516f3725f69cefb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 13:38:55 -0700 Subject: Use the code we already have for parsing the transition time too It's there and it's more efficient anyway. Change-Id: Ie9fd7afe060b4e4a8052fffd144fc40647430268 Reviewed-by: Edward Welbourne Reviewed-by: Brett Stottlemyer Reviewed-by: Lars Knoll --- src/corelib/tools/qtimezoneprivate_tz.cpp | 68 ++++++++++++++++++------------- 1 file changed, 40 insertions(+), 28 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index cb9581ab63..bfa967e67b 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -372,37 +372,21 @@ 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 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); -} - -static int parsePosixOffset(const char *begin, const char *end) -{ - // Format "[+|-]hh[:mm[:ss]]" + // Format "hh[:mm[:ss]]" int hour, min = 0, sec = 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; - } + // 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) + if (!ok || hour < 0) return INT_MIN; if (begin < end && *begin == ':') { // minutes @@ -424,7 +408,35 @@ static int parsePosixOffset(const char *begin, const char *end) if (begin != end) return INT_MIN; - int value = (hour * 60 + min) * 60 + sec; + return (hour * 60 + min) * 60 + sec; +} + +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]]" + // 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; } @@ -534,7 +546,7 @@ static QVector calculatePosixTransitions(const QByteArra 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); @@ -543,7 +555,7 @@ static QVector 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); -- cgit v1.2.3 From e0ab94b5251e732d4bea553f2d6e943f5d714720 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 24 May 2016 22:02:02 +0200 Subject: Compile fix: for OpenBSD: not included by On OpenBSD, isn't included in , so that leads to compile errors on files that include qcore_unix_p.h: qcore_unix_p.h:335:69: error: 'fd_set' has not been declared Just move the whole select include section from qcore_unix.cpp, no functional changes. The patch is adapted from OpenBSD ports maintainer Vadim Zhukov patch for qt ports. Change-Id: I35ba693440b1c1644bcfcdb69823e2b37870ad97 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_unix.cpp | 10 ---------- src/corelib/kernel/qcore_unix_p.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 5695cb3ec5..1bcb4720c2 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -34,16 +34,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 -# endif -# include -#else -# include -#endif - #include #ifdef Q_OS_MAC diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index f80dcb5a50..05711354ff 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -58,6 +58,16 @@ #include #include +#ifdef Q_OS_NACL +#elif !defined (Q_OS_VXWORKS) +# if !defined(Q_OS_HPUX) || defined(__ia64) +# include +# endif +# include +#else +# include +#endif + #include #include #include -- cgit v1.2.3 From 540978288ea0f6ed0b166bb9207f427a4c825ab6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 15 Mar 2016 10:10:12 -0700 Subject: Replace qUnaligned{Load,Store} with the existing q{To,From}Unaligned Move the Q_ALWAYS_INLINE and forcing of __builtin_memcpy to the existing functions. Change-Id: Icaa7fb2a490246bda156ffff143c137e520eea79 Reviewed-by: Lars Knoll --- src/corelib/global/qendian.h | 30 +++++++++++++++++--------- src/corelib/global/qendian.qdoc | 23 ++++++++++++++++++++ src/corelib/json/qjson_p.h | 2 +- src/corelib/mimetypes/qmimemagicrule.cpp | 3 +-- src/corelib/tools/qbitarray.cpp | 26 ++++------------------ src/corelib/tools/qhash.cpp | 9 ++++---- src/corelib/tools/qsimd.cpp | 22 ------------------- src/corelib/tools/qsimd_p.h | 37 -------------------------------- src/corelib/tools/qstring.cpp | 2 +- 9 files changed, 55 insertions(+), 99 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 2ddefaec8b..23dda270e3 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -42,6 +42,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 @@ -64,18 +69,29 @@ template 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 inline void qToUnaligned(const T src, uchar *dest) +template 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 inline T qFromUnaligned(const uchar *src) + +template 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; } @@ -87,12 +103,6 @@ template inline T qFromUnaligned(const uchar *src) */ template T qbswap(T source); -#ifdef __has_builtin -# define QT_HAS_BUILTIN(x) __has_builtin(x) -#else -# define QT_HAS_BUILTIN(x) 0 -#endif - // GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8; // Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one #if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32) diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc index e110461f8b..b7494c9a21 100644 --- a/src/corelib/global/qendian.qdoc +++ b/src/corelib/global/qendian.qdoc @@ -33,6 +33,29 @@ little and big endian representations of numbers. */ +/*! + \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 diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 59d0c91785..c52a37ba2b 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -402,7 +402,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 diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 44834420fe..398a670544 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -42,7 +42,6 @@ #include #include #include -#include // for qUnalignedLoad QT_BEGIN_NAMESPACE @@ -177,7 +176,7 @@ static bool matchNumber(const QMimeMagicRulePrivate *d, const QByteArray &data) const char *p = data.constData() + d->startPos; const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), d->endPos + 1); for ( ; p <= e; ++p) { - if ((qUnalignedLoad(p) & mask) == (value & mask)) + if ((qFromUnaligned(reinterpret_cast(p)) & mask) == (value & mask)) return true; } diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index a64edea77e..8e6b1203f8 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -162,25 +163,6 @@ QBitArray::QBitArray(int size, bool value) Same as size(). */ -template 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 @@ -196,17 +178,17 @@ int QBitArray::count(bool on) const const quint8 *const end = reinterpret_cast(d.end()); while (bits + 7 <= end) { - quint64 v = qUnalignedLoad(bits); + quint64 v = qFromUnaligned(bits); bits += 8; numBits += int(qPopulationCount(v)); } if (bits + 3 <= end) { - quint32 v = qUnalignedLoad(bits); + quint32 v = qFromUnaligned(bits); bits += 4; numBits += int(qPopulationCount(v)); } if (bits + 1 < end) { - quint16 v = qUnalignedLoad(bits); + quint16 v = qFromUnaligned(bits); bits += 2; numBits += int(qPopulationCount(v)); } diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index d40570d347..c5669babd9 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifndef QT_BOOTSTRAPPED @@ -105,24 +106,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(p - 8)); + h2 = _mm_crc32_u64(h2, qFromUnaligned(p - 8)); h = h2; p -= 8; len = e - p; if (len & 4) { - h = _mm_crc32_u32(h, qUnalignedLoad(p)); + h = _mm_crc32_u32(h, qFromUnaligned(p)); p += 4; } # else p += 4; for ( ; p <= e; p += 4) - h = _mm_crc32_u32(h, qUnalignedLoad(p - 4)); + h = _mm_crc32_u32(h, qFromUnaligned(p - 4)); p -= 4; len = e - p; # endif if (len & 2) { - h = _mm_crc32_u16(h, qUnalignedLoad(p)); + h = _mm_crc32_u16(h, qFromUnaligned(p)); p += 2; } if (sizeof(Char) == 1 && len & 1) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 5ca2ce4c6f..f07eb098f2 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -716,26 +716,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/qsimd_p.h b/src/corelib/tools/qsimd_p.h index ca53908cf5..d689654b29 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -476,43 +476,6 @@ unsigned _bit_scan_forward(unsigned val) #define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \ for (; i < static_cast(qMin(static_cast(length), ((4 - ((reinterpret_cast(ptr) >> 2) & 0x3)) & 0x3))); ++i) -// these defines are copied from qendian.h -// in Qt 5.7, they have been moved to qglobal.h -// drop them when merging this to 5.7 -#ifdef __has_builtin -# define QT_HAS_BUILTIN(x) __has_builtin(x) -#else -# define QT_HAS_BUILTIN(x) 0 -#endif - -template -Q_ALWAYS_INLINE -T qUnalignedLoad(const void *ptr) Q_DECL_NOTHROW -{ - T result; -#if QT_HAS_BUILTIN(__builtin_memcpy) - __builtin_memcpy -#else - memcpy -#endif - /*memcpy*/(&result, ptr, sizeof result); - return result; -} - -template -Q_ALWAYS_INLINE -void qUnalignedStore(void *ptr, T t) Q_DECL_NOTHROW -{ -#if QT_HAS_BUILTIN(__builtin_memcpy) - __builtin_memcpy -#else - memcpy -#endif - /*memcpy*/(ptr, &t, sizeof t); -} - -#undef QT_HAS_BUILTIN - QT_END_NAMESPACE #endif // QSIMD_P_H diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 6bbaf05fef..be1ca8ba95 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -577,7 +577,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(c + offset)); + __m128i chunk = _mm_cvtsi64_si128(qFromUnaligned(c + offset)); __m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask); __m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset)); -- cgit v1.2.3 From 5fe16358bbbcd1a6fdd4904b01ffcec4a9eee5d8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 25 May 2016 09:47:57 -0700 Subject: Fix use of QMutex on Linux before FUTEX_PRIVATE_FLAG was added It was added in 2.6.22. If we pass it to 2.6.21, we'll get -ENOSYS, which is bad for QMutex. This fix simply defines it to 0 if the header doesn't define it. But as a consequence: if Qt is built with newer kernel headers, it won't run on older versions. It's not likely that someone is still using Qt 5.7 on a 2.6.21 kernel (v2.6.21.7 was released on 2007-08-04). Change-Id: Icb178bb113bb437c9b67fffd1451dd7bb964f0c8 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/thread/qmutex_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') 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 -- cgit v1.2.3 From 9224255f13952e5b4092208c8cae1a31ab5c6a19 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 27 May 2016 07:22:40 +0200 Subject: QVector: silence clang warning about memmove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also made a small comment fix Task-number: QTBUG-53605 Change-Id: Ica9a06fe7a70f92f2a19a6df3ffdeaf1985e2eb6 Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qvector.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/corelib') 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::iterator QVector::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::iterator QVector::erase(iterator abegin, iterator aend) } } else { destruct(abegin, aend); - memmove(abegin, aend, (d->size - itemsToErase - itemsUntouched) * sizeof(T)); + // QTBUG-53605: static_cast 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(abegin), static_cast(aend), + (d->size - itemsToErase - itemsUntouched) * sizeof(T)); } d->size -= itemsToErase; } -- cgit v1.2.3 From c85f988fc785690ade283305181de8e7256d4040 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Wed, 25 May 2016 11:51:52 +0200 Subject: Disable thread_local on clang for FreeBSD FreeBSD's clang currently is not able to handle thread_local calls due to linker errors on __cxa_thread_atexit. The patch disables the define Q_COMPILER_THREAD_LOCAL for clang __FreeBSD__ only, no functional change. Otherwise, linking the tst_compiler autotest will fail. For details, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=192320 Change-Id: I2395c06499d4821213e2154769ccbeed3dcf1ffe Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 8574059616..ad881ef4c9 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -699,7 +699,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 -- cgit v1.2.3 From 0f559a2d998d7ff5b7dec83a1c7e8a9996cbaa26 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 25 Apr 2016 10:59:31 -0700 Subject: Force the use of the C++11 alignof keyword instead of an extension If the compiler supports C++11 alignof, let's use it. No point in perpetuating the use of __alignof__ or __alignof. There's a fallback implementation in qglobal.h that works even without compiler extensions. We can't drop it just yet (alignas is not a required C++11 feature), but at this point I doubt that fallback is used anywhere anymore. The tst_compiler test was wrong to use alignof(variable). That's not permitted by the standard nor would it work with our fallback implementation. MSVC 2015 enforces this, but ICC, GCC and Clang don't. Change-Id: Ifea6e497f11a461db432ffff1448abfa86672c63 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qcompilerdetection.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index ad881ef4c9..01b3a298af 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1053,7 +1053,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 -- cgit v1.2.3 From 261f9101dd8b03019251cf9aa58382de0fbde2e7 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 15 May 2016 14:53:38 +0300 Subject: QLockFile: Use a more robust stale file detection When a process that locked a lockfile crashes on Windows, sometimes a new instance of the process fails to lock. Unfortunately, I can't find a way to reproduce the problem consistently, but it happens from time to time with Qt Creator and Qbs. There are several ways to detect a dead process on Windows. Some of them can be found in stackoverflow[1]. The current implementation of stale lock detection is based on the second answer (using WaitForSingleObject), but apparently it doesn't work in 100% of the cases. The most voted answer[2] (using GetProcessExitCode) proves to work also on this case. [1] http://stackoverflow.com/q/1591342/764870 [2] http://stackoverflow.com/a/1591379/764870 Task-number: QTBUG-53392 Change-Id: Ied7bf00985d0f12e833b887a0143f7bdeee3e772 Reviewed-by: Kai Koehne Reviewed-by: Thiago Macieira --- src/corelib/io/qlockfile_win.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index 5bd1ba04c9..e72e486cce 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -137,9 +137,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) -- cgit v1.2.3 From 6d31d3e7effabcc998792283249d46f5c0d73b3d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 20:28:33 -0700 Subject: Fix build with ICC on OS X: __Z18qt_getQtMetaObjectv was undefiend It's inline, but the compiler did not inline it properly from Objective C++ sources. Undefined symbols for architecture x86_64: "__Z18qt_getQtMetaObjectv", referenced from: __ZN2Qt20qt_getEnumMetaObjectENS_15ScrollBarPolicyE in qlocale_mac.o ... Change-Id: Ie9fd7afe060b4e4a8052fffd144fda60c50a9779 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 771d2f5ea0..b39eefa795 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -444,8 +444,7 @@ protected: QScopedPointer 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; @@ -476,6 +475,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: -- cgit v1.2.3 From 32c301e2296c5b3ba31528e6d92b521d43a216e9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 29 May 2016 17:45:05 -0300 Subject: Fix crash when connecting a non-PMF with Qt::UniqueConnection... ...if a PMF connection had already happened. Since UniqueConnection isn't implemented for non-PMFs (functors and lambdas aren't comparable, even if static member functions or non-member functions are), we pass a null pointer for comparison argument. The disconnect() code already protected against a null pointer there, but not the connect code path with Qt::UniqueConnection Change-Id: I87e17314d8b24ae983b1fffd145324beced0494d Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Dario Freddi --- src/corelib/kernel/qobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d97f8d0ef1..a21dbffad5 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4683,7 +4683,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 = -- cgit v1.2.3 From b403b8c094a1bf59b70368e28cbd454b6872498f Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Thu, 26 May 2016 23:09:36 +0200 Subject: Add Interix OS system detection defines NetBSD (pkgsrc) ports are building qt on Interix as well, where the necessary defines are missing for in qsystemdetection.h. Patch for adding them provided by NetBSD ports maintainer Kamil Rytarowski Change-Id: I769c47f623317efda3130a7061307e84d3350fac Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/global/qsystemdetection.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index f1abc88b99..b6a7835ef2 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -60,6 +60,7 @@ NETBSD - NetBSD OPENBSD - OpenBSD BSDI - BSD/OS + INTERIX - Interix IRIX - SGI Irix OSF - HP Tru64 UNIX SCO - SCO OpenServer 5 @@ -147,6 +148,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__) -- cgit v1.2.3 From 886086f5d39a317443018689f817e8eb8ecb0be8 Mon Sep 17 00:00:00 2001 From: Aleksei Timofeyev Date: Fri, 22 Apr 2016 12:57:17 +0500 Subject: QWindowsPipeWriter: Discard queued signals in stop() The _q_queueBytesWritten signal may be already queued from the event loop at the time when stop() is called. We do not want to emit signals once stopped, so reset all respective state variables. Change-Id: I343e1702955e0bbc1d11930d19e75dab6e129b4c Reviewed-by: Alex Trotsenko Reviewed-by: Joerg Bornemann --- src/corelib/io/qwindowspipewriter.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 839dc8a19c..3731aba97b 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -202,6 +202,8 @@ bool QWindowsPipeWriter::write(const QByteArray &ba) void QWindowsPipeWriter::stop() { stopped = true; + bytesWrittenPending = false; + pendingBytesWrittenValue = 0; if (writeSequenceStarted) { if (!qt_cancelIo(handle, &overlapped)) { const DWORD dwError = GetLastError(); -- cgit v1.2.3 From e4d838ff9d7bedfd88d45fd833f13f0976265b3a Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Fri, 29 Apr 2016 15:40:46 +0300 Subject: QDateTimeParser: adapt to make good use of QStringRef. Avoid unnecessary allocations. Create QString from QStringRef only where necessary. Change-Id: I8f2a7dce51430162c84328e23ab3cc071227d6ae Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 23 ++++++++++++----------- src/corelib/tools/qdatetimeparser_p.h | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'src/corelib') 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; -- cgit v1.2.3 From 2f0ffba638bdb868a810bc0349c240b6b6e172cd Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 30 May 2016 14:15:49 +0200 Subject: Fix emission of QProcess:errorOccurred Consistently use setErrorAndEmit to emit errorOccurred and the deprecated error signal. Change-Id: I8bc7634a72d4d13f74bbf76547de08271dfcbb59 Reviewed-by: Kai Koehne --- src/corelib/io/qprocess.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 502628489d..6e1a771258 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2090,10 +2090,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; } @@ -2120,10 +2117,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; } -- cgit v1.2.3 From 2e4191eadce4cfe944afd0baf37f06bbcb65c5f4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 May 2016 12:31:48 -0300 Subject: QObject::connect: reduce generated code size for statics and functors Instead of placing the assignment of false in the impl() function, move it to the inline QSlotObjectBase::compare() function. That means it's assigned in one place (two, actually, inside qobject.cpp), instead of for every static member, non-member or functor we connect or disconnect. Change-Id: I87e17314d8b24ae983b1fffd1453623ad4c4dcb2 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject_impl.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 6140ae775e..b4091a4f1c 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -126,7 +126,7 @@ namespace QtPrivate { inline void destroyIfLastRef() Q_DECL_NOTHROW { if (!m_ref.deref()) m_impl(Destroy, this, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); } - inline bool compare(void **a) { bool ret; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } + inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, Q_NULLPTR); } protected: ~QSlotObjectBase() {} @@ -172,10 +172,9 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: - *ret = false; // not implemented - break; - case NumOperations: ; + case Compare: // not implemented + case NumOperations: + Q_UNUSED(ret); } } public: @@ -197,10 +196,9 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: - *ret = false; // not implemented - break; - case NumOperations: ; + case Compare: // not implemented + case NumOperations: + Q_UNUSED(ret); } } public: -- cgit v1.2.3 From 3432742caa5171ceddee0e75adefda9310c3b1eb Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Mon, 23 May 2016 22:00:05 +0200 Subject: Merge BSD implementations of QLockFilePrivate::processNameByPid() Until now, several solutions for the implementations of processNameByPid() on BSD systems existed: - one for FreeBSD using libutil through kinfo_getproc() using sysctl() implicitly - one for GNU/kFreeBSD using sysctl() explicitly added in commit a8f4fa217daa1b6f7b13cc48c1e5ee8d2d76b008 OpenBSD and NetBSD also had different approaches in their ports patches using kvm() and sysctl(). The code unifies this for all BSDs using sysctl(). Change-Id: Iced9ef01e5966d8688f464f51024a7ed562e26a3 Reviewed-by: Thiago Macieira Reviewed-by: Dmitry Shachnev --- src/corelib/io/io.pri | 1 - src/corelib/io/qlockfile_unix.cpp | 43 ++++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 8d9908cd90..553c996458 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -147,7 +147,6 @@ win32 { SOURCES += io/qsettings_mac.cpp OBJECTIVE_SOURCES += io/qurl_mac.mm } - freebsd: LIBS_PRIVATE += -lutil # qlockfile_unix.cpp requires this mac { osx { OBJECTIVE_SOURCES += io/qfilesystemwatcher_fsevents.mm diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index f23a232fb8..eed3158fbe 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -59,14 +59,12 @@ # include # include #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) +# if !defined(Q_OS_NETBSD) # include -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) +# endif # include # include # include -# else -# include -# endif #endif QT_BEGIN_NAMESPACE @@ -269,30 +267,33 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) buf[len] = 0; return QFileInfo(QFile::decodeName(buf)).fileName(); #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) -# 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(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(); -- cgit v1.2.3 From d96057328aae28a27a46492a310d9a05e250631c Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 31 May 2016 06:13:50 +0200 Subject: Compile fix: add OpenBSD define for ffsll usage On OpenBSD, ffsll needs to be defined to compile. This is the same change as in commit 725a9c27021bef1ac3828a4eafc013a2f50e6f22 for NetBSD. Change-Id: I3060caa10950a9419084a12de8c88a2f98b34d07 Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 0e3359ab81..ac28832c31 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -636,7 +636,7 @@ int ffsll(quint64 i) #endif } #endif -#elif defined(Q_OS_NETBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) +#elif defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) # define ffsll __builtin_ffsll #endif -- cgit v1.2.3 From bbb440bab261fecc7c9baf779dadf36659d3cf6f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 20 May 2016 06:28:26 +0200 Subject: QJsonValue: fix use-after-free in assignment operator The assignment operator of a String QJsonValue that holds the only remaining reference to the QString::Data block was freeing the block before obtaining its own reference, leading to a use-after-free in the case where *this was passed as 'other' (self-assignment). Fixed by reformulating the assignment operator in terms of the copy ctor, using the copy-swap idiom, with the twist that QJsonValue doesn't, yet, have a swap member function, so we use three per-member qSwap()s. Change-Id: I3c5ccc4d9f32c7593af3fc6a0edbf12b7feb1391 Reviewed-by: Lars Knoll --- src/corelib/json/qjsonvalue.cpp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index 76e5ae562f..c9f3ec35fe 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -269,25 +269,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; } -- cgit v1.2.3 From e81877218b2c5f5321a2032e602e7255f370e72a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 1 Jun 2016 09:58:48 +0000 Subject: Revert "QObject::connect: reduce generated code size for statics and functors" This reverts commit 2e4191eadce4cfe944afd0baf37f06bbcb65c5f4. The change is backwards compatible but not forwards, so it can't appear past the .0 release. Change-Id: I390c5e80795a9b3b27f6edcab79f7892a79c3564 Reviewed-by: Marc Mutz --- src/corelib/kernel/qobject_impl.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index b4091a4f1c..6140ae775e 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -126,7 +126,7 @@ namespace QtPrivate { inline void destroyIfLastRef() Q_DECL_NOTHROW { if (!m_ref.deref()) m_impl(Destroy, this, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); } - inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } + inline bool compare(void **a) { bool ret; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, Q_NULLPTR); } protected: ~QSlotObjectBase() {} @@ -172,9 +172,10 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: // not implemented - case NumOperations: - Q_UNUSED(ret); + case Compare: + *ret = false; // not implemented + break; + case NumOperations: ; } } public: @@ -196,9 +197,10 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: // not implemented - case NumOperations: - Q_UNUSED(ret); + case Compare: + *ret = false; // not implemented + break; + case NumOperations: ; } } public: -- cgit v1.2.3 From 7b8a553a130125ef4cf2592879ea8c438aa3d966 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 May 2016 13:18:21 -0300 Subject: Remove the code for QObject::connect for non-C++11 compilers It's required now in Qt 5.7 (at least the required features of rvalue references and variadic templates) Change-Id: I87e17314d8b24ae983b1fffd145364c52f9bb6c3 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.h | 23 -- src/corelib/kernel/qobject_impl.h | 29 --- src/corelib/kernel/qobjectdefs_impl.h | 381 ---------------------------------- 3 files changed, 433 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1f3d3dcfc7..e99c8f35f3 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -299,7 +299,6 @@ public: connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, const QObject *context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { -#if defined (Q_COMPILER_VARIADIC_TEMPLATES) typedef QtPrivate::FunctionPointer SignalType; const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount::Value; @@ -307,28 +306,6 @@ public: "Signal and slot arguments are not compatible."); const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0; typedef typename QtPrivate::FunctorReturnType::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 SlotType ; - typedef QtPrivate::FunctionPointer 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::value), - "Signal and slot arguments are not compatible."); -#endif Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible::value), "Return type of the slot is not compatible with the return type of the signal."); diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 6140ae775e..aa68c9c1ad 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 struct TypesAreDeclaredMetaType { enum { Value = false }; }; - template <> struct TypesAreDeclaredMetaType { enum { Value = true }; }; - template struct TypesAreDeclaredMetaType > { enum { Value = QMetaTypeId2::Defined && TypesAreDeclaredMetaType::Value }; }; - - template ::Value > struct ConnectionTypes - { static const int *types() { return 0; } }; - template <> struct ConnectionTypes - { static const int *types() { static const int t[1] = { 0 }; return t; } }; - template struct ConnectionTypes, true> - { static const int *types() { static const int t[2] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes >, true> - { static const int *types() { static const int t[3] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes > >, true> - { static const int *types() { static const int t[4] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes > > >, true> - { static const int *types() { static const int t[5] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes > > > >, true> - { static const int *types() { static const int t[6] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template - struct ConnectionTypes > > > > >, true> - { static const int *types() { static const int t[7] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; -#else template struct TypesAreDeclaredMetaType { enum { Value = false }; }; template <> struct TypesAreDeclaredMetaType> { enum { Value = true }; }; template struct TypesAreDeclaredMetaType > @@ -101,7 +73,6 @@ namespace QtPrivate { { static const int *types() { return Q_NULLPTR; } }; template struct ConnectionTypes, true> { static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper::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 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 struct List { typedef Head Car; typedef Tail Cdr; }; - template struct List_Left { typedef List::Value > Value; }; - template struct List_Left { typedef void Value; }; -#else // With variadic template, lists are represented using a variadic template argument instead of the lisp way template struct List {}; template struct List { typedef Head Car; typedef List Cdr; }; @@ -79,7 +74,6 @@ namespace QtPrivate { typedef typename List_Append,typename List_Left::Value>::Value Value; }; template struct List_Left { typedef List<> Value; }; -#endif // List_Select returns (via typedef Value) the Nth element of the list L template struct List_Select { typedef typename List_Select::Value Value; }; template struct List_Select { typedef typename L::Car Value; }; @@ -100,13 +94,11 @@ namespace QtPrivate { if (container.data) *reinterpret_cast(container.data) = value; } -#ifdef Q_COMPILER_RVALUE_REFS template void operator,(T &&value, const ApplyReturnValue &container) { if (container.data) *reinterpret_cast(container.data) = value; } -#endif template void operator,(T, const ApplyReturnValue &) {} @@ -127,364 +119,6 @@ namespace QtPrivate { The Functor 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 struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; }; - //Pointers to member functions - template struct FunctionPointer - { - typedef Obj Object; - typedef void Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (); - enum {ArgumentCount = 0, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1); - enum {ArgumentCount = 1, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)((*reinterpret_cast::Type *>(arg[1]))), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2); - enum {ArgumentCount = 2, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3); - enum {ArgumentCount = 3, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template - struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; - - //Pointers to const member functions - template struct FunctionPointer - { - typedef Obj Object; - typedef void Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) () const; - enum {ArgumentCount = 0, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1) const; - enum {ArgumentCount = 1, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)((*reinterpret_cast::Type *>(arg[1]))), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2) const; - enum {ArgumentCount = 2, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const; - enum {ArgumentCount = 3, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const; - enum {ArgumentCount = 4, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const; - enum {ArgumentCount = 5, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template - struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const; - enum {ArgumentCount = 6, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; - - //Static functions - template struct FunctionPointer - { - typedef void Arguments; - typedef Ret (*Function) (); - typedef Ret ReturnType; - enum {ArgumentCount = 0, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { f(), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef List Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1); - enum {ArgumentCount = 1, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) - { f(*reinterpret_cast::Value>::Type *>(arg[1])), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef List > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2); - enum {ArgumentCount = 2, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f(*reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef List > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3); - enum {ArgumentCount = 3, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef List > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef List > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef List > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; - - //Functors - template struct Functor; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue(arg[0]); } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f(*reinterpret_cast::Value>::Type *>(arg[1])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; -#else template struct IndexesList {}; template struct IndexesAppend; template struct IndexesAppend, Right> @@ -558,7 +192,6 @@ namespace QtPrivate { FunctorCall::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 struct AreArgumentsCompatible { enum { value = true }; }; template<> struct AreArgumentsCompatible { enum { value = true }; }; -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template struct CheckCompatibleArguments { enum { value = false }; }; - template <> struct CheckCompatibleArguments { enum { value = true }; }; - template struct CheckCompatibleArguments { enum { value = true }; }; - template struct CheckCompatibleArguments, List > - { - enum { value = AreArgumentsCompatible::Type, typename RemoveConstRef::Type>::value - && CheckCompatibleArguments::value }; - }; -#else template struct CheckCompatibleArguments { enum { value = false }; }; template <> struct CheckCompatibleArguments, List<>> { enum { value = true }; }; template struct CheckCompatibleArguments> { enum { value = true }; }; @@ -597,9 +220,7 @@ namespace QtPrivate { enum { value = AreArgumentsCompatible::Type, typename RemoveConstRef::Type>::value && CheckCompatibleArguments, List>::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 static D dummy(); typedef decltype(dummy().operator()((dummy())...)) Value; }; -#endif - } QT_END_NAMESPACE -- cgit v1.2.3 From 86b612d037da59edf482d8a7d4df5ef97f47fb42 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 2 Jun 2016 14:28:34 +0300 Subject: QXmlStreamWriter: don't call virtual QTextCodec::name() twice Just cache and reuse result. Change-Id: I2ada2eced7c272c041013d35b59eeb176ed04659 Reviewed-by: Edward Welbourne --- src/corelib/xml/qxmlstream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 8e62804025..df5f3711cc 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3790,7 +3790,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 +3814,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) -- cgit v1.2.3 From dc0ae02ebc8e221f952829230c0301a718a6f10b Mon Sep 17 00:00:00 2001 From: Volker Krause Date: Wed, 1 Jun 2016 20:46:07 +0200 Subject: CMake: Add imported target for qdoc. Change-Id: Ic950a4171830c83fb44cab13f79e593e5ea1ed52 Reviewed-by: Stephen Kelly --- src/corelib/Qt5CoreConfigExtras.cmake.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/corelib') 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) -- cgit v1.2.3 From f9c60038bf098015172998c2a216dd02672cd96b Mon Sep 17 00:00:00 2001 From: Alejandro Exojo Date: Sun, 8 May 2016 17:34:26 +0200 Subject: Fix QVariantAnimation documentation Since 5.0, this class is not abstract. Only the documentation of updateCurrentValue was updated at that time. Fix the class reference and the mentions of the class being abstract in the Animation Framework overview. Change-Id: I8ef9accb0b870dc8eb75bfc74361c7f2ad8d1d8b Reviewed-by: Venugopal Shivashankar Reviewed-by: Frederik Gladhorn --- src/corelib/animation/qvariantanimation.cpp | 6 ++---- src/corelib/doc/src/animation.qdoc | 11 ++++++----- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 1322b8c810..d2545bfb88 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -48,15 +48,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 @@ -69,7 +67,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 e5e67cf503..304eb9d112 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 -- cgit v1.2.3 From 862fa24179505ef725ff78bb64bdabd54bd00c95 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 20 May 2016 23:56:19 +0200 Subject: Optimize QJsonObject::operator== The old code iterated through one QJsonObject and looked up the key in the other, comparing the values. It had linearithmic complexity, and created one QString 'key' per element. Since the entries in a QJsonObject are lexicographically ordered, we can, however, just walk through the two objects in lock-step and compare corresponding entries (at the same index) with each other. Doing so saves O(N) QString creations and QJsonObject::value() calls, and makes operator== linear in the number of elements. Change-Id: Ib46ee0c1008b7f114454e282b6bd2bfcdbe59e2a Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 2 ++ src/corelib/json/qjsonobject.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index c52a37ba2b..b7de24d165 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -670,6 +670,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 b83c8dd19a..f5fd76eac0 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -545,8 +545,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; } -- cgit v1.2.3 From 7a4ce3cbccbdce920f3e0d0f82fe9d707d50f393 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 30 Mar 2016 13:19:03 +0300 Subject: QString: remove unnecessary copy in replace() When a copy is needed, replace_helper() takes care of that for us. Change-Id: I9e5c89cb70b2902c96062a9edaf77fedda6ddb2c Reviewed-by: Edward Welbourne --- src/corelib/tools/qstring.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 940fd5817b..cf36be1f7c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2346,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()); } /*! -- cgit v1.2.3 From 5a15545ee274a9caa33014755a3fdb7022c7ea8c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 8 Jun 2016 10:01:51 +0200 Subject: QDebug: fix streaming of QChars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 9ef3ff30 introduced a new function, putUcs4(), to output QChar, char16_t, char32_t as a, possibly escaped, character literal, but got the order of stream modifiers wrong. Instead of applying the field width to the 'ucs' streaming, it applied it to the prefix '\u'. The same problem exists for the pad char, leading to the result '00\ue4' for a QChar containing ä (LATIN SMALL LETTER A WITH DIAERESIS) Fix by reordering the elements streamed so that the prefixes come last. Added a test. Change-Id: I6eaa0586501b9e780aaa3bb5dcec0e5c2f86a219 Reviewed-by: Thiago Macieira --- src/corelib/io/qdebug.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 81af96b96b..a1d7d9806d 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -160,16 +160,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('\''); } -- cgit v1.2.3 From 767319a5aac2462df84431917b3724f884091036 Mon Sep 17 00:00:00 2001 From: Luca Bellonda Date: Wed, 1 Jun 2016 00:06:13 +0200 Subject: Add support for 8bit encodings not ASCII compatible in QXMLStreamWriter. When using a 8 bit encoding to write a file, a test discovers if the encoding is really ASCII compatible by examining a letter and one of the XML reserved characters. EBCDIC, in the current base, was not well handled. [ChangeLog][QtCore][QXmlStreamWriter] Fixed a bug that prevented the generation of valid XML files when using encoding with 8 bit per character but not ASCII compatible. QXMLStreamWriter generated XML markup using always ASCII in this case. Change-Id: I9c86a122dd91b2290d50c358638442f99777d4ae Reviewed-by: Thiago Macieira --- src/corelib/xml/qxmlstream.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 64a130e45a..a235145669 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3019,10 +3019,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 -- cgit v1.2.3 From 43ff604f9453edb24154c2ab5ea72bafe0fc501d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 8 Jun 2016 19:03:19 -0700 Subject: x86: Fix build with BMI but no LZCNT extensions The GCC builtins for clzs and ctzs are enabled when the x86 extension for LZCNT and TZCNT are enabled. The use of only __BMI__ in commit f5f47987ce369aa3f7553e6c0da509461a1ddf1a was incorrect. But GCC needs both BMI and LZCNT enabled to enable this builtin. Change-Id: I1cc7601489634e96833cfffd145647e9fc9f2f51 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qalgorithms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index 14465240b4..4f704d6764 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -626,7 +626,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) Q_DECL_NOT Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) -# if QT_HAS_BUILTIN(__builtin_ctzs) || defined(__BMI__) +# if QT_HAS_BUILTIN(__builtin_ctzs) || (defined(__LZCNT__) && defined(__BMI__)) return v ? __builtin_ctzs(v) : 16U; # else return v ? __builtin_ctz(v) : 16U; @@ -689,7 +689,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTH Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) -# if QT_HAS_BUILTIN(__builtin_clzs) || defined(__BMI__) +# if QT_HAS_BUILTIN(__builtin_clzs) || (defined(__LZCNT__) && defined(__BMI__)) return v ? __builtin_clzs(v) : 16U; # else return v ? __builtin_clz(v)-16U : 16U; -- cgit v1.2.3 From 0a78d918f0f411e0da2242a84a396f169154f5d6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 5 Jun 2015 00:41:36 +0200 Subject: Replace qAllocMore with a pair of more useful functions The first is "exact", not "more": qCalculateBlockSize. It ensures that there's no overflow in multiplying, adding the header size or when converting back to an int. The second is the replacement for qAllocMore: it calculates the block size like the first, but increases the block size to accommodate future appends. The number of elements that fit in the block is also returned. Task-number: QTBUG-41230 Change-Id: I52dd43c12685407bb9a6ffff13f5da09f816e667 Reviewed-by: Lars Knoll --- src/corelib/tools/qarraydata.cpp | 34 +++++------- src/corelib/tools/qbytearray.cpp | 112 +++++++++++++++++++++++++++++++++++---- src/corelib/tools/qlist.cpp | 29 ++++------ src/corelib/tools/qstring.cpp | 11 ++-- src/corelib/tools/qtools_p.h | 14 +++-- 5 files changed, 143 insertions(+), 57 deletions(-) (limited to 'src/corelib') 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::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(::malloc(allocSize)); if (header) { diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 2efe3c1a86..c9d6f4e411 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::max(); + + unsigned bytes; + if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) || + Q_UNLIKELY(add_overflow(bytes, header, &bytes))) + return std::numeric_limits::max(); + if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB + return std::numeric_limits::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::max(),std::numeric_limits::max() + }; + + unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize)); + if (int(bytes) < 0) // catches std::numeric_limits::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(::realloc(d, sizeof(Data) + alloc)); + + Data *x = static_cast(::realloc(d, blockSize)); Q_CHECK_PTR(x); x->alloc = alloc; x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0; 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(::malloc(DataHeaderSize + alloc * sizeof(void *))); + auto blockInfo = qCalculateGrowingBlockSize(nl, sizeof(void *), DataHeaderSize); + Data* t = static_cast(::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(::malloc(DataHeaderSize + alloc * sizeof(void *))); + Data* t = static_cast(::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(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + Data *x = static_cast(::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(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + auto r = qCalculateGrowingBlockSize(d->alloc + growth, sizeof(void *), DataHeaderSize); + Data *x = static_cast(::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/qstring.cpp b/src/corelib/tools/qstring.cpp index cf36be1f7c..85da174366 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1760,10 +1760,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)) { @@ -1777,7 +1780,7 @@ void QString::reallocData(uint alloc, bool grow) Data::deallocate(d); d = x; } else { - Data *p = static_cast(::realloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Data *p = static_cast(::realloc(d, blockSize)); Q_CHECK_PTR(p); d = p; d->alloc = alloc; 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 +#include 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::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 -- cgit v1.2.3 From b05741937c2827c05d2160ccf98f389eb03b6f35 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Nov 2015 19:22:43 -0800 Subject: Plug padding holes in QHostAddressPrivate On ABIs where quint64 is aligned on 8-byte boundaries (such 32-bit Windows and all 64-bit systems), there was a padding hole of 4 bytes between QHostAddressPrivate::a and the anonymous union. If we move the member to after the union, there is no hole anymore. That operation causes the tail padding to grow from 3 to 7 bytes. Since we also don't need full 32 bits for the protocol, we can shrink the structure by 8 bytes on those architectures and by 4 bytes on 32-bit Unix systems. Change-Id: I461e9fc7199748faa187ffff1415d6601a7bd777 Reviewed-by: hjk --- src/corelib/global/qhooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp index da401ffd78..b91ec64786 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. - 4 + 5 }; Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0])); -- cgit v1.2.3 From ea86f736404bab170ebfd75af6ee0f594e10f0f7 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 8 Jun 2016 16:14:04 +0200 Subject: Mention extension in QFileInfo's suffix-related documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier for users to find out how to get a file's extension when browsing docs. Change-Id: I08a1b620dea5432462133324824fae85754b9a09 Task-number: QTBUG-53380 Reviewed-by: Topi Reiniö --- src/corelib/io/qfileinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index dd194594c9..cb1ce6fd65 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -814,7 +814,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 '.'. @@ -833,7 +833,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 '.'. -- cgit v1.2.3