Fix moc preprocessor
When tokenizing, after macro expansion, moc needs to concatenate subsequent string literals, because parser do not check for such expressions. Change-Id: Icc4f01395a5a7b67368eb8341a45ee74ade7d7f5 Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
a8723871ee
commit
0c9d1f99da
@ -972,6 +972,36 @@ static QByteArray readOrMapFile(QFile *file)
|
|||||||
return rawInput ? QByteArray::fromRawData(rawInput, size) : file->readAll();
|
return rawInput ? QByteArray::fromRawData(rawInput, size) : file->readAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mergeStringLiterals(Symbols *_symbols)
|
||||||
|
{
|
||||||
|
Symbols &symbols = *_symbols;
|
||||||
|
for (Symbols::iterator i = symbols.begin(); i != symbols.end(); ++i) {
|
||||||
|
if (i->token == STRING_LITERAL) {
|
||||||
|
Symbols::Iterator mergeSymbol = i;
|
||||||
|
int literalsLength = mergeSymbol->len;
|
||||||
|
while (++i != symbols.end() && i->token == STRING_LITERAL)
|
||||||
|
literalsLength += i->len - 2; // no quotes
|
||||||
|
|
||||||
|
if (literalsLength != mergeSymbol->len) {
|
||||||
|
QByteArray mergeSymbolOriginalLexem = mergeSymbol->unquotedLexem();
|
||||||
|
QByteArray &mergeSymbolLexem = mergeSymbol->lex;
|
||||||
|
mergeSymbolLexem.resize(0);
|
||||||
|
mergeSymbolLexem.reserve(literalsLength);
|
||||||
|
mergeSymbolLexem.append('"');
|
||||||
|
mergeSymbolLexem.append(mergeSymbolOriginalLexem);
|
||||||
|
for (Symbols::const_iterator j = mergeSymbol + 1; j != i; ++j)
|
||||||
|
mergeSymbolLexem.append(j->lex.constData() + j->from + 1, j->len - 2); // append j->unquotedLexem()
|
||||||
|
mergeSymbolLexem.append('"');
|
||||||
|
mergeSymbol->len = mergeSymbol->lex.length();
|
||||||
|
mergeSymbol->from = 0;
|
||||||
|
i = symbols.erase(mergeSymbol + 1, i);
|
||||||
|
}
|
||||||
|
if (i == symbols.end())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
||||||
{
|
{
|
||||||
currentFilenames.push(filename);
|
currentFilenames.push(filename);
|
||||||
@ -1190,6 +1220,7 @@ Symbols Preprocessor::preprocessed(const QByteArray &filename, QFile *file)
|
|||||||
// phase 3: preprocess conditions and substitute macros
|
// phase 3: preprocess conditions and substitute macros
|
||||||
Symbols result;
|
Symbols result;
|
||||||
preprocess(filename, result);
|
preprocess(filename, result);
|
||||||
|
mergeStringLiterals(&result);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
for (int j = 0; j < result.size(); ++j)
|
for (int j = 0; j < result.size(); ++j)
|
||||||
|
@ -572,6 +572,7 @@ private slots:
|
|||||||
void relatedMetaObjectsInGadget();
|
void relatedMetaObjectsInGadget();
|
||||||
void relatedMetaObjectsNameConflict_data();
|
void relatedMetaObjectsNameConflict_data();
|
||||||
void relatedMetaObjectsNameConflict();
|
void relatedMetaObjectsNameConflict();
|
||||||
|
void strignLiteralsInMacroExtension();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigWithUnsignedArg(unsigned foo);
|
void sigWithUnsignedArg(unsigned foo);
|
||||||
@ -3269,6 +3270,45 @@ void tst_Moc::relatedMetaObjectsNameConflict()
|
|||||||
QCOMPARE(dependency.size(), relatedMetaObjects.size());
|
QCOMPARE(dependency.size(), relatedMetaObjects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StringLiteralsInMacroExtension: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
#define Macro(F) F " " F
|
||||||
|
Q_CLASSINFO(Macro("String"), Macro("Literal"))
|
||||||
|
#undef Macro
|
||||||
|
|
||||||
|
#define Macro(F) F
|
||||||
|
Q_CLASSINFO("String" Macro("!"), "Literal" Macro("!"))
|
||||||
|
Q_CLASSINFO(Macro("!") "String", Macro("!") "Literal")
|
||||||
|
#undef Macro
|
||||||
|
|
||||||
|
#define Macro "foo"
|
||||||
|
Q_CLASSINFO("String" Macro, "Literal" Macro)
|
||||||
|
Q_CLASSINFO(Macro "String", Macro "Literal")
|
||||||
|
#undef Macro
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_Moc::strignLiteralsInMacroExtension()
|
||||||
|
{
|
||||||
|
const QMetaObject *mobj = &StringLiteralsInMacroExtension::staticMetaObject;
|
||||||
|
QCOMPARE(mobj->classInfoCount(), 5);
|
||||||
|
|
||||||
|
QCOMPARE(mobj->classInfo(0).name(), "String String");
|
||||||
|
QCOMPARE(mobj->classInfo(0).value(), "Literal Literal");
|
||||||
|
|
||||||
|
QCOMPARE(mobj->classInfo(1).name(), "String!");
|
||||||
|
QCOMPARE(mobj->classInfo(1).value(), "Literal!");
|
||||||
|
|
||||||
|
QCOMPARE(mobj->classInfo(2).name(), "!String");
|
||||||
|
QCOMPARE(mobj->classInfo(2).value(), "!Literal");
|
||||||
|
|
||||||
|
QCOMPARE(mobj->classInfo(3).name(), "Stringfoo");
|
||||||
|
QCOMPARE(mobj->classInfo(3).value(), "Literalfoo");
|
||||||
|
|
||||||
|
QCOMPARE(mobj->classInfo(4).name(), "fooString");
|
||||||
|
QCOMPARE(mobj->classInfo(4).value(), "fooLiteral");
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_Moc)
|
QTEST_MAIN(tst_Moc)
|
||||||
|
|
||||||
// the generated code must compile with QT_NO_KEYWORDS
|
// the generated code must compile with QT_NO_KEYWORDS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user