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>
This commit is contained in:
parent
ec166aaa70
commit
b05f19f232
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user