diff options
author | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2016-11-11 11:40:24 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2018-03-14 15:31:26 +0000 |
commit | 94957d6f4e6e244897a1ea968a3e3d08606dc8e1 (patch) | |
tree | fc3429385ef17522e07f2870e7531f47277bbfe0 /src | |
parent | 5e2b4c37f9566c0d17d482f6a65bf0ea10080c3e (diff) |
qmake: introduce magic bypassNesting() scope
Task-number: QTCREATORBUG-18220
Change-Id: If14e6944fe84767bd67604ecde98076f873749ef
(cherry picked from qtbase/b6b44b368c6fc2df168195eaee57a2f925a29646)
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/shared/proparser/proitems.h | 3 | ||||
-rw-r--r-- | src/shared/proparser/qmakeevaluator.cpp | 18 | ||||
-rw-r--r-- | src/shared/proparser/qmakeparser.cpp | 26 |
3 files changed, 46 insertions, 1 deletions
diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index 31e662bcf0..d98d0d9f97 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -320,6 +320,9 @@ enum ProToken { // - function name: hash (2), length (1), chars (length) // - body length (2) // - body + TokTerminator (body length) + TokBypassNesting, // escape from function local variable scopes: + // - block length (2) + // - block + TokTerminator (block length) TokMask = 0xff, TokQuoted = 0x100, // The expression is quoted => join expanded stringlist TokNewStr = 0x200 // Next stringlist element diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index bec43b1d4e..7fa0c3e5d7 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -591,6 +591,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock( tokPtr += blockLen; okey = true, or_op = false; // force next evaluation break; + case TokBypassNesting: + blockLen = getBlockLen(tokPtr); + if ((m_cumulative || okey != or_op) && blockLen) { + ProValueMapStack savedValuemapStack = m_valuemapStack; + m_valuemapStack.clear(); + m_valuemapStack.append(savedValuemapStack.takeFirst()); + traceMsg("visiting nesting-bypassing block"); + ret = visitProBlock(tokPtr); + traceMsg("visited nesting-bypassing block"); + savedValuemapStack.prepend(m_valuemapStack.first()); + m_valuemapStack = savedValuemapStack; + } else { + traceMsg("skipped nesting-bypassing block"); + ret = ReturnTrue; + } + tokPtr += blockLen; + okey = true, or_op = false; // force next evaluation + break; case TokTestDef: case TokReplaceDef: if (m_cumulative || okey != or_op) { diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index 5d1bd71043..a9a1b6d9a7 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -115,6 +115,7 @@ static struct { QString strfor; QString strdefineTest; QString strdefineReplace; + QString strbypassNesting; QString stroption; QString strreturn; QString strnext; @@ -138,6 +139,7 @@ void QMakeParser::initialize() statics.strfor = QLatin1String("for"); statics.strdefineTest = QLatin1String("defineTest"); statics.strdefineReplace = QLatin1String("defineReplace"); + statics.strbypassNesting = QLatin1String("bypassNesting"); statics.stroption = QLatin1String("option"); statics.strreturn = QLatin1String("return"); statics.strnext = QLatin1String("next"); @@ -1171,6 +1173,25 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg } parseError(fL1S("%1(function) requires one literal argument.").arg(*defName)); return; + } else if (m_tmp == statics.strbypassNesting) { + if (*uce != TokFuncTerminator) { + bogusTest(tokPtr, fL1S("%1() requires zero arguments.").arg(m_tmp)); + return; + } + if (!(m_blockstack.top().nest & NestFunction)) { + bogusTest(tokPtr, fL1S("Unexpected %1().").arg(m_tmp)); + return; + } + if (m_invert) { + bogusTest(tokPtr, fL1S("Unexpected NOT operator in front of %1().").arg(m_tmp)); + return; + } + flushScopes(tokPtr); + putLineMarker(tokPtr); + putOperator(tokPtr); + putTok(tokPtr, TokBypassNesting); + enterScope(tokPtr, true, StCtrl); + return; } else if (m_tmp == statics.strreturn) { if (m_blockstack.top().nest & NestFunction) { if (argc > 1) { @@ -1439,7 +1460,7 @@ static bool getBlock(const ushort *tokens, int limit, int &offset, QString *outS "TokReturn", "TokBreak", "TokNext", "TokNot", "TokAnd", "TokOr", "TokBranch", "TokForLoop", - "TokTestDef", "TokReplaceDef" + "TokTestDef", "TokReplaceDef", "TokBypassNesting" }; while (offset != limit) { @@ -1523,6 +1544,9 @@ static bool getBlock(const ushort *tokens, int limit, int &offset, QString *outS if (ok) ok = getSubBlock(tokens, limit, offset, outStr, indent, "body"); break; + case TokBypassNesting: + ok = getSubBlock(tokens, limit, offset, outStr, indent, "block"); + break; default: Q_ASSERT(!"unhandled token"); } |