diff --git a/dist/changes-4.15.2.md b/dist/changes-4.15.2.md new file mode 100644 index 00000000000..cf053f0046a --- /dev/null +++ b/dist/changes-4.15.2.md @@ -0,0 +1,55 @@ +Qt Creator 4.15.2 +================= + +Qt Creator version 4.15.2 contains bug fixes. + +The most important changes are listed in this document. For a complete +list of changes, see the Git log for the Qt Creator sources that +you can check out from the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/v4.15.1..v4.15.2 + +Projects +-------- + +### CMake + +* Improved performance after project load and reparse +* Fixed crash on session switch (QTCREATORBUG-25837) + +### qmake + +* Fixed issues with executing system calls (QTCREATORBUG-25970) + +Test Integration +---------------- + +### CTest + +* Fixed test detection if `ctest` takes long to run (QTCREATORBUG-25851) + +Platforms +--------- + +### WASM + +* Fixed Python version that is on Windows (QTCREATORBUG-25897) + +Credits for these changes go to: +-------------------------------- +Ahmad Samir +Alessandro Portale +Christian Stenger +Cristian Adam +Eike Ziller +Ivan Komissarov +Kai Köhne +Knud Dollereder +Michael Winkelmann +Mitch Curtis +Robert Löhning +Thomas Hartmann +Tim Blechmann +Tim Jenssen +Tuomo Pelkonen diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index acb1c14e1f4..83377bc987e 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -284,8 +284,11 @@ QmakeBuildSystem::~QmakeBuildSystem() delete m_qmakeVfs; m_qmakeVfs = nullptr; - m_asyncUpdateFutureInterface.reportCanceled(); - m_asyncUpdateFutureInterface.reportFinished(); + if (m_asyncUpdateFutureInterface) { + m_asyncUpdateFutureInterface->reportCanceled(); + m_asyncUpdateFutureInterface->reportFinished(); + m_asyncUpdateFutureInterface.reset(); + } } void QmakeBuildSystem::updateCodeModels() @@ -591,8 +594,9 @@ void QmakeBuildSystem::incrementPendingEvaluateFutures() } ++m_pendingEvaluateFuturesCount; TRACE("pending inc to: " << m_pendingEvaluateFuturesCount); - m_asyncUpdateFutureInterface.setProgressRange(m_asyncUpdateFutureInterface.progressMinimum(), - m_asyncUpdateFutureInterface.progressMaximum() + 1); + m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(), + m_asyncUpdateFutureInterface->progressMaximum() + + 1); } void QmakeBuildSystem::decrementPendingEvaluateFutures() @@ -605,15 +609,17 @@ void QmakeBuildSystem::decrementPendingEvaluateFutures() return; // We are closing the project! } - m_asyncUpdateFutureInterface.setProgressValue(m_asyncUpdateFutureInterface.progressValue() + 1); + m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + + 1); if (m_pendingEvaluateFuturesCount == 0) { // We are done! setRootProjectNode(QmakeNodeTreeBuilder::buildTree(this)); if (!m_rootProFile->validParse()) - m_asyncUpdateFutureInterface.reportCanceled(); + m_asyncUpdateFutureInterface->reportCanceled(); - m_asyncUpdateFutureInterface.reportFinished(); + m_asyncUpdateFutureInterface->reportFinished(); + m_asyncUpdateFutureInterface.reset(); m_cancelEvaluate = false; // TODO clear the profile cache ? @@ -659,12 +665,13 @@ void QmakeBuildSystem::asyncUpdate() m_qmakeVfs->invalidateCache(); } - m_asyncUpdateFutureInterface.setProgressRange(0, 0); - Core::ProgressManager::addTask(m_asyncUpdateFutureInterface.future(), + m_asyncUpdateFutureInterface.reset(new QFutureInterface); + m_asyncUpdateFutureInterface->setProgressRange(0, 0); + Core::ProgressManager::addTask(m_asyncUpdateFutureInterface->future(), tr("Reading Project \"%1\"").arg(project()->displayName()), Constants::PROFILE_EVALUATE); - m_asyncUpdateFutureInterface.reportStarted(); + m_asyncUpdateFutureInterface->reportStarted(); const auto watcher = new QFutureWatcher(this); connect(watcher, &QFutureWatcher::canceled, this, [this, watcher] { if (!m_qmakeGlobals) @@ -676,7 +683,7 @@ void QmakeBuildSystem::asyncUpdate() watcher->disconnect(); watcher->deleteLater(); }); - watcher->setFuture(m_asyncUpdateFutureInterface.future()); + watcher->setFuture(m_asyncUpdateFutureInterface->future()); const Kit *const k = kit(); QtSupport::BaseQtVersion *const qtVersion = QtSupport::QtKitAspect::qtVersion(k); @@ -687,8 +694,9 @@ void QmakeBuildSystem::asyncUpdate() .arg(project()->displayName(), k->displayName()) : tr("Cannot parse project \"%1\": No kit selected.").arg(project()->displayName()); proFileParseError(errorMessage, project()->projectFilePath()); - m_asyncUpdateFutureInterface.reportCanceled(); - m_asyncUpdateFutureInterface.reportFinished(); + m_asyncUpdateFutureInterface->reportCanceled(); + m_asyncUpdateFutureInterface->reportFinished(); + m_asyncUpdateFutureInterface.reset(); return; } diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h index 6f281b6e710..369b8c03415 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.h +++ b/src/plugins/qmakeprojectmanager/qmakeproject.h @@ -200,7 +200,7 @@ private: QString m_qmakeSysroot; - QFutureInterface m_asyncUpdateFutureInterface; + std::unique_ptr> m_asyncUpdateFutureInterface; int m_pendingEvaluateFuturesCount = 0; AsyncUpdateState m_asyncUpdateState = Base; bool m_cancelEvaluate = false; diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp index f689c419237..1f4a436115e 100644 --- a/src/shared/proparser/proitems.cpp +++ b/src/shared/proparser/proitems.cpp @@ -25,6 +25,7 @@ #include "proitems.h" +#include #include #include #include @@ -50,6 +51,11 @@ ProString::ProString() : { } +ProString::ProString(const ProString &other) : + m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(other.m_hash) +{ +} + ProString::ProString(const ProString &other, OmitPreHashing) : m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(0x80000000) { @@ -72,13 +78,13 @@ ProString::ProString(Utils::StringView str) : } ProString::ProString(const char *str, DoPreHashing) : - m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0) + m_string(QString::fromLatin1(str)), m_offset(0), m_length(int(qstrlen(str))), m_file(0) { updatedHash(); } ProString::ProString(const char *str) : - m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0), m_hash(0x80000000) + m_string(QString::fromLatin1(str)), m_offset(0), m_length(int(qstrlen(str))), m_file(0), m_hash(0x80000000) { } @@ -148,7 +154,8 @@ QString ProString::toQString() const QString &ProString::toQString(QString &tmp) const { - return tmp.setRawData(m_string.constData() + m_offset, m_length); + tmp = m_string.mid(m_offset, m_length); + return tmp; } ProString &ProString::prepend(const ProString &other) @@ -493,4 +500,9 @@ ProKey ProFile::getHashStr(const ushort *&tPtr) return ret; } +QDebug operator<<(QDebug debug, const ProString &str) +{ + return debug << str.toQString(); +} + QT_END_NAMESPACE diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index 3e0686fe136..9d851a9d578 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -64,6 +64,8 @@ class ProFile; class ProString { public: ProString(); + ProString(const ProString &other); + ProString &operator=(const ProString &) = default; template ProString &operator=(const QStringBuilder &str) { return *this = QString(str); } @@ -74,7 +76,6 @@ public: ProString(const QStringBuilder &str) : ProString(QString(str)) {} - ProString(const QString &str, int offset, int length); void setValue(const QString &str); void clear() { m_string.clear(); m_length = 0; } @@ -83,14 +84,14 @@ public: int sourceFile() const { return m_file; } ProString &prepend(const ProString &other); - ProString &append(const ProString &other, bool *pending = 0); + ProString &append(const ProString &other, bool *pending = nullptr); ProString &append(const QString &other) { return append(ProString(other)); } template ProString &append(const QStringBuilder &other) { return append(QString(other)); } ProString &append(const QLatin1String other); ProString &append(const char *other) { return append(QLatin1String(other)); } ProString &append(QChar other); - ProString &append(const ProStringList &other, bool *pending = 0, bool skipEmpty1st = false); + ProString &append(const ProStringList &other, bool *pending = nullptr, bool skipEmpty1st = false); ProString &operator+=(const ProString &other) { return append(other); } ProString &operator+=(const QString &other) { return append(other); } template @@ -146,9 +147,9 @@ public: bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, 0, cs) >= 0; } bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(QLatin1String(s), 0, cs) >= 0; } bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, 0, cs) >= 0; } - int toLongLong(bool *ok = 0, int base = 10) const { return toStringView().toLongLong(ok, base); } - int toInt(bool *ok = 0, int base = 10) const { return toStringView().toInt(ok, base); } - short toShort(bool *ok = 0, int base = 10) const { return toStringView().toShort(ok, base); } + qlonglong toLongLong(bool *ok = nullptr, int base = 10) const { return toStringView().toLongLong(ok, base); } + int toInt(bool *ok = nullptr, int base = 10) const { return toStringView().toInt(ok, base); } + short toShort(bool *ok = nullptr, int base = 10) const { return toStringView().toShort(ok, base); } uint hash() const { return m_hash; } static uint hash(const QChar *p, int n); @@ -185,7 +186,8 @@ private: friend QString operator+(const ProString &one, const ProString &two); friend class ProKey; }; -Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(ProString, Q_RELOCATABLE_TYPE); + class ProKey : public ProString { public: @@ -195,7 +197,6 @@ public: ProKey(const QStringBuilder &str) : ProString(str) {} - PROITEM_EXPLICIT ProKey(const char *str); ProKey(const QString &str, int off, int len); ProKey(const QString &str, int off, int len, uint hash); @@ -217,7 +218,7 @@ public: private: ProKey(const ProString &other); }; -Q_DECLARE_TYPEINFO(ProKey, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(ProKey, Q_RELOCATABLE_TYPE); template <> struct QConcatenable : private QAbstractConcatenable { @@ -228,6 +229,8 @@ template <> struct QConcatenable : private QAbstractConcatenable static inline void appendTo(const ProString &a, QChar *&out) { const auto n = a.size(); + if (!n) + return; memcpy(out, a.toStringView().data(), sizeof(QChar) * n); out += n; } @@ -242,6 +245,8 @@ template <> struct QConcatenable : private QAbstractConcatenable static inline void appendTo(const ProKey &a, QChar *&out) { const auto n = a.size(); + if (!n) + return; memcpy(out, a.toStringView().data(), sizeof(QChar) * n); out += n; } @@ -257,6 +262,54 @@ QTextStream &operator<<(QTextStream &t, const ProString &str); template QTextStream &operator<<(QTextStream &t, const QStringBuilder &str) { return t << QString(str); } +// This class manages read-only access to a ProString via a raw data QString +// temporary, ensuring that the latter is accessed exclusively. +class ProStringRoUser +{ +public: + ProStringRoUser(QString &rs) + { + m_rs = &rs; + } + ProStringRoUser(const ProString &ps, QString &rs) + : ProStringRoUser(rs) + { + ps.toQString(rs); + } + // No destructor, as a RAII pattern cannot be used: references to the + // temporary string can legitimately outlive instances of this class + // (if they are held by Qt, e.g. in QRegExp). + QString &set(const ProString &ps) { return ps.toQString(*m_rs); } + QString &str() { return *m_rs; } + +protected: + QString *m_rs; +}; + +// This class manages read-write access to a ProString via a raw data QString +// temporary, ensuring that the latter is accessed exclusively, and that raw +// data does not leak outside its source's refcounting. +class ProStringRwUser : public ProStringRoUser +{ +public: + ProStringRwUser(QString &rs) + : ProStringRoUser(rs), m_ps(nullptr) {} + ProStringRwUser(const ProString &ps, QString &rs) + : ProStringRoUser(ps, rs), m_ps(&ps) {} + QString &set(const ProString &ps) { m_ps = &ps; return ProStringRoUser::set(ps); } + ProString extract(const QString &s) const + { return s.isSharedWith(*m_rs) ? *m_ps : ProString(s).setSource(*m_ps); } + ProString extract(const QString &s, const ProStringRwUser &other) const + { + if (other.m_ps && s.isSharedWith(*other.m_rs)) + return *other.m_ps; + return extract(s); + } + +private: + const ProString *m_ps; +}; + class ProStringList : public QVector { public: ProStringList() {} @@ -290,21 +343,12 @@ public: { return contains(ProString(str), cs); } bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; }; -Q_DECLARE_TYPEINFO(ProStringList, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(ProStringList, Q_RELOCATABLE_TYPE); inline ProStringList operator+(const ProStringList &one, const ProStringList &two) { ProStringList ret = one; ret += two; return ret; } -typedef QHash ProValueMap; - -// For std::list (sic!) -#ifdef Q_CC_MSVC -inline bool operator<(const ProValueMap &, const ProValueMap &) -{ - Q_ASSERT(false); - return false; -} -#endif +typedef QMap ProValueMap; // These token definitions affect both ProFileEvaluator and ProWriter enum ProToken { @@ -419,7 +463,7 @@ class ProFunctionDef { public: ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); } ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); } - ProFunctionDef(ProFunctionDef &&other) Q_DECL_NOTHROW + ProFunctionDef(ProFunctionDef &&other) noexcept : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; } ~ProFunctionDef() { if (m_pro) m_pro->deref(); } ProFunctionDef &operator=(const ProFunctionDef &o) @@ -433,13 +477,13 @@ public: } return *this; } - ProFunctionDef &operator=(ProFunctionDef &&other) Q_DECL_NOTHROW + ProFunctionDef &operator=(ProFunctionDef &&other) noexcept { ProFunctionDef moved(std::move(other)); swap(moved); return *this; } - void swap(ProFunctionDef &other) Q_DECL_NOTHROW + void swap(ProFunctionDef &other) noexcept { qSwap(m_pro, other.m_pro); qSwap(m_offset, other.m_offset); @@ -452,11 +496,13 @@ private: int m_offset; }; -Q_DECLARE_TYPEINFO(ProFunctionDef, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(ProFunctionDef, Q_RELOCATABLE_TYPE); struct ProFunctionDefs { QHash testFunctions; QHash replaceFunctions; }; +QDebug operator<<(QDebug debug, const ProString &str); + QT_END_NAMESPACE