diff options
author | Tarja Sundqvist <[email protected]> | 2025-06-03 13:43:30 +0300 |
---|---|---|
committer | Tarja Sundqvist <[email protected]> | 2025-06-03 13:43:30 +0300 |
commit | 4a6a9dcc73b82cd49a846d5eadadc1835d7b0ec8 (patch) | |
tree | 2f027d908308b8ad503b746cd9012fbc98ea32f2 /src/corelib | |
parent | 3fe9e69e4d7510480544f928e8a07f0f110b2181 (diff) | |
parent | 5d8e9a8415562ba004b38508d91e1fa0254c17d3 (diff) |
Merge tag 'v6.5.6-lts-lgpl' into 6.56.5
Qt 6.5.6-lts-lgpl release
Diffstat (limited to 'src/corelib')
43 files changed, 262 insertions, 120 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 4630a3a587f..4784a310f79 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -316,7 +316,6 @@ qt_internal_add_module(Core text/qstringconverter.cpp # enum Data tools/qcryptographichash.cpp # KeccakNISTInterface/Final io/qdebug.cpp # undef qDebug - io/qsettings.cpp # Space (also in qjsonparser.cpp) NO_PCH_SOURCES compat/removed_api.cpp global/qsimd.cpp @@ -1409,4 +1408,10 @@ foreach(minor_version RANGE ${PROJECT_VERSION_MINOR}) endforeach() qt_internal_extend_target(Core EXTRA_LINKER_SCRIPT_CONTENT "${linker_script_contents}" + + # Workaround for QTBUG-117514: + # Function called by inline methods taking a pointer to a private class as a parameter + EXTRA_LINKER_SCRIPT_EXPORTS + # QFutureInterfaceBase::setContinuation(std::function<void (QFutureInterfaceBase const&)>, QFutureInterfaceBasePrivate*) + "_ZN20QFutureInterfaceBase15setContinuationE*P27QFutureInterfaceBasePrivate" ) diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake index 9a8d02165f2..66f508f3b23 100644 --- a/src/corelib/Qt6AndroidMacros.cmake +++ b/src/corelib/Qt6AndroidMacros.cmake @@ -236,6 +236,10 @@ function(qt6_android_generate_deployment_settings target) _qt_internal_add_android_deployment_property(file_contents "android-no-deploy-qt-libs" ${target} "QT_ANDROID_NO_DEPLOY_QT_LIBS") + __qt_internal_collect_plugin_targets_from_dependencies("${target}" plugin_targets) + __qt_internal_collect_plugin_library_files("${target}" "${plugin_targets}" plugin_targets) + string(APPEND file_contents " \"android-deploy-plugins\":\"${plugin_targets}\",\n") + # App binary string(APPEND file_contents " \"application-binary\": \"${target_output_name}\",\n") @@ -303,7 +307,7 @@ function(qt6_android_generate_deployment_settings target) # content end string(APPEND file_contents "}\n") - file(GENERATE OUTPUT ${deploy_file} CONTENT ${file_contents}) + file(GENERATE OUTPUT ${deploy_file} CONTENT "${file_contents}") set_target_properties(${target} PROPERTIES @@ -554,7 +558,7 @@ function(qt6_android_add_apk_target target) "$<TARGET_FILE:${target}>" "${androiddeployqt_output_path}/${target_file_copy_relative_path}" ) - if(has_depfile_support) + if(has_depfile_support AND FALSE) # TODO: It breaks multi-abi builds. See QTBUG-122838 set(deploy_android_deps_dir "${apk_final_dir}/${target}_deploy_android") set(timestamp_file "${deploy_android_deps_dir}/timestamp") set(dep_file "${deploy_android_deps_dir}/${target}.d") @@ -1007,7 +1011,8 @@ function(_qt_internal_get_android_abi_cmake_dir_path out_path abi) NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_INTERNAL_IS_STANDALONE_TEST) set(cmake_dir "${QT_CONFIG_BUILD_DIR}") else() - set(cmake_dir "${prefix_path}/${QT6_INSTALL_LIBS}/cmake") + string(TOUPPER "${QT_CMAKE_EXPORT_NAMESPACE}" export_namespace_upper) + set(cmake_dir "${prefix_path}/${${export_namespace_upper}_INSTALL_LIBS}/cmake") endif() endif() diff --git a/src/corelib/Qt6CoreDeploySupport.cmake b/src/corelib/Qt6CoreDeploySupport.cmake index 999708185ec..b3cfe29160f 100644 --- a/src/corelib/Qt6CoreDeploySupport.cmake +++ b/src/corelib/Qt6CoreDeploySupport.cmake @@ -437,8 +437,13 @@ function(qt6_deploy_runtime_dependencies) # Specify path to target Qt's qtpaths .exe or .bat file, so windeployqt deploys the correct # libraries when cross-compiling from x86_64 to arm64 windows. - if(__QT_DEPLOY_TARGET_QT_PATHS_PATH) + if(__QT_DEPLOY_TARGET_QT_PATHS_PATH AND EXISTS "${__QT_DEPLOY_TARGET_QT_PATHS_PATH}") list(APPEND tool_options --qtpaths "${__QT_DEPLOY_TARGET_QT_PATHS_PATH}") + else() + message(WARNING + "No qtpaths executable found for target Qt " + "at: ${__QT_DEPLOY_TARGET_QT_PATHS_PATH}. " + "Libraries may not be deployed correctly.") endif() elseif(__QT_DEPLOY_SYSTEM_NAME STREQUAL Darwin) diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index c692839b36f..f7f658d5afe 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -2666,7 +2666,30 @@ function(_qt_internal_setup_deploy_support) else() set(qt_paths_ext "") endif() - set(target_qtpaths_path "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_BINS}/qtpaths${qt_paths_ext}") + + + + set(target_qtpaths_path "") + set(qtpaths_prefix "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_BINS}") + get_property(qt_major_version TARGET "${target}" PROPERTY INTERFACE_QT_MAJOR_VERSION) + if(qt_major_version) + set(target_qtpaths_with_major_version_path + "${qtpaths_prefix}/qtpaths${qt_major_version}${qt_paths_ext}") + if(EXISTS "${target_qtpaths_with_major_version_path}") + set(target_qtpaths_path "${target_qtpaths_with_major_version_path}") + endif() + endif() + + if(NOT target_qtpaths_path) + set(target_qtpaths_path_without_version "${qtpaths_prefix}/qtpaths${qt_paths_ext}") + if(EXISTS "${target_qtpaths_path_without_version}") + set(target_qtpaths_path "${target_qtpaths_path_without_version}") + endif() + endif() + + if(NOT target_qtpaths_path) + message(DEBUG "No qtpaths executable found for deployment purposes.") + endif() file(GENERATE OUTPUT "${QT_DEPLOY_SUPPORT}" CONTENT "cmake_minimum_required(VERSION 3.16...3.21) diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index 7acbae8a5e8..586d84d9497 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -200,7 +200,7 @@ void QObject::setObjectName(const QString &name) void QSettings::beginGroup(const QString &prefix) { - return beginGroup(qToAnyStringViewIgnoringNull(prefix)); + beginGroup(qToAnyStringViewIgnoringNull(prefix)); } int QSettings::beginReadArray(const QString &prefix) diff --git a/src/corelib/debug_script.py b/src/corelib/debug_script.py index 6dee5961524..f6207c6104e 100644 --- a/src/corelib/debug_script.py +++ b/src/corelib/debug_script.py @@ -1,5 +1,5 @@ # Copyright (C) 2017 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 import os import sys diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 58a36893412..02b5e64a69a 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1370,6 +1370,11 @@ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantic # endif #endif +// libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346 +#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) +# define QT_COMPILER_HAS_LWG3346 +#endif + #endif // __cplusplus #endif // QCOMPILERDETECTION_H diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h index 26e22caced9..20701e0e54c 100644 --- a/src/corelib/global/qglobalstatic.h +++ b/src/corelib/global/qglobalstatic.h @@ -41,8 +41,16 @@ template <typename QGS> union Holder ~Holder() { + // TSAN does not support atomic_thread_fence and GCC complains: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97868 + // https://github.com/google/sanitizers/issues/1352 +QT_WARNING_PUSH +#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100 +QT_WARNING_DISABLE_GCC("-Wtsan") +#endif // import changes to *pointer() by other threads before running ~PlainType(): std::atomic_thread_fence(std::memory_order_acquire); +QT_WARNING_POP pointer()->~PlainType(); guard.storeRelease(QtGlobalStatic::Destroyed); } diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index ea281931c12..82857718911 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -87,10 +87,19 @@ void QLibrarySettings::load() } } +namespace { +const QString *qtconfManualPath = nullptr; +} + +void QLibraryInfoPrivate::setQtconfManualPath(const QString *path) +{ + qtconfManualPath = path; +} + static QSettings *findConfiguration() { - if (QLibraryInfoPrivate::qtconfManualPath) - return new QSettings(*QLibraryInfoPrivate::qtconfManualPath, QSettings::IniFormat); + if (qtconfManualPath) + return new QSettings(*qtconfManualPath, QSettings::IniFormat); QString qtconfig = QStringLiteral(":/qt/etc/qt.conf"); if (QFile::exists(qtconfig)) @@ -122,8 +131,6 @@ static QSettings *findConfiguration() return nullptr; //no luck } -const QString *QLibraryInfoPrivate::qtconfManualPath = nullptr; - QSettings *QLibraryInfoPrivate::configuration() { QLibrarySettings *ls = qt_library_settings(); diff --git a/src/corelib/global/qlibraryinfo_p.h b/src/corelib/global/qlibraryinfo_p.h index d3c458290b1..4b471b932e5 100644 --- a/src/corelib/global/qlibraryinfo_p.h +++ b/src/corelib/global/qlibraryinfo_p.h @@ -32,7 +32,7 @@ public: #if QT_CONFIG(settings) static QSettings *configuration(); static void reload(); - static const QString *qtconfManualPath; + static void setQtconfManualPath(const QString *qtconfManualPath); #endif struct LocationInfo diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index f493dce1ea4..95aa9f5dcdd 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -7,6 +7,7 @@ #include <variant> #include <optional> #include <tuple> +#include <type_traits> #ifndef QTYPEINFO_H #define QTYPEINFO_H diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 7acb2ff027c..e925f37fb15 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -283,67 +283,67 @@ using QDebugIfHasDebugStreamContainer = template<typename T> inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec) { - return QtPrivate::printSequentialContainer(debug, "QList", vec); + return QtPrivate::printSequentialContainer(std::move(debug), "QList", vec); } template<typename T, qsizetype P> inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QVarLengthArray<T, P> &vec) { - return QtPrivate::printSequentialContainer(debug, "QVarLengthArray", vec); + return QtPrivate::printSequentialContainer(std::move(debug), "QVarLengthArray", vec); } template <typename T, typename Alloc> inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::vector<T, Alloc> &vec) { - return QtPrivate::printSequentialContainer(debug, "std::vector", vec); + return QtPrivate::printSequentialContainer(std::move(debug), "std::vector", vec); } template <typename T, typename Alloc> inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::list<T, Alloc> &vec) { - return QtPrivate::printSequentialContainer(debug, "std::list", vec); + return QtPrivate::printSequentialContainer(std::move(debug), "std::list", vec); } template <typename T> inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, std::initializer_list<T> list) { - return QtPrivate::printSequentialContainer(debug, "std::initializer_list", list); + return QtPrivate::printSequentialContainer(std::move(debug), "std::initializer_list", list); } template <typename Key, typename T, typename Compare, typename Alloc> inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map) { - return QtPrivate::printSequentialContainer(debug, "std::map", map); // yes, sequential: *it is std::pair + return QtPrivate::printSequentialContainer(std::move(debug), "std::map", map); // yes, sequential: *it is std::pair } template <typename Key, typename T, typename Compare, typename Alloc> inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map) { - return QtPrivate::printSequentialContainer(debug, "std::multimap", map); // yes, sequential: *it is std::pair + return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map); // yes, sequential: *it is std::pair } template <class Key, class T> inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map) { - return QtPrivate::printAssociativeContainer(debug, "QMap", map); + return QtPrivate::printAssociativeContainer(std::move(debug), "QMap", map); } template <class Key, class T> inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map) { - return QtPrivate::printAssociativeContainer(debug, "QMultiMap", map); + return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiMap", map); } template <class Key, class T> inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash) { - return QtPrivate::printAssociativeContainer(debug, "QHash", hash); + return QtPrivate::printAssociativeContainer(std::move(debug), "QHash", hash); } template <class Key, class T> inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash) { - return QtPrivate::printAssociativeContainer(debug, "QMultiHash", hash); + return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash); } template <class T1, class T2> @@ -357,7 +357,7 @@ inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T template <typename T> inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set) { - return QtPrivate::printSequentialContainer(debug, "QSet", set); + return QtPrivate::printSequentialContainer(std::move(debug), "QSet", set); } template <class T> diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 98057222138..3d8c85dceeb 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -347,8 +347,8 @@ void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat) for enabling debugging by default for category \a categoryName. The category name must start with "qt." */ -void QLoggingRegistry::registerEnvironmentOverrideForCategory(QByteArrayView categoryName, - QByteArrayView environment) +void QLoggingRegistry::registerEnvironmentOverrideForCategory(const char *categoryName, + const char *environment) { qtCategoryEnvironmentOverrides.insert(categoryName, environment); } @@ -442,7 +442,7 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) if (it == reg->qtCategoryEnvironmentOverrides.end()) debug = false; else - debug = qEnvironmentVariableIntValue(it.value().data()); + debug = qEnvironmentVariableIntValue(it.value()); } } diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index 69ed1a4f96e..aa38ed895be 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -97,7 +97,7 @@ public: #ifndef QT_BUILD_INTERNAL Q_CORE_EXPORT // always export from QtCore #endif - void registerEnvironmentOverrideForCategory(QByteArrayView categoryName, QByteArrayView environment); + void registerEnvironmentOverrideForCategory(const char *categoryName, const char *environment); void setApiRules(const QString &content); @@ -127,7 +127,7 @@ private: QList<QLoggingRule> ruleSets[NumRuleSets]; QHash<QLoggingCategory *, QtMsgType> categories; QLoggingCategory::CategoryFilter categoryFilter; - QMap<QByteArrayView, QByteArrayView> qtCategoryEnvironmentOverrides; + QMap<QByteArrayView, const char *> qtCategoryEnvironmentOverrides; friend class ::tst_QLoggingRegistry; }; @@ -140,12 +140,12 @@ public: {} private: - static const char *registerOverride(QByteArrayView categoryName, QByteArrayView environment) + static const char *registerOverride(const char *categoryName, const char *environment) { QLoggingRegistry *c = QLoggingRegistry::instance(); if (c) c->registerEnvironmentOverrideForCategory(categoryName, environment); - return categoryName.data(); + return categoryName; } }; diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 41266d8219f..3c74fcb634d 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1494,6 +1494,8 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile) } } +namespace SettingsImpl { + enum { Space = 0x1, Special = 0x2 }; static const char charTraits[256] = @@ -1520,10 +1522,15 @@ static const char charTraits[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +} // namespace SettingsImpl + +using SettingsImpl::charTraits; + bool QConfFileSettingsPrivate::readIniLine(QByteArrayView data, qsizetype &dataPos, qsizetype &lineStart, qsizetype &lineLen, qsizetype &equalsPos) { + using namespace SettingsImpl; qsizetype dataLen = data.size(); bool inQuotes = false; diff --git a/src/corelib/kernel/qeventdispatcher_wasm_p.h b/src/corelib/kernel/qeventdispatcher_wasm_p.h index 9ae92c811be..b2057af6cb7 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm_p.h +++ b/src/corelib/kernel/qeventdispatcher_wasm_p.h @@ -50,7 +50,7 @@ public: void interrupt() override; void wakeUp() override; - static void runOnMainThreadAsync(std::function<void(void)> fn); + static void runOnMainThread(std::function<void(void)> fn); static void socketSelect(int timeout, int socket, bool waitForRead, bool waitForWrite, bool *selectForRead, bool *selectForWrite, bool *socketDisconnect); protected: @@ -87,7 +87,7 @@ private: static void run(std::function<void(void)> fn); static void runAsync(std::function<void(void)> fn); - static void runOnMainThread(std::function<void(void)> fn); + static void runOnMainThreadAsync(std::function<void(void)> fn); static QEventDispatcherWasm *g_mainThreadEventDispatcher; diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 9c7c70a6c88..792fe986563 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2338,7 +2338,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const \since 5.0 Returns the meta-method that corresponds to the given \a signal, or an - invalid QMetaMethod if \a signal is not a signal of the class. + invalid QMetaMethod if \a signal is \c{nullptr} or not a signal of the class. Example: diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 65390d83fc8..a2e9b23ac6c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -252,7 +252,7 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const { QObjectList returnValue; int signal_index = signalIndex(signal); - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (signal_index < 0 || !cd) return returnValue; if (signal_index < cd->signalVectorCount()) { @@ -281,13 +281,17 @@ QObjectList QObjectPrivate::senderList() const return returnValue; } +/*! + \internal + The signalSlotLock() of the sender must be locked while calling this function +*/ inline void QObjectPrivate::ensureConnectionData() { if (connections.loadRelaxed()) return; ConnectionData *cd = new ConnectionData; cd->ref.ref(); - connections.storeRelaxed(cd); + connections.storeRelease(cd); } /*! @@ -452,7 +456,7 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) if (checkDeclarative && isDeclarativeSignalConnected(signalIndex)) return true; - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (!cd) return false; SignalVector *signalVector = cd->signalVector.loadRelaxed(); @@ -475,7 +479,7 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const { - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (!cd) return false; SignalVector *signalVector = cd->signalVector.loadRelaxed(); @@ -1015,8 +1019,8 @@ void QObjectPrivate::clearBindingStorage() outside the parent. If you still do, the destroyed() signal gives you an opportunity to detect when an object is destroyed. - \warning Deleting a QObject while pending events are waiting to - be delivered can cause a crash. You must not delete the QObject + \warning Deleting a QObject while it is handling an event + delivered to it can cause a crash. You must not delete the QObject directly if it exists in a different thread than the one currently executing. Use deleteLater() instead, which will cause the event loop to delete the object after all pending events have been @@ -1065,7 +1069,7 @@ QObject::~QObject() if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::destroyed) QAbstractDeclarativeData::destroyed(d->declarativeData, this); - QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); + QObjectPrivate::ConnectionData *cd = d->connections.loadAcquire(); if (cd) { if (cd->currentSender) { cd->currentSender->receiverDeleted(); @@ -1429,11 +1433,13 @@ bool QObject::event(QEvent *e) { QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e); - if (!d_func()->connections.loadRelaxed()) { + QObjectPrivate::ConnectionData *connections = d_func()->connections.loadAcquire(); + if (!connections) { QMutexLocker locker(signalSlotLock(this)); d_func()->ensureConnectionData(); + connections = d_func()->connections.loadRelaxed(); } - QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId()); + QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId(), connections); mce->placeMetaCall(this); break; @@ -1766,7 +1772,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (cd) { if (cd->currentSender) { cd->currentSender->receiverDeleted(); @@ -2709,8 +2715,8 @@ int QObject::receivers(const char *signal) const signal_index); } - QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); QMutexLocker locker(signalSlotLock(this)); + QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); if (cd && signal_index < cd->signalVectorCount()) { const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed(); while (c) { @@ -3968,8 +3974,8 @@ void doActivate(QObject *sender, int signal_index, void **argv) bool senderDeleted = false; { - Q_ASSERT(sp->connections.loadAcquire()); - QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed()); + Q_ASSERT(sp->connections.loadRelaxed()); + QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadAcquire()); QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed(); const QObjectPrivate::ConnectionList *list; @@ -4045,7 +4051,9 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (c->isSingleShot && !QObjectPrivate::removeConnection(c)) continue; - QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index); + QObjectPrivate::Sender senderData( + receiverInSameThread ? receiver : nullptr, sender, signal_index, + receiverInSameThread ? QObjectPrivate::get(receiver)->connections.loadAcquire() : nullptr); if (c->isSlotObject) { SlotObjectGuard obj{c->slotObj}; @@ -4094,7 +4102,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) senderDeleted = true; } if (!senderDeleted) { - sp->connections.loadRelaxed()->cleanOrphanedConnections(sender); + sp->connections.loadAcquire()->cleanOrphanedConnections(sender); if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) signal_spy_set->signal_end_callback(sender, signal_index); @@ -5154,9 +5162,9 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) { + if (type & Qt::UniqueConnection && slot) { QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed(); - if (connections->signalVectorCount() > signal_index) { + if (connections && connections->signalVectorCount() > signal_index) { const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed(); while (c2) { @@ -5433,7 +5441,7 @@ inline bool QObjectPrivate::removeConnection(QObjectPrivate::Connection *c) QtPrivate::QPropertyAdaptorSlotObject * QObjectPrivate::getPropertyAdaptorSlotObject(const QMetaProperty &property) { - if (auto conns = connections.loadRelaxed()) { + if (auto conns = connections.loadAcquire()) { Q_Q(QObject); const QMetaObject *metaObject = q->metaObject(); int signal_index = methodIndexToSignalIndex(&metaObject, property.notifySignalIndex()); diff --git a/src/corelib/kernel/qobject_p_p.h b/src/corelib/kernel/qobject_p_p.h index d79ce7e2b93..537ea55f4d7 100644 --- a/src/corelib/kernel/qobject_p_p.h +++ b/src/corelib/kernel/qobject_p_p.h @@ -215,19 +215,18 @@ struct QObjectPrivate::ConnectionData struct QObjectPrivate::Sender { - Sender(QObject *receiver, QObject *sender, int signal) + Sender(QObject *receiver, QObject *sender, int signal, ConnectionData *receiverConnections) : receiver(receiver), sender(sender), signal(signal) { - if (receiver) { - ConnectionData *cd = receiver->d_func()->connections.loadRelaxed(); - previous = cd->currentSender; - cd->currentSender = this; + if (receiverConnections) { + previous = receiverConnections->currentSender; + receiverConnections->currentSender = this; } } ~Sender() { if (receiver) - receiver->d_func()->connections.loadRelaxed()->currentSender = previous; + receiver->d_func()->connections.loadAcquire()->currentSender = previous; } void receiverDeleted() { @@ -237,7 +236,7 @@ struct QObjectPrivate::Sender s = s->previous; } } - Sender *previous; + Sender *previous = nullptr; QObject *receiver; QObject *sender; int signal; diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 5e78489fdae..68f6f424104 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -732,13 +732,6 @@ void QPropertyObserverPointer::setChangeHandler(QPropertyObserver::ChangeHandler ptr->next.setTag(QPropertyObserver::ObserverNotifiesChangeHandler); } -void QPropertyObserverPointer::setBindingToNotify(QPropertyBindingPrivate *binding) -{ - Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder); - ptr->binding = binding; - ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding); -} - /*! \internal The same as as setBindingToNotify, but assumes that the tag is already correct. diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 77a744097eb..d8301e98852 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -134,7 +134,13 @@ struct QPropertyObserverPointer unlink_common(); } - void setBindingToNotify(QPropertyBindingPrivate *binding); + void setBindingToNotify(QPropertyBindingPrivate *binding) + { + Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder); + ptr->binding = binding; + ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding); + } + void setBindingToNotify_unsafe(QPropertyBindingPrivate *binding); void setChangeHandler(QPropertyObserver::ChangeHandler changeHandler); @@ -937,7 +943,15 @@ QBindingObserverPtr::QBindingObserverPtr(QPropertyObserver *observer) noexcept : QPropertyObserverPointer{d}.binding()->addRef(); } -QBindingObserverPtr::~QBindingObserverPtr() { if (d) QPropertyObserverPointer{d}.binding()->deref(); } +QBindingObserverPtr::~QBindingObserverPtr() +{ + if (!d) + return; + + QPropertyBindingPrivate *bindingPrivate = binding(); + if (!bindingPrivate->deref()) + QPropertyBindingPrivate::destroyAndFreeMemory(bindingPrivate); +} QPropertyBindingPrivate *QBindingObserverPtr::binding() const noexcept { return QPropertyObserverPointer{d}.binding(); } diff --git a/src/corelib/mimetypes/mime/hexdump.ps1 b/src/corelib/mimetypes/mime/hexdump.ps1 index 01d386fa821..26fb9dd6e65 100644 --- a/src/corelib/mimetypes/mime/hexdump.ps1 +++ b/src/corelib/mimetypes/mime/hexdump.ps1 @@ -1,5 +1,5 @@ # Copyright (C) 2019 Intel Corporation. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 param([String]$path, [String]$orig) diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index e196b778125..8aea2ff8455 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -12,7 +12,6 @@ #include <private/qfilesystementry_p.h> -#include <QtCore/QMap> #include <QtCore/QFile> #include <QtCore/QFileInfo> #include <QtCore/QStandardPaths> diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 9111f1f0e9d..020e2d5a228 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -8,7 +8,6 @@ #include "qmimetypeparser_p.h" #include <QtCore/QList> -#include <QtCore/QMap> #include <QtCore/QDebug> #include <qendian.h> diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h index 523ef9ea349..e9918a30a56 100644 --- a/src/corelib/serialization/qcbormap.h +++ b/src/corelib/serialization/qcbormap.h @@ -40,6 +40,7 @@ public: constexpr Iterator() = default; constexpr Iterator(const Iterator &) = default; + ~Iterator() = default; Iterator &operator=(const Iterator &other) { // rebind the reference @@ -100,6 +101,7 @@ public: constexpr ConstIterator() = default; constexpr ConstIterator(const ConstIterator &) = default; + ~ConstIterator() = default; ConstIterator &operator=(const ConstIterator &other) { // rebind the reference diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index b364f7f9e2f..cc7a3604cf6 100644 --- a/src/corelib/serialization/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp @@ -1056,13 +1056,15 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l) if (len == 0) return *this; - const quint32 Step = 1024 * 1024; + quint32 step = 1024 * 1024; quint32 allocated = 0; char *prevBuf = nullptr; char *curBuf = nullptr; + constexpr quint32 MaxBlockSize = std::numeric_limits<int>::max(); do { - int blockSize = qMin(Step, len - allocated); + const quint32 sz = qMin(step, len - allocated); + int blockSize = qMin(sz, MaxBlockSize); prevBuf = curBuf; curBuf = new char[allocated + blockSize + 1]; if (prevBuf) { @@ -1074,6 +1076,7 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l) return *this; } allocated += blockSize; + step *= 2; } while (allocated < len); s = curBuf; diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 48839d832e6..21153603525 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -2981,54 +2981,80 @@ void QXmlStreamWriterPrivate::write(QAnyStringView s) void QXmlStreamWriterPrivate::writeEscaped(QAnyStringView s, bool escapeWhitespace) { + struct NextLatin1 { + char32_t operator()(const char *&it, const char *) const + { return uchar(*it++); } + }; + struct NextUtf8 { + char32_t operator()(const char *&it, const char *end) const + { + uchar uc = *it++; + char32_t utf32 = 0; + char32_t *output = &utf32; + qsizetype n = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(uc, output, it, end); + return n < 0 ? 0 : utf32; + } + }; + struct NextUtf16 { + char32_t operator()(const QChar *&it, const QChar *) const + { + return (it++)->unicode(); + } + }; + QString escaped; escaped.reserve(s.size()); s.visit([&] (auto s) { using View = decltype(s); + using Decoder = std::conditional_t<std::is_same_v<View, QLatin1StringView>, NextLatin1, + std::conditional_t<std::is_same_v<View, QUtf8StringView>, NextUtf8, NextUtf16>>; auto it = s.begin(); const auto end = s.end(); + Decoder decoder; while (it != end) { QLatin1StringView replacement; auto mark = it; while (it != end) { - if (*it == u'<') { + auto next_it = it; + char32_t uc = decoder(next_it, end); + if (uc == u'<') { replacement = "<"_L1; break; - } else if (*it == u'>') { + } else if (uc == u'>') { replacement = ">"_L1; break; - } else if (*it == u'&') { + } else if (uc == u'&') { replacement = "&"_L1; break; - } else if (*it == u'\"') { + } else if (uc == u'\"') { replacement = """_L1; break; - } else if (*it == u'\t') { + } else if (uc == u'\t') { if (escapeWhitespace) { replacement = "	"_L1; break; } - } else if (*it == u'\n') { + } else if (uc == u'\n') { if (escapeWhitespace) { replacement = " "_L1; break; } - } else if (*it == u'\v' || *it == u'\f') { + } else if (uc == u'\v' || uc == u'\f') { hasEncodingError = true; break; - } else if (*it == u'\r') { + } else if (uc == u'\r') { if (escapeWhitespace) { replacement = " "_L1; break; } - } else if (*it <= u'\x1F' || *it >= u'\uFFFE') { + } else if (uc <= u'\x1F' || uc == u'\uFFFE' || uc == u'\uFFFF') { hasEncodingError = true; break; } - ++it; + it = next_it; } escaped.append(View{mark, it}); diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 8faa130d38f..e6399baf909 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -1342,6 +1342,9 @@ QByteArray &QByteArray::operator=(const QByteArray & other) noexcept \overload Assigns \a str to this byte array. + + \a str is assumed to point to a null-terminated string, and its length is + determined dynamically. */ QByteArray &QByteArray::operator=(const char *str) diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 4466a460b23..1a2fbee2357 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -109,18 +109,18 @@ QLocale::Language QLocalePrivate::codeToLanguage(QStringView code, auto searchCode = [codeBuf](auto f) { return std::find_if(languageCodeList.begin(), languageCodeList.end(), - [=](const LanguageCodeEntry &i) { return f(i) == codeBuf; }); + [=](LanguageCodeEntry i) { return f(i) == codeBuf; }); }; if (codeTypes.testFlag(QLocale::ISO639Part1) && uc3 == 0) { - auto i = searchCode([](const LanguageCodeEntry &i) { return i.part1; }); + auto i = searchCode([](LanguageCodeEntry i) { return i.part1; }); if (i != languageCodeList.end()) return QLocale::Language(std::distance(languageCodeList.begin(), i)); } if (uc3 != 0) { if (codeTypes.testFlag(QLocale::ISO639Part2B)) { - auto i = searchCode([](const LanguageCodeEntry &i) { return i.part2B; }); + auto i = searchCode([](LanguageCodeEntry i) { return i.part2B; }); if (i != languageCodeList.end()) return QLocale::Language(std::distance(languageCodeList.begin(), i)); } @@ -129,13 +129,13 @@ QLocale::Language QLocalePrivate::codeToLanguage(QStringView code, // This is asserted in iso639_3.LanguageCodeData. if (codeTypes.testFlag(QLocale::ISO639Part2T) && !codeTypes.testFlag(QLocale::ISO639Part3)) { - auto i = searchCode([](const LanguageCodeEntry &i) { return i.part2T; }); + auto i = searchCode([](LanguageCodeEntry i) { return i.part2T; }); if (i != languageCodeList.end()) return QLocale::Language(std::distance(languageCodeList.begin(), i)); } if (codeTypes.testFlag(QLocale::ISO639Part3)) { - auto i = searchCode([](const LanguageCodeEntry &i) { return i.part3; }); + auto i = searchCode([](LanguageCodeEntry i) { return i.part3; }); if (i != languageCodeList.end()) return QLocale::Language(std::distance(languageCodeList.begin(), i)); } @@ -250,7 +250,7 @@ struct LikelyPair QLocaleId value = QLocaleId { 0, 0, 0 }; }; -bool operator<(const LikelyPair &lhs, const LikelyPair &rhs) +bool operator<(LikelyPair lhs, LikelyPair rhs) { // Must match the comparison LocaleDataWriter.likelySubtags() uses when // sorting, see qtbase/util/locale_database.qlocalexml2cpp.py @@ -461,7 +461,7 @@ QByteArray QLocalePrivate::bcp47Name(char separator) const return m_data->id().withLikelySubtagsRemoved().name(separator); } -static qsizetype findLocaleIndexById(const QLocaleId &localeId) +static qsizetype findLocaleIndexById(QLocaleId localeId) { qsizetype idx = locale_index[localeId.language_id]; // If there are no locales for specified language (so we we've got the diff --git a/src/corelib/text/qlocale.qdoc b/src/corelib/text/qlocale.qdoc index fcc4ab4cfb1..f81c10a87fe 100644 --- a/src/corelib/text/qlocale.qdoc +++ b/src/corelib/text/qlocale.qdoc @@ -1153,7 +1153,7 @@ */ /*! - \fn QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const + \fn QVariant QSystemLocale::query(QueryType type, QVariant &&in = QVariant()) const Generic query method for locale data. Provides indirection. Denotes the \a type of the query diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm index ec592616c53..9c3f7a4f31c 100644 --- a/src/corelib/text/qlocale_mac.mm +++ b/src/corelib/text/qlocale_mac.mm @@ -571,7 +571,7 @@ static QLocale::Language codeToLanguage(QStringView s) return QLocalePrivate::codeToLanguage(s); } -QVariant QSystemLocale::query(QueryType type, QVariant in) const +QVariant QSystemLocale::query(QueryType type, QVariant &&in) const { QMacAutoReleasePool pool; diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h index cb1adfbe592..8a61dd77829 100644 --- a/src/corelib/text/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -35,6 +35,7 @@ struct QLocaleData; // Subclassed by Android platform plugin: class Q_CORE_EXPORT QSystemLocale { + Q_DISABLE_COPY_MOVE(QSystemLocale) QSystemLocale *next = nullptr; // Maintains a stack. public: QSystemLocale(); @@ -98,7 +99,7 @@ public: StandaloneDayNameShort, // QString, in: int StandaloneDayNameNarrow // QString, in: int }; - virtual QVariant query(QueryType type, QVariant in = QVariant()) const; + virtual QVariant query(QueryType type, QVariant &&in = QVariant()) const; virtual QLocale fallbackLocale() const; inline qsizetype fallbackLocaleIndex() const; diff --git a/src/corelib/text/qlocale_unix.cpp b/src/corelib/text/qlocale_unix.cpp index 6f6884d3661..a0c9ecc4341 100644 --- a/src/corelib/text/qlocale_unix.cpp +++ b/src/corelib/text/qlocale_unix.cpp @@ -124,7 +124,7 @@ QLocale QSystemLocale::fallbackLocale() const return QLocale(lang); } -QVariant QSystemLocale::query(QueryType type, QVariant in) const +QVariant QSystemLocale::query(QueryType type, QVariant &&in) const { QSystemLocaleData *d = qSystemLocaleData(); @@ -258,9 +258,10 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const return d->uiLanguages.isEmpty() ? QVariant() : QVariant(d->uiLanguages); } case StringToStandardQuotation: - return lc_messages.quoteString(qvariant_cast<QStringView>(in)); + return lc_messages.quoteString(qvariant_cast<QStringView>(std::move(in))); case StringToAlternateQuotation: - return lc_messages.quoteString(qvariant_cast<QStringView>(in), QLocale::AlternateQuotation); + return lc_messages.quoteString(qvariant_cast<QStringView>(std::move(in)), + QLocale::AlternateQuotation); case ListToSeparatedString: return lc_messages.createSeparatedList(in.toStringList()); case LocaleChanged: diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp index 3454e859852..9ce9f9af4b0 100644 --- a/src/corelib/text/qlocale_win.cpp +++ b/src/corelib/text/qlocale_win.cpp @@ -837,7 +837,7 @@ QLocale QSystemLocale::fallbackLocale() const return QLocale(QString::fromLatin1(getWinLocaleName())); } -QVariant QSystemLocale::query(QueryType type, QVariant in) const +QVariant QSystemLocale::query(QueryType type, QVariant &&in) const { QSystemLocalePrivate *d = systemLocalePrivate(); switch(type) { diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp index 8b67cbeabce..a3a0b3c4f8c 100644 --- a/src/corelib/text/qstringconverter.cpp +++ b/src/corelib/text/qstringconverter.cpp @@ -1365,10 +1365,10 @@ QString QLocal8Bit::convertToUnicode_sys(QByteArrayView in, quint32 codePage, // encounter an error int nextIn = qt_saturate<int>(mblen); while (mblen > 0) { - const int nextOut = qt_saturate<int>(outlen); std::tie(out, outlen) = growOut(1); // Need space for at least one character if (!out) return {}; + const int nextOut = qt_saturate<int>(outlen); len = MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, mb, nextIn, out, nextOut); if (len) { mb += nextIn; @@ -1576,9 +1576,11 @@ QByteArray QLocal8Bit::convertFromUnicode_sys(QStringView in, quint32 codePage, // incomplete sequence, probably a Windows bug. We try to avoid that from // happening by reducing the window size in that case. But let's keep this // branch just in case of other bugs. +#ifndef QT_NO_DEBUG r = GetLastError(); fprintf(stderr, "WideCharToMultiByte: Cannot convert multibyte text (error %d)\n", r); +#endif // !QT_NO_DEBUG break; } std::tie(out, outlen) = growOut(neededLength); @@ -1964,7 +1966,7 @@ struct QStringConverterICU : QStringConverter const void *context; ucnv_getToUCallBack(icu_conv, &action, &context); if (context != state) - ucnv_setToUCallBack(icu_conv, action, &state, nullptr, nullptr, &err); + ucnv_setToUCallBack(icu_conv, action, state, nullptr, nullptr, &err); ucnv_toUnicode(icu_conv, &target, targetLimit, &source, sourceLimit, nullptr, flush, &err); // We did reserve enough space: @@ -1997,7 +1999,7 @@ struct QStringConverterICU : QStringConverter const void *context; ucnv_getFromUCallBack(icu_conv, &action, &context); if (context != state) - ucnv_setFromUCallBack(icu_conv, action, &state, nullptr, nullptr, &err); + ucnv_setFromUCallBack(icu_conv, action, state, nullptr, nullptr, &err); ucnv_fromUnicode(icu_conv, &target, targetLimit, &source, sourceLimit, nullptr, flush, &err); // We did reserve enough space: diff --git a/src/corelib/text/qstringconverter_p.h b/src/corelib/text/qstringconverter_p.h index 40f9b62a3ee..da19fa70577 100644 --- a/src/corelib/text/qstringconverter_p.h +++ b/src/corelib/text/qstringconverter_p.h @@ -43,18 +43,27 @@ struct QUtf8BaseTraits static void appendByte(qchar8_t *&ptr, qchar8_t b) { *ptr++ = b; } + static uchar peekByte(const char *ptr, qsizetype n = 0) + { return ptr[n]; } + static uchar peekByte(const uchar *ptr, qsizetype n = 0) { return ptr[n]; } static uchar peekByte(const qchar8_t *ptr, qsizetype n = 0) { return ptr[n]; } + static qptrdiff availableBytes(const char *ptr, const char *end) + { return end - ptr; } + static qptrdiff availableBytes(const uchar *ptr, const uchar *end) { return end - ptr; } static qptrdiff availableBytes(const qchar8_t *ptr, const qchar8_t *end) { return end - ptr; } + static void advanceByte(const char *&ptr, qsizetype n = 1) + { ptr += n; } + static void advanceByte(const uchar *&ptr, qsizetype n = 1) { ptr += n; } diff --git a/src/corelib/text/qstringtokenizer.h b/src/corelib/text/qstringtokenizer.h index 2b679608f91..7a627b45084 100644 --- a/src/corelib/text/qstringtokenizer.h +++ b/src/corelib/text/qstringtokenizer.h @@ -5,6 +5,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qcontainerfwd.h> +#include <iterator> QT_BEGIN_NAMESPACE diff --git a/src/corelib/text/qt_attribution.json b/src/corelib/text/qt_attribution.json index 0084ccc18d9..3ae1bd2925a 100644 --- a/src/corelib/text/qt_attribution.json +++ b/src/corelib/text/qt_attribution.json @@ -35,8 +35,8 @@ available.", "Homepage": "https://cldr.unicode.org/", "Version": "v44.1", - "License": "Unicode License V3", - "LicenseId": "UNICODE-3.0", + "License": "Unicode License v3", + "LicenseId": "Unicode-3.0", "Copyright": "Copyright (C) 2004-2023 Unicode, Inc." } ] diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h index 7e682e69b68..86b8cbd3484 100644 --- a/src/corelib/thread/qfutureinterface.h +++ b/src/corelib/thread/qfutureinterface.h @@ -452,7 +452,7 @@ template <> class QFutureInterface<void> : public QFutureInterfaceBase { public: - explicit QFutureInterface<void>(State initialState = NoState) + explicit QFutureInterface(State initialState = NoState) : QFutureInterfaceBase(initialState) { } diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp index f1ea6128ae3..276291a4719 100644 --- a/src/corelib/time/qtimezoneprivate_tz.cpp +++ b/src/corelib/time/qtimezoneprivate_tz.cpp @@ -578,7 +578,12 @@ PosixZone PosixZone::parse(const char *&pos, const char *end) return {std::move(name), offset}; } -static auto validatePosixRule(const QByteArray &posixRule) +/* Parse and check a POSIX rule. + + By default a simple zone abbreviation with no offset information is accepted. + Set \a requireOffset to \c true to require that there be offset data present. +*/ +static auto validatePosixRule(const QByteArray &posixRule, bool requireOffset = false) { // Format is described here: // http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html @@ -590,15 +595,19 @@ static auto validatePosixRule(const QByteArray &posixRule) return fail; const char *begin = zoneinfo.begin(); - - // Updates begin to point after the name and offset it parses: - if (PosixZone::parse(begin, zoneinfo.end()).name.isEmpty()) - return fail; + { + // Updates begin to point after the name and offset it parses: + const auto posix = PosixZone::parse(begin, zoneinfo.end()); + if (posix.name.isEmpty()) + return fail; + if (requireOffset && !posix.hasValidOffset()) + return fail; + } if (good.hasDst) { if (begin >= zoneinfo.end()) return fail; - // Expect a second name and offset after the first: + // Expect a second name (and optional offset) after the first: if (PosixZone::parse(begin, zoneinfo.end()).name.isEmpty()) return fail; } @@ -772,7 +781,7 @@ public: QTzTimeZoneCacheEntry fetchEntry(const QByteArray &ianaId); private: - QTzTimeZoneCacheEntry findEntry(const QByteArray &ianaId); + static QTzTimeZoneCacheEntry findEntry(const QByteArray &ianaId); QCache<QByteArray, QTzTimeZoneCacheEntry> m_cache; QMutex m_mutex; }; @@ -977,6 +986,8 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::fetchEntry(const QByteArray &ianaId) // Create a named time zone QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId) { + if (!isTimeZoneIdAvailable(ianaId)) // Avoid pointlessly creating cache entries + return; static QTzTimeZoneCache tzCache; auto entry = tzCache.fetchEntry(ianaId); if (entry.m_tranTimes.isEmpty() && entry.m_posixRule.isEmpty()) @@ -1239,7 +1250,11 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const { - return tzZones->contains(ianaId); + // Allow a POSIX rule as long as it has offset data. (This needs to reject a + // plain abbreviation, without offset, since claiming to support such zones + // would prevent the custom QTimeZone constructor from accepting such a + // name, as it doesn't want a custom zone to over-ride a "real" one.) + return tzZones->contains(ianaId) || validatePosixRule(ianaId, true).isValid; } QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h index d380421170c..7efea45acd2 100644 --- a/src/corelib/tools/qcontainertools_impl.h +++ b/src/corelib/tools/qcontainertools_impl.h @@ -265,7 +265,11 @@ using IfAssociativeIteratorHasKeyAndValue = template <typename Iterator> using IfAssociativeIteratorHasFirstAndSecond = - std::enable_if_t<qxp::is_detected_v<FirstAndSecondTest, Iterator>, bool>; + std::enable_if_t< + std::conjunction_v< + std::negation<qxp::is_detected<KeyAndValueTest, Iterator>>, + qxp::is_detected<FirstAndSecondTest, Iterator> + >, bool>; template <typename T, typename U> using IfIsNotSame = @@ -323,8 +327,7 @@ template <typename Container, typename T> auto sequential_erase_with_copy(Container &c, const T &t) { using CopyProxy = std::conditional_t<std::is_copy_constructible_v<T>, T, const T &>; - const T &tCopy = CopyProxy(t); - return sequential_erase(c, tCopy); + return sequential_erase(c, CopyProxy(t)); } template <typename Container, typename T> diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index d61b90503a4..8ed4110bae7 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -109,8 +109,7 @@ public: public: using difference_type = qsizetype; using value_type = T; - // libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346 -#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) +#ifdef QT_COMPILER_HAS_LWG3346 using iterator_concept = std::contiguous_iterator_tag; using element_type = value_type; #endif @@ -180,8 +179,7 @@ public: public: using difference_type = qsizetype; using value_type = T; - // libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346 -#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) +#ifdef QT_COMPILER_HAS_LWG3346 using iterator_concept = std::contiguous_iterator_tag; using element_type = const value_type; #endif diff --git a/src/corelib/tools/quniquehandle_p.h b/src/corelib/tools/quniquehandle_p.h index e31699a1229..7af1536c2ed 100644 --- a/src/corelib/tools/quniquehandle_p.h +++ b/src/corelib/tools/quniquehandle_p.h @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QUNIQUEHANDLE_P_H #define QUNIQUEHANDLE_P_H |