From 7c87ffff9aa62883bf61efe1bf27704d479eace5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 29 May 2018 16:36:53 +0200 Subject: qmake: skip empty parts when splitting strings in some more places ... and make it explicit where we can't do that for semantical or backwards compat reasons. most urgently, this fixes an assertion failure when $QMAKEFEATURES contains empty paths (e.g., due to a trailing semicolon). notable observation: QByteArray::split() has no argument for the split behavior (it always keeps empty parts). Task-number: QTBUG-47325 Change-Id: I72d4b2e154a2ed1802cfa98fb4a5211a68e43231 Reviewed-by: Joerg Bornemann --- qmake/library/qmakebuiltins.cpp | 9 ++++++--- qmake/library/qmakeevaluator.cpp | 5 +++-- qmake/library/qmakeglobals.cpp | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index c1d446263e..02ad3220d3 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -738,7 +738,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep; const auto vars = values(map(args.at(0))); for (const ProString &var : vars) { - const auto splits = var.toQStringRef().split(sep); + // FIXME: this is inconsistent with the "there are no empty strings" dogma. + const auto splits = var.toQStringRef().split(sep, QString::KeepEmptyParts); for (const auto &splt : splits) ret << ProString(splt).setSource(var); } @@ -1445,7 +1446,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } if (args.count() == 1) return returnBool(isActiveConfig(args.at(0).toQStringRef())); - const auto mutuals = args.at(1).toQStringRef().split(QLatin1Char('|')); + const auto mutuals = args.at(1).toQStringRef().split(QLatin1Char('|'), + QString::SkipEmptyParts); const ProStringList &configs = values(statics.strCONFIG); for (int i = configs.size() - 1; i >= 0; i--) { @@ -1477,7 +1479,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnTrue; } } else { - const auto mutuals = args.at(2).toQStringRef().split(QLatin1Char('|')); + const auto mutuals = args.at(2).toQStringRef().split(QLatin1Char('|'), + QString::SkipEmptyParts); for (int i = l.size() - 1; i >= 0; i--) { const ProString val = l[i]; for (int mut = 0; mut < mutuals.count(); mut++) { diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 7112b57c11..6b23412327 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -297,6 +297,7 @@ ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, int sourc case '\'': if (!quote) quote = unicode; + // FIXME: this is inconsistent with the "there are no empty strings" dogma. hadWord = true; break; case ' ': @@ -879,7 +880,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable( return ReturnTrue; } QChar sep = val.at(1); - auto func = val.split(sep); + auto func = val.split(sep, QString::KeepEmptyParts); if (func.count() < 3 || func.count() > 4) { evalError(fL1S("The s/// function expects 3 or 4 arguments.")); return ReturnTrue; @@ -1018,7 +1019,7 @@ static ProString msvcArchitecture(const QString &vcInstallDir, const QString &pa QString vcBinDir = vcInstallDir; if (vcBinDir.endsWith(QLatin1Char('\\'))) vcBinDir.chop(1); - const auto dirs = pathVar.split(QLatin1Char(';')); + const auto dirs = pathVar.split(QLatin1Char(';'), QString::SkipEmptyParts); for (const QString &dir : dirs) { if (!dir.startsWith(vcBinDir, Qt::CaseInsensitive)) continue; diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index 452b44c045..daf4707779 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -261,7 +261,7 @@ QStringList QMakeGlobals::splitPathList(const QString &val) const QStringList ret; if (!val.isEmpty()) { QString cwd(QDir::currentPath()); - const QStringList vals = val.split(dirlist_sep); + const QStringList vals = val.split(dirlist_sep, QString::SkipEmptyParts); ret.reserve(vals.length()); for (const QString &it : vals) ret << IoUtils::resolvePath(cwd, it); -- cgit v1.2.3