summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2013-03-04 16:52:12 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-14 09:42:53 +0100
commit2b26f801b5b49e2f354da0b67070917d25d5917d (patch)
treec3542211d7827e2d05cbf18281af00c16d99e89b
parent8e261ac756132baeb857fb15013cde126ffa22cc (diff)
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.cpp2
-rw-r--r--src/corelib/kernel/qmetaobject_moc_p.h31
-rw-r--r--src/tools/moc/moc.cpp38
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp19
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()