From 70e6e9fe590590f602dee230a64870365d9301aa Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 17 Sep 2019 07:35:26 -0700 Subject: Filesystem: avoid crashes on exit in case the locale codec is null On exit, QLocale::codecForLocale() can return null as the codec may have already been destroyed. In that case, pretend that Latin1 was the locale, so any file name is acceptable. This matches QString: QTextCodec *codec = QTextCodec::codecForLocale(); if (codec) return codec->toUnicode(str, size); #endif // textcodec return fromLatin1(str, size); Note that if we're wrong and the locale was *not* Latin1, files that you had a name to may not be encoded or decoded the same way. Fixes: QTBUG-78446 Change-Id: Iece6e011237e4ab284ecfffd15c54077728a17ca Reviewed-by: Edward Welbourne --- src/corelib/io/qfilesystemiterator_unix.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp index 92ebdf0341..0d178d062a 100644 --- a/src/corelib/io/qfilesystemiterator_unix.cpp +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -69,7 +69,9 @@ static bool checkNameDecodable(const char *d_name, qsizetype len) # ifdef QT_LOCALE_IS_UTF8 int mibEnum = 106; # else - int mibEnum = codec->mibEnum(); + int mibEnum = 4; // Latin 1 + if (codec) + mibEnum = codec->mibEnum(); # endif if (Q_LIKELY(mibEnum == 106)) // UTF-8 return QUtf8::isValidUtf8(d_name, len).isValidUtf8; -- cgit v1.2.3 From 1872d1a41de0d4994c799c8d7dd4e72aaf49c677 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 28 Jul 2019 08:05:44 -0700 Subject: Doc: Q_FLAG should be applied to the enum, not the QFlags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit moc extracts he name that is inthe Q_FLAG macro and that gets used in qDebug(). As the documentation described, qDebug would have printed: QFlags(QLibrary::ResolveAllSymbolsHint) which doesn't compile (though we could have partially specialized QFlags> to be QFlags). The semantically correct output is: QFlags(QLibrary::ResolveAllSymbolsHint) which is what this change gets. The ideal output would be: LoadHints(QLibrary::ResolveAllSymbolsHint) But that's not a doc change. Fixes: QTBUG-77216 Change-Id: I0635172f4f2a4c51a435fffd15b59a859886e90c Reviewed-by: Mårten Nordheim --- src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp index 1e31a5292f..1966f8195a 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp @@ -416,7 +416,7 @@ public: LoadArchiveMemberHint = 0x04 }; Q_DECLARE_FLAGS(LoadHints, LoadHint) - Q_FLAG(LoadHints) + Q_FLAG(LoadHint) ... } //! [39] -- cgit v1.2.3 From abfac029ceaf6c3199694a505f312ace347b8245 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 14 Aug 2019 10:34:18 -0700 Subject: QFileInfo: clarify documentation about handling of symlink attributes On Windows, shortcut ".lnk" files are treated as symlinks, and attribute queries on a shortcut file return the results for the shortcut target. Fixes: QTBUG-77523 Change-Id: I907a43cd9a714da288a2fffd15bada7eba37d3ba Reviewed-by: Volker Hilsheimer --- src/corelib/io/qfileinfo.cpp | 86 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 11 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 998382021d..82d848eba0 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -249,17 +249,18 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) isSymLink(). The symLinkTarget() function provides the name of the file the symlink points to. - On Unix (including \macos and iOS), the symlink has the same size() has - the file it points to, because Unix handles symlinks - transparently; similarly, opening a symlink using QFile - effectively opens the link's target. For example: + On Unix (including \macos and iOS), the property getter functions in this + class return the properties such as times and size of the target file, not + the symlink, because Unix handles symlinks transparently. Opening a symlink + using QFile effectively opens the link's target. For example: \snippet code/src_corelib_io_qfileinfo.cpp 0 - On Windows, symlinks (shortcuts) are \c .lnk files. The reported - size() is that of the symlink (not the link's target), and - opening a symlink using QFile opens the \c .lnk file. For - example: + On Windows, symlinks (shortcuts) are \c .lnk files. Similarly to Unix + systems, the property getters return the size of the targeted file, not + the \c .lnk file itself. Please note this behavior is deprecated and will + likely be removed in a future version of Qt, after which \c .lnk files will + be treated as regular files. \snippet code/src_corelib_io_qfileinfo.cpp 1 @@ -904,6 +905,9 @@ QDir QFileInfo::absoluteDir() const /*! Returns \c true if the user can read the file; otherwise returns \c false. + If the file is a symlink, this function returns true if the target is + readable (not the symlink). + \note If the \l{NTFS permissions} check has not been enabled, the result on Windows will merely reflect whether the file exists. @@ -921,6 +925,9 @@ bool QFileInfo::isReadable() const /*! Returns \c true if the user can write to the file; otherwise returns \c false. + If the file is a symlink, this function returns true if the target is + writeable (not the symlink). + \note If the \l{NTFS permissions} check has not been enabled, the result on Windows will merely reflect whether the file is marked as Read Only. @@ -938,6 +945,9 @@ bool QFileInfo::isWritable() const /*! Returns \c true if the file is executable; otherwise returns \c false. + If the file is a symlink, this function returns true if the target is + executable (not the symlink). + \sa isReadable(), isWritable(), permission() */ bool QFileInfo::isExecutable() const @@ -952,8 +962,13 @@ bool QFileInfo::isExecutable() const /*! Returns \c true if this is a `hidden' file; otherwise returns \c false. - \b{Note:} This function returns \c true for the special entries - "." and ".." on Unix, even though QDir::entryList threats them as shown. + \b{Note:} This function returns \c true for the special entries "." and + ".." on Unix, even though QDir::entryList threats them as shown. And note + that, since this function inspects the file name, on Unix it will inspect + the name of the symlink, if this file is a symlink, not the target's name. + + On Windows, this function returns \c true if the target file is hidden (not + the symlink). */ bool QFileInfo::isHidden() const { @@ -992,6 +1007,9 @@ bool QFileInfo::isNativePath() const link to a file. Returns \c false if the object points to something which isn't a file, such as a directory. + If the file is a symlink, this function returns true if the target is a + regular file (not the symlink). + \sa isDir(), isSymLink(), isBundle() */ bool QFileInfo::isFile() const @@ -1007,6 +1025,9 @@ bool QFileInfo::isFile() const Returns \c true if this object points to a directory or to a symbolic link to a directory; otherwise returns \c false. + If the file is a symlink, this function returns true if the target is a + directory (not the symlink). + \sa isFile(), isSymLink(), isBundle() */ bool QFileInfo::isDir() const @@ -1024,6 +1045,9 @@ bool QFileInfo::isDir() const Returns \c true if this object points to a bundle or to a symbolic link to a bundle on \macos and iOS; otherwise returns \c false. + If the file is a symlink, this function returns true if the target is a + bundle (not the symlink). + \sa isDir(), isSymLink(), isFile() */ bool QFileInfo::isBundle() const @@ -1045,7 +1069,8 @@ bool QFileInfo::isBundle() const the \l{symLinkTarget()}{link's target}. In addition, true will be returned for shortcuts (\c *.lnk files) on - Windows. Opening those will open the \c .lnk file itself. + Windows. This behavior is deprecated and will likely change in a future + version of Qt. Opening those will open the \c .lnk file itself. Example: @@ -1136,6 +1161,9 @@ QString QFileInfo::symLinkTarget() const milliseconds). On Windows, it will return an empty string unless the \l{NTFS permissions} check has been enabled. + If the file is a symlink, this function returns the owner of the target + (not the symlink). + \sa ownerId(), group(), groupId() */ QString QFileInfo::owner() const @@ -1152,6 +1180,9 @@ QString QFileInfo::owner() const On Windows and on systems where files do not have owners this function returns ((uint) -2). + If the file is a symlink, this function returns the id of the owner of the target + (not the symlink). + \sa owner(), group(), groupId() */ uint QFileInfo::ownerId() const @@ -1171,6 +1202,9 @@ uint QFileInfo::ownerId() const This function can be time consuming under Unix (in the order of milliseconds). + If the file is a symlink, this function returns the owning group of the + target (not the symlink). + \sa groupId(), owner(), ownerId() */ QString QFileInfo::group() const @@ -1187,6 +1221,9 @@ QString QFileInfo::group() const On Windows and on systems where files do not have groups this function always returns (uint) -2. + If the file is a symlink, this function returns the id of the group owning the + target (not the symlink). + \sa group(), owner(), ownerId() */ uint QFileInfo::groupId() const @@ -1212,6 +1249,9 @@ uint QFileInfo::groupId() const Example: \snippet code/src_corelib_io_qfileinfo.cpp 10 + If the file is a symlink, this function checks the permissions of the + target (not the symlink). + \sa isReadable(), isWritable(), isExecutable() */ bool QFileInfo::permission(QFile::Permissions permissions) const @@ -1234,6 +1274,9 @@ bool QFileInfo::permission(QFile::Permissions permissions) const \note The result might be inaccurate on Windows if the \l{NTFS permissions} check has not been enabled. + + If the file is a symlink, this function returns the permissions of the + target (not the symlink). */ QFile::Permissions QFileInfo::permissions() const { @@ -1251,6 +1294,9 @@ QFile::Permissions QFileInfo::permissions() const Returns the file size in bytes. If the file does not exist or cannot be fetched, 0 is returned. + If the file is a symlink, the size of the target file is returned + (not the symlink). + \sa exists() */ qint64 QFileInfo::size() const @@ -1280,6 +1326,9 @@ qint64 QFileInfo::size() const the time the file was created, metadataChangeTime() to get the time its metadata was last changed, or lastModified() to get the time it was last modified. + If the file is a symlink, the time of the target file is returned + (not the symlink). + \sa birthTime(), metadataChangeTime(), lastModified(), lastRead() */ QDateTime QFileInfo::created() const @@ -1298,6 +1347,9 @@ QDateTime QFileInfo::created() const If the file birth time is not available, this function returns an invalid QDateTime. + If the file is a symlink, the time of the target file is returned + (not the symlink). + \sa lastModified(), lastRead(), metadataChangeTime() */ QDateTime QFileInfo::birthTime() const @@ -1312,6 +1364,9 @@ QDateTime QFileInfo::birthTime() const user writes or sets inode information (for example, changing the file permissions). + If the file is a symlink, the time of the target file is returned + (not the symlink). + \sa lastModified(), lastRead() */ QDateTime QFileInfo::metadataChangeTime() const @@ -1322,6 +1377,9 @@ QDateTime QFileInfo::metadataChangeTime() const /*! Returns the date and local time when the file was last modified. + If the file is a symlink, the time of the target file is returned + (not the symlink). + \sa birthTime(), lastRead(), metadataChangeTime(), fileTime() */ QDateTime QFileInfo::lastModified() const @@ -1335,6 +1393,9 @@ QDateTime QFileInfo::lastModified() const On platforms where this information is not available, returns the same as lastModified(). + If the file is a symlink, the time of the target file is returned + (not the symlink). + \sa birthTime(), lastModified(), metadataChangeTime(), fileTime() */ QDateTime QFileInfo::lastRead() const @@ -1348,6 +1409,9 @@ QDateTime QFileInfo::lastRead() const Returns the file time specified by \a time. If the time cannot be determined, an invalid date time is returned. + If the file is a symlink, the time of the target file is returned + (not the symlink). + \sa QFile::FileTime, QDateTime::isValid() */ QDateTime QFileInfo::fileTime(QFile::FileTime time) const -- cgit v1.2.3 From dc042c6deea7e90b4a9dfcffdc33cbe61df421bd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 24 Sep 2019 16:12:22 +0200 Subject: Windows: QSysInfo::prettyProductName(): Improve version formatting For Windows 10 and higher, the SP version and major/minor versions are not relevant any more; the release id (displayed by the winver tool as "Version" should be displayed instead. Add helpers and change the output accordingly. For Windows 7, output the build number. [ChangeLog][QtCore][Windows] QSysInfo::prettyProductName() now returns a version including the Windows 10 release id or Windows 7 build number respectively, resembling the version string displayed by the winver tool. Change-Id: Ia783272a0da234d2f7ff35c4a9a6fc296da277e0 Reviewed-by: Volker Hilsheimer --- src/corelib/global/qglobal.cpp | 70 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 13 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index dfd5137703..123aeb1f7c 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -48,6 +48,10 @@ #include "qoperatingsystemversion_p.h" #if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) || defined(Q_OS_WINRT) #include "qoperatingsystemversion_win_p.h" +# if QT_CONFIG(settings) +# include "qsettings.h" +# include "qvariant.h" +# endif #endif #include @@ -2186,12 +2190,36 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion() QT_WARNING_POP #endif +static QString readRegistryString(const QString &key, const QString &subKey) +{ +#if QT_CONFIG(settings) + QSettings settings(key, QSettings::NativeFormat); + return settings.value(subKey).toString(); +#else + Q_UNUSED(key); + Q_UNUSED(subKey); + return QString(); +#endif +} + +static inline QString windowsVersionKey() { return QStringLiteral(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"); } + +static inline QString windows10ReleaseId() +{ + return readRegistryString(windowsVersionKey(), QStringLiteral("ReleaseId")); +} + +static inline QString windows7Build() +{ + return readRegistryString(windowsVersionKey(), QStringLiteral("CurrentBuild")); +} + static QString winSp_helper() { const auto osv = qWindowsVersionInfo(); const qint16 major = osv.wServicePackMajor; if (major) { - QString sp = QStringLiteral(" SP ") + QString::number(major); + QString sp = QStringLiteral("SP ") + QString::number(major); const qint16 minor = osv.wServicePackMinor; if (minor) sp += QLatin1Char('.') + QString::number(minor); @@ -2904,19 +2932,35 @@ QString QSysInfo::prettyProductName() { #if (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN) const auto version = QOperatingSystemVersion::current(); + const int majorVersion = version.majorVersion(); + const QString versionString = QString::number(majorVersion) + QLatin1Char('.') + + QString::number(version.minorVersion()); + QString result = version.name() + QLatin1Char(' '); const char *name = osVer_helper(version); - if (name) - return version.name() + QLatin1Char(' ') + QLatin1String(name) -# if defined(Q_OS_WIN) - + winSp_helper() -# endif - + QLatin1String(" (") + QString::number(version.majorVersion()) - + QLatin1Char('.') + QString::number(version.minorVersion()) - + QLatin1Char(')'); - else - return version.name() + QLatin1Char(' ') - + QString::number(version.majorVersion()) + QLatin1Char('.') - + QString::number(version.minorVersion()); + if (!name) + return result + versionString; + result += QLatin1String(name); +# if !defined(Q_OS_WIN) + return result + QLatin1String(" (") + versionString + QLatin1Char(')'); +# else + // (resembling winver.exe): Windows 10 "Windows 10 Version 1809" + result += QLatin1String(" Version "); + if (majorVersion >= 10) { + const auto releaseId = windows10ReleaseId(); + if (!releaseId.isEmpty()) + result += QLatin1String(" Version ") + releaseId; + return result; + } + // Windows 7: "Windows 7 Version 6.1 (Build 7601: Service Pack 1)" + result += versionString + QLatin1String(" ("); + const auto build = windows7Build(); + if (!build.isEmpty()) + result += QLatin1String("Build ") + build; + const auto servicePack = winSp_helper(); + if (!servicePack.isEmpty()) + result += QLatin1String(": ") + servicePack; + return result + QLatin1Char(')'); +# endif // Windows #elif defined(Q_OS_HAIKU) return QLatin1String("Haiku ") + productVersion(); #elif defined(Q_OS_UNIX) -- cgit v1.2.3 From 06a7aba731a8b0a3027d14b7aa37229d1ed46d32 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 25 Sep 2019 16:06:02 +0200 Subject: Fix QCalendar::isValid(): make it const Spotted in API change review, thanks to Albert Astals Cid. Also added documentation of this method. Change-Id: I2ef2c526a98b571a3cb3bb5f93d1952b1b0d63a9 Reviewed-by: Albert Astals Cid --- src/corelib/time/qcalendar.cpp | 11 ++++++++++- src/corelib/time/qcalendar.h | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/time/qcalendar.cpp b/src/corelib/time/qcalendar.cpp index d706f1d5ab..d308aeba2b 100644 --- a/src/corelib/time/qcalendar.cpp +++ b/src/corelib/time/qcalendar.cpp @@ -701,7 +701,7 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system) calendar being constructed by other means first. With no argument, the default constructor returns the Gregorian calendar. - \sa QCalendar, System + \sa QCalendar, System, isValid() */ QCalendar::QCalendar() @@ -723,6 +723,15 @@ QCalendar::QCalendar(QLatin1String name) QCalendar::QCalendar(QStringView name) : d(QCalendarBackend::fromName(name)) {} +/* + \fn bool QCalendar::isValid() const + + Returns true if this is a valid calendar object. + + Constructing a calendar with an unrecognised calendar name may result in an + invalid object. Use this method to check after creating a calendar by name. +*/ + // Date queries: /*! diff --git a/src/corelib/time/qcalendar.h b/src/corelib/time/qcalendar.h index dd3df76e17..42c8e150c5 100644 --- a/src/corelib/time/qcalendar.h +++ b/src/corelib/time/qcalendar.h @@ -137,7 +137,7 @@ public: explicit QCalendar(QStringView name); // QCalendar is a trivially copyable value type. - bool isValid() { return d != nullptr; } + bool isValid() const { return d != nullptr; } // Date queries: int daysInMonth(int month, int year = Unspecified) const; -- cgit v1.2.3 From 5839714d986f28412c9f9ed4801d1bf9378f7b51 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Thu, 5 Sep 2019 10:23:08 +0300 Subject: Fix QRandomGenerator initialization on AMD CPUs Some AMD CPUs (e.g. AMD A4-6250J and AMD Ryzen 3000-series) have a failing random generation instruction, which always returns 0xffffffff, even when generation was "successful". This code checks if hardware random generator generates four consecutive equal numbers. If it does, then we probably have a failing one and should disable it completely. Change-Id: I38c87920ca2e8cce4143afbff5e453ce3845d11a Fixes: QTBUG-69423 Reviewed-by: Edward Welbourne --- src/corelib/global/qrandom.cpp | 45 ++-------------------------- src/corelib/global/qrandom_p.h | 8 ----- src/corelib/tools/qsimd.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++ src/corelib/tools/qsimd_p.h | 18 +++++++++++ 4 files changed, 88 insertions(+), 51 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index fa26d54afa..b150a29b88 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -90,47 +90,6 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando QT_BEGIN_NAMESPACE -#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) -static qsizetype qt_random_cpu(void *buffer, qsizetype count) Q_DECL_NOTHROW; - -# ifdef Q_PROCESSOR_X86_64 -# define _rdrandXX_step _rdrand64_step -# else -# define _rdrandXX_step _rdrand32_step -# endif - -static QT_FUNCTION_TARGET(RDRND) qsizetype qt_random_cpu(void *buffer, qsizetype count) Q_DECL_NOTHROW -{ - unsigned *ptr = reinterpret_cast(buffer); - unsigned *end = ptr + count; - int retries = 10; - - while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { - if (_rdrandXX_step(reinterpret_cast(ptr))) - ptr += sizeof(qregisteruint)/sizeof(*ptr); - else if (--retries == 0) - goto out; - } - - while (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { - bool ok = _rdrand32_step(ptr); - if (!ok && --retries) - continue; - if (ok) - ++ptr; - break; - } - -out: - return ptr - reinterpret_cast(buffer); -} -#else -static qsizetype qt_random_cpu(void *, qsizetype) -{ - return 0; -} -#endif - enum { // may be "overridden" by a member enum FillBufferNoexcept = true @@ -371,8 +330,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, } qsizetype filled = 0; - if (qt_has_hwrng() && (uint(qt_randomdevice_control) & SkipHWRNG) == 0) - filled += qt_random_cpu(buffer, count); + if (qHasHwrng() && (uint(qt_randomdevice_control) & SkipHWRNG) == 0) + filled += qRandomCpu(buffer, count); if (filled != count && (uint(qt_randomdevice_control) & SkipSystemRNG) == 0) { qsizetype bytesFilled = diff --git a/src/corelib/global/qrandom_p.h b/src/corelib/global/qrandom_p.h index 917a91098e..4a0adff51c 100644 --- a/src/corelib/global/qrandom_p.h +++ b/src/corelib/global/qrandom_p.h @@ -79,14 +79,6 @@ extern Q_CORE_EXPORT QBasicAtomicInteger qt_randomdevice_control; enum { qt_randomdevice_control = 0 }; #endif -inline bool qt_has_hwrng() -{ -#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) - return qCpuHasFeature(RDRND); -#else - return false; -#endif -} QT_END_NAMESPACE diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index ddd715f745..09c276c4e0 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -376,6 +376,38 @@ static quint64 detectProcessorFeatures() features &= ~AllAVX512; } +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) + /** + * Some AMD CPUs (e.g. AMD A4-6250J and AMD Ryzen 3000-series) have a + * failing random generation instruction, which always returns + * 0xffffffff, even when generation was "successful". + * + * This code checks if hardware random generator generates four consecutive + * equal numbers. If it does, then we probably have a failing one and + * should disable it completely. + * + * https://bugreports.qt.io/browse/QTBUG-69423 + */ + if (features & CpuFeatureRDRND) { + const qsizetype testBufferSize = 4; + unsigned testBuffer[4] = {}; + + const qsizetype generated = qRandomCpu(testBuffer, testBufferSize); + + if (Q_UNLIKELY(generated == testBufferSize && + testBuffer[0] == testBuffer[1] && + testBuffer[1] == testBuffer[2] && + testBuffer[2] == testBuffer[3])) { + + fprintf(stderr, "WARNING: CPU random generator seem to be failing, disable hardware random number generation\n"); + fprintf(stderr, "WARNING: RDRND generated: 0x%x 0x%x 0x%x 0x%x\n", + testBuffer[0], testBuffer[1], testBuffer[2], testBuffer[3]); + + features &= ~CpuFeatureRDRND; + } + } +#endif + return features; } @@ -590,4 +622,40 @@ void qDumpCPUFeatures() puts(""); } +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) + +# ifdef Q_PROCESSOR_X86_64 +# define _rdrandXX_step _rdrand64_step +# else +# define _rdrandXX_step _rdrand32_step +# endif + +QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) Q_DECL_NOTHROW +{ + unsigned *ptr = reinterpret_cast(buffer); + unsigned *end = ptr + count; + int retries = 10; + + while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { + if (_rdrandXX_step(reinterpret_cast(ptr))) + ptr += sizeof(qregisteruint)/sizeof(*ptr); + else if (--retries == 0) + goto out; + } + + while (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { + bool ok = _rdrand32_step(ptr); + if (!ok && --retries) + continue; + if (ok) + ++ptr; + break; + } + +out: + return ptr - reinterpret_cast(buffer); +} +#endif + + QT_END_NAMESPACE diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index c36e1e484f..d603631a24 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -346,6 +346,15 @@ extern Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[2]; #endif Q_CORE_EXPORT quint64 qDetectCpuFeatures(); +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) +Q_CORE_EXPORT qsizetype qRandomCpu(void *, qsizetype) Q_DECL_NOTHROW; +#else +static inline qsizetype qRandomCpu(void *, qsizetype) Q_DECL_NOTHROW +{ + return 0; +} +#endif + static inline quint64 qCpuFeatures() { quint64 features = qt_cpu_features[0].load(); @@ -362,6 +371,15 @@ static inline quint64 qCpuFeatures() #define qCpuHasFeature(feature) (((qCompilerCpuFeatures & CpuFeature ## feature) == CpuFeature ## feature) \ || ((qCpuFeatures() & CpuFeature ## feature) == CpuFeature ## feature)) +inline bool qHasHwrng() +{ +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) + return qCpuHasFeature(RDRND); +#else + return false; +#endif +} + #define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \ for (; i < static_cast(qMin(static_cast(length), ((4 - ((reinterpret_cast(ptr) >> 2) & 0x3)) & 0x3))); ++i) -- cgit v1.2.3 From e24c387413b9707622060f381b2a007aa5c814a0 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 20 Sep 2019 09:32:25 +0200 Subject: Short live QtPrivate::{condition_variable,mutex}! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a temporary measure to work around an implementation bug on Integrity: For all other platforms, QtPrivate::condition_variable is just std::condition_variable. On Integrity, it's a class that wraps QWaitCondition to provide the interface of std::condition_variable. This allows the use of std::condition_variable across Qt without running into the Integrity issue. Once we can depend on an more modern Integrity toolchain, removing QtPrivate::condition_variable is a simple mechanical change: s/QtPrivate::condition_variable/std::condition_variable/g; s/QtPrivate::mutex/std::mutex/g; Task-number: QTBUG-78450 Change-Id: I293a99d1cdc48691817b926aa51ecd84556e5e90 Reviewed-by: Mårten Nordheim Reviewed-by: Thiago Macieira --- src/corelib/thread/qwaitcondition_p.h | 153 ++++++++++++++++++++++++++++++++++ src/corelib/thread/thread.pri | 1 + 2 files changed, 154 insertions(+) create mode 100644 src/corelib/thread/qwaitcondition_p.h (limited to 'src/corelib') diff --git a/src/corelib/thread/qwaitcondition_p.h b/src/corelib/thread/qwaitcondition_p.h new file mode 100644 index 0000000000..5133e52e92 --- /dev/null +++ b/src/corelib/thread/qwaitcondition_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QWAITCONDITION_P_H +#define QWAITCONDITION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header +// file may change from version to version without notice, or even be +// removed. +// +// We mean it. +// + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QtPrivate +{ + +#if defined(Q_OS_INTEGRITY) + +class condition_variable; + +class mutex : private QMutex +{ + friend class QtPrivate::condition_variable; +public: + // all special member functions are ok! + // do not expose the (QMutex::Recursive) ctor + // don't use 'using QMutex::lock;' etc as those have the wrong noexcept + + void lock() { return QMutex::lock(); } + void unlock() { return QMutex::unlock(); } + bool try_lock() { return QMutex::tryLock(); } +}; + +class condition_variable : private QWaitCondition +{ +public: + // all special member functions are ok! + + void notify_one() { QWaitCondition::wakeOne(); } + void notify_all() { QWaitCondition::wakeAll(); } + + void wait(std::unique_lock &lock) { QWaitCondition::wait(lock.mutex()); } + template + void wait(std::unique_lock &lock, Predicate p) + { + while (!p()) + wait(lock); + } + + template + std::cv_status wait_for(std::unique_lock &lock, + const std::chrono::duration &d) + { + return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{d}) + ? std::cv_status::no_timeout + : std::cv_status::timeout; + } + template + bool wait_for(std::unique_lock &lock, + const std::chrono::duration &d, Predicate p) + { + const auto timer = QDeadlineTimer{d}; + while (!p()) { + if (!QWaitCondition::wait(lock.mutex(), timer)) + return p(); + } + return true; + } + + template + std::cv_status wait_until(std::unique_lock &lock, + const std::chrono::time_point &t) + { + return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{t}) + ? std::cv_status::no_timeout + : std::cv_status::timeout; + } + + template + bool wait_until(std::unique_lock &lock, + const std::chrono::time_point &t, Predicate p) + { + const auto timer = QDeadlineTimer{t}; + while (!p()) { + if (!QWaitCondition::wait(lock.mutex(), timer)) + return p(); + } + return true; + } + +}; + +#else // Integrity + +using mutex = std::mutex; +using condition_variable = std::condition_variable; + +#endif // Integrity + +} // namespace QtPrivate + +QT_END_NAMESPACE + +#endif /* QWAITCONDITION_P_H */ diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 9fc9af0e65..25cf68a324 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -6,6 +6,7 @@ HEADERS += \ thread/qrunnable.h \ thread/qthread.h \ thread/qthreadstorage.h \ + thread/qwaitcondition_p.h \ thread/qwaitcondition.h SOURCES += \ -- cgit v1.2.3 From 72457ed0764188264ffdadaf75c4a86f98eeba19 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 25 Sep 2019 16:13:02 +0200 Subject: Fix doc of QDateTime::YearRange; include its \since 5.14 Change-Id: I2e6c27953ecce95df3ac4868a6d953596ba115f2 Reviewed-by: Thiago Macieira --- src/corelib/time/qdatetime.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/corelib') diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 13a54c1210..6ed0efe77d 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -3548,6 +3548,7 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT */ /*! + \since 5.14 \enum QDateTime::YearRange This enumerated type describes the range of years (in the Gregorian -- cgit v1.2.3 From 25430f90e6985652be65dec156f010c6d446631f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 25 Sep 2019 15:56:53 +0200 Subject: Fix documentation of qfloat16 Various methods were undocumented and even one that was lacked a \since 5.14 Change-Id: I1e65ed1bb9c5b9de06210d7e18af36539aafc4ec Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.cpp | 47 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index ff2997b73a..2ba4c79374 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -107,10 +107,51 @@ QT_BEGIN_NAMESPACE */ /*! - \internal - Implements qFpClassify() for qfloat16. - */ + \internal + \since 5.14 + bool qfloat16::isInf() const noexcept + + Tests whether this \c qfloat16 value is an infinity. + + \sa qIsInf() +*/ + +/*! + \internal + \since 5.14 + bool qfloat16::isNaN() const noexcept + + Tests whether this \c qfloat16 value is "not a number". + + \sa qIsNaN() +*/ + +/*! + \since 5.14 + bool qfloat16::isNormal() const noexcept + Tests whether this \c qfloat16 value is finite and in normal form. + + \sa qFpClassify() +*/ + +/*! + \internal + \since 5.14 + bool qfloat16::isFinite() const noexcept + + Tests whether this \c qfloat16 value is finite. + + \sa qIsFinite() +*/ + +/*! + \internal + \since 5.14 + Implements qFpClassify() for qfloat16. + + \sa qFpClassify() +*/ int qfloat16::fpClassify() const noexcept { return isInf() ? FP_INFINITE : isNaN() ? FP_NAN -- cgit v1.2.3 From d35de9e1b250ce46739dcb6afb9ae8a0247195c7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Sep 2019 09:12:39 +0200 Subject: Windows/MinGW: Fix posted events timer not stopping Specify the type of the enum value SendPostedEventsWindowsTimerId to be UINT_PTR to work with the g++ interpretation of enumeration signedness and use the correct type for the returned timer id. Fixes: QTBUG-78491 Change-Id: I7b3f306d3f60da7a21500ece5243ac90854ccf1a Reviewed-by: Thiago Macieira --- src/corelib/kernel/qeventdispatcher_win.cpp | 7 +++++-- src/corelib/kernel/qeventdispatcher_win_p.h | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 685d765adb..8ff7637b7e 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -83,7 +83,10 @@ enum { WM_QT_SOCKETNOTIFIER = WM_USER, WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, WM_QT_ACTIVATENOTIFIERS = WM_USER + 2, - SendPostedEventsWindowsTimerId = ~1u +}; + +enum : UINT_PTR { + SendPostedEventsWindowsTimerId = ~UINT_PTR(1) }; class QEventDispatcherWin32Private; @@ -278,7 +281,7 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) // no more input or timer events in the message queue, we can allow posted events to be sent normally now if (d->sendPostedEventsWindowsTimerId != 0) { // stop the timer to send posted events, since we now allow the WM_QT_SENDPOSTEDEVENTS message - KillTimer(d->internalHwnd, d->sendPostedEventsWindowsTimerId); + KillTimer(d->internalHwnd, SendPostedEventsWindowsTimerId); d->sendPostedEventsWindowsTimerId = 0; } (void) d->wakeUps.fetchAndStoreRelease(0); diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index dbad2a5450..a3a0cd1c2f 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -173,7 +173,8 @@ public: // for controlling when to send posted events QAtomicInt serialNumber; - int lastSerialNumber, sendPostedEventsWindowsTimerId; + int lastSerialNumber; + UINT_PTR sendPostedEventsWindowsTimerId; QAtomicInt wakeUps; // timers -- cgit v1.2.3 From 401e81063fd27639e0b3eaf4b4745faa186ceeb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 27 Sep 2019 12:29:59 +0200 Subject: Replace use of deprecated API in macOS event dispatchers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I077ba12b406f662ba22b2f2cddf0171963335739 Reviewed-by: Tor Arne Vestbø Reviewed-by: Timur Pocheptsov --- src/corelib/kernel/qeventdispatcher_cf.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 33c231987f..b9e334f1f4 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -423,7 +423,7 @@ bool QEventDispatcherCoreFoundation::processPostedEvents() m_processEvents.processedPostedEvents = true; qCDebug(lcEventDispatcher) << "Sending posted events for" - << QEventLoop::ProcessEventsFlags(m_processEvents.flags.load()); + << QEventLoop::ProcessEventsFlags(m_processEvents.flags.loadRelaxed()); QCoreApplication::sendPostedEvents(); return true; -- cgit v1.2.3 From 46201f0e82a7b1629adad196dfa8f7ff1cf4dffd Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 28 Sep 2019 15:52:45 +0200 Subject: QVarLengthArray: Avoid int vs. size_t warnings in operator= Change-Id: I879b62c55e4211d3e4e1a18f6699f26e3f5de1f8 Reviewed-by: Thiago Macieira --- src/corelib/tools/qvarlengtharray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 597e7464cb..ef3a9884bf 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -99,7 +99,7 @@ public: #ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray &operator=(std::initializer_list list) { - resize(list.size()); + resize(int(list.size())); // ### q6sizetype std::copy(list.begin(), list.end(), QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size())); return *this; -- cgit v1.2.3 From 4bd6cd1992fdcdc933861ba646ea9da870670237 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 5 Sep 2019 17:50:17 +0200 Subject: Featurize support for signaling NaN One of our compilers for emscripten coerces all signaling NaNs to quiet ones, so won't do any actual signaling. Anyone relying on them to do so shall be disappointed, so it's better that they know about it at compile-time - or, at least, have the ability to find it out. Put the signaling NaN producers (and remaining (test) code using them) under the control of a feature that's disabled when numeric_limits claims double has no signaling NaN. Assume the bootstrap library doesn't need signaling NaNs. Sadly, until C++20 , there's no contexpr way to test that alleged signalling and quiet NaNs are actually distinct. Added some auto-tests for signaling NaN, including that it's distinct from quiet NaN. Any platform on which the last fails should disable this feature. Task-number: QTBUG-77967 Change-Id: I57e9d14bfe276732cd313887adc9acc354d88f08 Reviewed-by: Joerg Bornemann --- src/corelib/global/qconfig-bootstrapped.h | 1 + src/corelib/global/qnumeric.cpp | 2 ++ src/corelib/global/qnumeric.h | 7 +++++-- src/corelib/global/qnumeric_p.h | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 2e58dabf5f..e6ad80525a 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -109,6 +109,7 @@ # define QT_FEATURE_renameat2 -1 #endif #define QT_FEATURE_sharedmemory -1 +#define QT_FEATURE_signaling_nan -1 #define QT_FEATURE_slog2 -1 #ifdef __GLIBC_PREREQ # define QT_FEATURE_statx (__GLIBC_PREREQ(2, 28) ? 1 : -1) diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index 11440f40a4..9cb9c1283a 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -81,11 +81,13 @@ Q_CORE_EXPORT bool qIsNaN(float f) { return qt_is_nan(f); } */ Q_CORE_EXPORT bool qIsFinite(float f) { return qt_is_finite(f); } +#if QT_CONFIG(signaling_nan) /*! Returns the bit pattern of a signalling NaN as a double. \relates */ Q_CORE_EXPORT double qSNaN() { return qt_snan(); } +#endif /*! Returns the bit pattern of a quiet NaN as a double. diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 6a0c64712f..2771eea64f 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE - Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d); @@ -53,7 +52,9 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val); +#if QT_CONFIG(signaling_nan) Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN(); +#endif Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN(); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf(); @@ -61,7 +62,9 @@ Q_CORE_EXPORT quint32 qFloatDistance(float a, float b); Q_CORE_EXPORT quint64 qFloatDistance(double a, double b); #define Q_INFINITY (QT_PREPEND_NAMESPACE(qInf)()) -#define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)()) +#if QT_CONFIG(signaling_nan) +# define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)()) +#endif #define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)()) QT_END_NAMESPACE diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 21f9cfbef0..86e7997680 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -133,13 +133,14 @@ Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() noexcept return std::numeric_limits::infinity(); } -// Signaling NaN +#if QT_CONFIG(signaling_nan) Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() noexcept { Q_STATIC_ASSERT_X(std::numeric_limits::has_signaling_NaN, "platform has no definition for signaling NaN for type double"); return std::numeric_limits::signaling_NaN(); } +#endif // Quiet NaN Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() noexcept -- cgit v1.2.3