diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2013-02-19 16:56:30 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-02-21 16:55:41 +0100 |
commit | b05f19f23217ebf982f021c71a04b1df73827c35 (patch) | |
tree | a4a4bb23e037ef98d5bc0b1bd1b2beec292d618d | |
parent | ec166aaa70d5451d84caf0a1ae984cacecd88d5b (diff) |
moc: Fix infinite recursion in macro substitution
When performing macro argument substitution, one should keep the set of
macro to exclude, else we can enter an infinite recursion.
Testcase:
#define M1(A) A
#define M2 M1(M2)
Task-number: QTBUG-29759
Change-Id: I564bbfed65e1c8599592eaf12c6d67285d2fd9ce
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
-rw-r--r-- | src/tools/moc/preprocessor.cpp | 7 | ||||
-rw-r--r-- | src/tools/moc/preprocessor.h | 3 | ||||
-rw-r--r-- | src/tools/moc/symbols.h | 15 | ||||
-rw-r--r-- | tests/auto/tools/moc/parse-defines.h | 5 | ||||
-rw-r--r-- | tests/auto/tools/moc/tst_moc.cpp | 4 |
5 files changed, 29 insertions, 5 deletions
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 96b920b7cd..8f4b84a9c8 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.org> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the tools applications of the Qt Toolkit. @@ -536,12 +537,14 @@ static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode m return symbols; } -Symbols Preprocessor::macroExpand(Preprocessor *that, Symbols &toExpand, int &index, int lineNum, bool one) +Symbols Preprocessor::macroExpand(Preprocessor *that, Symbols &toExpand, int &index, + int lineNum, bool one, const QSet<QByteArray> &excludeSymbols) { SymbolStack symbols; SafeSymbols sf; sf.symbols = toExpand; sf.index = index; + sf.excludedSymbols = excludeSymbols; symbols.push(sf); Symbols result; @@ -664,7 +667,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym if (i == macro.symbols.size() - 1 || macro.symbols.at(i + 1).token != PP_HASHHASH) { Symbols arg = arguments.at(index); int idx = 1; - expansion += macroExpand(that, arg, idx, lineNum, false); + expansion += macroExpand(that, arg, idx, lineNum, false, symbols.excludeSymbols()); } else { expansion += arguments.at(index); } diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h index 55e452a2bd..72d02a3292 100644 --- a/src/tools/moc/preprocessor.h +++ b/src/tools/moc/preprocessor.h @@ -85,7 +85,8 @@ public: void substituteUntilNewline(Symbols &substituted); static Symbols macroExpandIdentifier(Preprocessor *that, SymbolStack &symbols, int lineNum, QByteArray *macroName); - static Symbols macroExpand(Preprocessor *that, Symbols &toExpand, int &index, int lineNum, bool one); + static Symbols macroExpand(Preprocessor *that, Symbols &toExpand, int &index, int lineNum, bool one, + const QSet<QByteArray> &excludeSymbols = QSet<QByteArray>()); int evaluateCondition(); diff --git a/src/tools/moc/symbols.h b/src/tools/moc/symbols.h index 35d4ed6ec9..b588cd5beb 100644 --- a/src/tools/moc/symbols.h +++ b/src/tools/moc/symbols.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the tools applications of the Qt Toolkit. @@ -134,6 +135,7 @@ typedef QVector<Symbol> Symbols; struct SafeSymbols { Symbols symbols; QByteArray expandedMacro; + QSet<QByteArray> excludedSymbols; int index; }; @@ -159,6 +161,7 @@ public: inline QByteArray unquotedLexem() { return symbol().unquotedLexem(); } bool dontReplaceSymbol(const QByteArray &name); + QSet<QByteArray> excludeSymbols(); }; inline bool SymbolStack::test(Token token) @@ -178,12 +181,22 @@ inline bool SymbolStack::test(Token token) inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name) { for (int i = 0; i < size(); ++i) { - if (name == at(i).expandedMacro) + if (name == at(i).expandedMacro || at(i).excludedSymbols.contains(name)) return true; } return false; } +inline QSet<QByteArray> SymbolStack::excludeSymbols() +{ + QSet<QByteArray> set; + for (int i = 0; i < size(); ++i) { + set << at(i).expandedMacro; + set += at(i).excludedSymbols; + } + return set; +} + QT_END_NAMESPACE #endif // SYMBOLS_H diff --git a/tests/auto/tools/moc/parse-defines.h b/tests/auto/tools/moc/parse-defines.h index 3e5841835d..f12899e368 100644 --- a/tests/auto/tools/moc/parse-defines.h +++ b/tests/auto/tools/moc/parse-defines.h @@ -76,6 +76,9 @@ #endif +#define PD_ADD_SUFFIX(x) PD_DEFINE1(x,_SUFFIX) +#define PD_DEFINE_ITSELF PD_ADD_SUFFIX(PD_DEFINE_ITSELF) + PD_BEGIN_NAMESPACE class PD_CLASSNAME : public QObject @@ -128,6 +131,8 @@ public slots: void conditionSlot() {} #endif + void PD_DEFINE_ITSELF(int) {} + }; #undef QString diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index f0d1934a93..ee82dc0652 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -2772,7 +2772,6 @@ void tst_Moc::parseDefines() } if (!qstrcmp(mci.name(), "TestString2")) { ++count; - qDebug() << mci.value(); QVERIFY(!qstrcmp(mci.value(), "ParseDefine")); } if (!qstrcmp(mci.name(), "TestString3")) { @@ -2781,6 +2780,9 @@ void tst_Moc::parseDefines() } } QVERIFY(count == 3); + + index = mo->indexOfSlot("PD_DEFINE_ITSELF_SUFFIX(int)"); + QVERIFY(index != -1); } void tst_Moc::preprocessorOnly() |