diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2013-03-04 16:52:12 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-14 09:42:53 +0100 |
commit | 2b26f801b5b49e2f354da0b67070917d25d5917d (patch) | |
tree | c3542211d7827e2d05cbf18281af00c16d99e89b | |
parent | 8e261ac756132baeb857fb15013cde126ffa22cc (diff) | |
download | qtbase-2b26f801b5b49e2f354da0b67070917d25d5917d.tar.gz qtbase-2b26f801b5b49e2f354da0b67070917d25d5917d.tar.bz2 qtbase-2b26f801b5b49e2f354da0b67070917d25d5917d.zip |
Make parsing of template arguments more robust.
At first, my goal was just to fix Moc::until() to parse properly
template arguments containing expressions containing > or >>
such as Foo<(8>>2)>
But with the test, I realized that normalizeType also requires change
not to split the > > too much.
And QMetaObjectPrivate::decodeMethodSignature should not interpret
the ) within the template parameter as the end of the function.
Change-Id: Ia9d3a2a786368aeda1edcf66280d70f64cf05070
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_moc_p.h | 31 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 38 | ||||
-rw-r--r-- | tests/auto/tools/moc/tst_moc.cpp | 19 |
4 files changed, 62 insertions, 28 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index ff2675dfc8..1e11887387 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -677,7 +677,7 @@ QByteArray QMetaObjectPrivate::decodeMethodSignature( const char *lparens = strchr(signature, '('); if (!lparens) return QByteArray(); - const char *rparens = strchr(lparens + 1, ')'); + const char *rparens = strrchr(lparens + 1, ')'); if (!rparens || *(rparens+1)) return QByteArray(); int nameLength = lparens - signature; diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h index c791f017d4..d26cd54e5d 100644 --- a/src/corelib/kernel/qmetaobject_moc_p.h +++ b/src/corelib/kernel/qmetaobject_moc_p.h @@ -155,21 +155,28 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc //template recursion const char* tt = t; int templdepth = 1; + int scopeDepth = 0; while (t != e) { c = *t++; - if (c == '<') - ++templdepth; - if (c == '>') - --templdepth; - if (templdepth == 0 || (templdepth == 1 && c == ',')) { - result += normalizeTypeInternal(tt, t-1, fixScope, false); - result += c; - if (templdepth == 0) { - if (*t == '>') - result += ' '; // avoid >> - break; + if (c == '{' || c == '(' || c == '[') + ++scopeDepth; + if (c == '}' || c == ')' || c == ']') + --scopeDepth; + if (scopeDepth == 0) { + if (c == '<') + ++templdepth; + if (c == '>') + --templdepth; + if (templdepth == 0 || (templdepth == 1 && c == ',')) { + result += normalizeTypeInternal(tt, t-1, fixScope, false); + result += c; + if (templdepth == 0) { + if (*t == '>') + result += ' '; // avoid >> + break; + } + tt = t; } - tt = t; } } } diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 8ff481d5b1..22cbb97364 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -224,14 +224,7 @@ Type Moc::parseType() ; } if (test(LANGLE)) { - QByteArray templ = lexemUntil(RANGLE); - for (int i = 0; i < templ.size(); ++i) { - type.name += templ.at(i); - if ((templ.at(i) == '<' && i+1 < templ.size() && templ.at(i+1) == ':') - || (templ.at(i) == '>' && i+1 < templ.size() && templ.at(i+1) == '>')) { - type.name += ' '; - } - } + type.name += lexemUntil(RANGLE); } if (test(SCOPE)) { type.name += lexem(); @@ -1395,10 +1388,14 @@ QByteArray Moc::lexemUntil(Token target) QByteArray s; while (from <= index) { QByteArray n = symbols.at(from++-1).lexem(); - if (s.size() && n.size() - && is_ident_char(s.at(s.size()-1)) - && is_ident_char(n.at(0))) - s += ' '; + if (s.size() && n.size()) { + char prev = s.at(s.size()-1); + char next = n.at(0); + if ((is_ident_char(prev) && is_ident_char(next)) + || (prev == '<' && next == ':') + || (prev == '>' && next == '>')) + s += ' '; + } s += n; } return s; @@ -1433,9 +1430,20 @@ bool Moc::until(Token target) { case RBRACK: --brackCount; break; case LPAREN: ++parenCount; break; case RPAREN: --parenCount; break; - case LANGLE: ++angleCount; break; - case RANGLE: --angleCount; break; - case GTGT: angleCount -= 2; t = RANGLE; break; + case LANGLE: + if (parenCount == 0 && braceCount == 0 && parenCount == 0) + ++angleCount; + break; + case RANGLE: + if (parenCount == 0 && braceCount == 0) + --angleCount; + break; + case GTGT: + if (parenCount == 0 && braceCount == 0) { + angleCount -= 2; + t = RANGLE; + } + break; default: break; } if (t == target diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 8ce55cbdf5..e26b02a560 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1538,13 +1538,30 @@ class QTBUG12260_defaultTemplate_Object : public QObject public slots: #if !(defined(Q_CC_GNU) && __GNUC__ == 4 && __GNUC_MINOR__ <= 3) || defined(Q_MOC_RUN) void doSomething(QHash<QString, QVariant> values = QHash<QString, QVariant>() ) { Q_UNUSED(values); } + void doSomethingElse(QSharedPointer<QVarLengthArray<QString, (16 >> 2)> > val + = QSharedPointer<QVarLengthArray<QString, (16 >> 2)> >() ) + { Q_UNUSED(val); } #else // we want to test the previous function, but gcc < 4.4 seemed to have a bug similar to the one moc has. typedef QHash<QString, QVariant> WorkaroundGCCBug; void doSomething(QHash<QString, QVariant> values = WorkaroundGCCBug() ) { Q_UNUSED(values); } + void doSomethingElse(QSharedPointer<QVarLengthArray<QString, (16 >> 2)> > val + = (QSharedPointer<QVarLengthArray<QString, (16 >> 2)> >()) ) + { Q_UNUSED(val); } #endif void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); } + +#if defined(Q_MOC_RUN) || (defined(Q_COMPILER_AUTO_TYPE) && !(defined(Q_CC_CLANG) && (__clang_major__ * 100) + __clang_minor__) < 304) + // There is no Q_COMPILER_>> but if compiler support auto, it should also support >> + void performSomething(QVector<QList<QString>> e = QVector<QList<QString>>(8 < 1), + QHash<int, QVector<QString>> h = QHash<int, QVector<QString>>()) + { Q_UNUSED(e); Q_UNUSED(h); } +#else + void performSomething(QVector<QList<QString> > e = QVector<QList<QString> >(), + QHash<int, QVector<QString> > h = (QHash<int, QVector<QString> >())) + { Q_UNUSED(e); Q_UNUSED(h); } +#endif }; @@ -1552,6 +1569,8 @@ void tst_Moc::QTBUG12260_defaultTemplate() { QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomething(QHash<QString,QVariant>)") != -1); QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doAnotherThing(bool,bool)") != -1); + QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomethingElse(QSharedPointer<QVarLengthArray<QString,(16>>2)> >)") != -1); + QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("performSomething(QVector<QList<QString> >,QHash<int,QVector<QString> >)") != -1); } void tst_Moc::notifyError() |