forked from qt-creator/qt-creator
C++: Fix preprocessor blocked macro bug.
By lexing the first token after a macro call (meaning: the token after the closing parenthesis (which was passed to handleFunctionLikeMacro which in turn pushed it back into the token buffer)), a token buffer might be popped, which unblocks the macro that generated the actual param pack. The effect was that if this happens in the expansion of a recursive macro (with parameters!), the preprocessor ended up in an infinite loop. Task-number: QTCREATORBUG-9015 Task-number: QTCREATORBUG-9447 Change-Id: I0d83c59188ec15c4a948970e9fa944a17d765475 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
d0afdfcc2b
commit
271c3f45a4
@@ -1048,7 +1048,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
|
||||
argRefs);
|
||||
}
|
||||
|
||||
if (!handleFunctionLikeMacro(tk, macro, body, allArgTks, baseLine)) {
|
||||
if (!handleFunctionLikeMacro(macro, body, allArgTks, baseLine)) {
|
||||
if (m_client && !idTk.expanded())
|
||||
m_client->stopExpandingMacro(idTk.offset, *macro);
|
||||
return false;
|
||||
@@ -1119,8 +1119,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Preprocessor::handleFunctionLikeMacro(PPToken *tk,
|
||||
const Macro *macro,
|
||||
bool Preprocessor::handleFunctionLikeMacro(const Macro *macro,
|
||||
QVector<PPToken> &body,
|
||||
const QVector<QVector<PPToken> > &actuals,
|
||||
unsigned baseLine)
|
||||
@@ -1220,9 +1219,6 @@ bool Preprocessor::handleFunctionLikeMacro(PPToken *tk,
|
||||
body = expanded;
|
||||
body.squeeze();
|
||||
|
||||
// Next token to be lexed after the expansion.
|
||||
pushToken(tk);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1479,9 +1475,9 @@ bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken>
|
||||
actuals->append(tokens);
|
||||
}
|
||||
|
||||
if (tk->is(T_RPAREN))
|
||||
lex(tk);
|
||||
//###TODO: else error message
|
||||
if (!tk->is(T_RPAREN)) {
|
||||
//###TODO: else error message
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,8 +205,7 @@ private:
|
||||
void lex(PPToken *tk);
|
||||
void skipPreprocesorDirective(PPToken *tk);
|
||||
bool handleIdentifier(PPToken *tk);
|
||||
bool handleFunctionLikeMacro(PPToken *tk,
|
||||
const Macro *macro,
|
||||
bool handleFunctionLikeMacro(const Macro *macro,
|
||||
QVector<PPToken> &body,
|
||||
const QVector<QVector<PPToken> > &actuals,
|
||||
unsigned lineRef);
|
||||
|
||||
6
tests/auto/cplusplus/preprocessor/data/recursive.2.cpp
Normal file
6
tests/auto/cplusplus/preprocessor/data/recursive.2.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#define a(x) b(x) c(x)
|
||||
#define b(x) c(x) a(x)
|
||||
#define c(x) a(x) b(x)
|
||||
|
||||
b(1)
|
||||
a(1)
|
||||
12
tests/auto/cplusplus/preprocessor/data/recursive.2.out.cpp
Normal file
12
tests/auto/cplusplus/preprocessor/data/recursive.2.out.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
# 1 "data/recursive.2.cpp"
|
||||
|
||||
|
||||
|
||||
|
||||
# expansion begin 70,1 ~2 5:2 ~3 5:2 ~3 5:2 ~3 5:2 ~3 5:2 ~3 5:2 ~1
|
||||
b(1) c(1) b(1) b(1) a(1) b(1)
|
||||
# expansion end
|
||||
# expansion begin 75,1 ~2 6:2 ~3 6:2 ~3 6:2 ~3 6:2 ~3 6:2 ~3 6:2 ~1
|
||||
a(1) b(1) a(1) a(1) c(1) a(1)
|
||||
# expansion end
|
||||
# 7 "data/recursive.2.cpp"
|
||||
@@ -822,6 +822,8 @@ void tst_Preprocessor::comparisons_data()
|
||||
<< "reserved.1.cpp" << "reserved.1.out.cpp" << "";
|
||||
QTest::newRow("recursive 1")
|
||||
<< "recursive.1.cpp" << "recursive.1.out.cpp" << "";
|
||||
QTest::newRow("recursive 2")
|
||||
<< "recursive.2.cpp" << "recursive.2.out.cpp" << "";
|
||||
QTest::newRow("macro_pounder_fn")
|
||||
<< "macro_pounder_fn.c" << "" << "";
|
||||
QTest::newRow("macro_expand")
|
||||
|
||||
Reference in New Issue
Block a user