aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2016-11-11 11:40:24 +0100
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2018-03-14 15:31:26 +0000
commit94957d6f4e6e244897a1ea968a3e3d08606dc8e1 (patch)
treefc3429385ef17522e07f2870e7531f47277bbfe0 /src
parent5e2b4c37f9566c0d17d482f6a65bf0ea10080c3e (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.h3
-rw-r--r--src/shared/proparser/qmakeevaluator.cpp18
-rw-r--r--src/shared/proparser/qmakeparser.cpp26
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");
}