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>
This commit is contained in:
parent
8e261ac756
commit
2b26f801b5
@ -677,7 +677,7 @@ QByteArray QMetaObjectPrivate::decodeMethodSignature(
|
|||||||
const char *lparens = strchr(signature, '(');
|
const char *lparens = strchr(signature, '(');
|
||||||
if (!lparens)
|
if (!lparens)
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
const char *rparens = strchr(lparens + 1, ')');
|
const char *rparens = strrchr(lparens + 1, ')');
|
||||||
if (!rparens || *(rparens+1))
|
if (!rparens || *(rparens+1))
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
int nameLength = lparens - signature;
|
int nameLength = lparens - signature;
|
||||||
|
@ -155,21 +155,28 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc
|
|||||||
//template recursion
|
//template recursion
|
||||||
const char* tt = t;
|
const char* tt = t;
|
||||||
int templdepth = 1;
|
int templdepth = 1;
|
||||||
|
int scopeDepth = 0;
|
||||||
while (t != e) {
|
while (t != e) {
|
||||||
c = *t++;
|
c = *t++;
|
||||||
if (c == '<')
|
if (c == '{' || c == '(' || c == '[')
|
||||||
++templdepth;
|
++scopeDepth;
|
||||||
if (c == '>')
|
if (c == '}' || c == ')' || c == ']')
|
||||||
--templdepth;
|
--scopeDepth;
|
||||||
if (templdepth == 0 || (templdepth == 1 && c == ',')) {
|
if (scopeDepth == 0) {
|
||||||
result += normalizeTypeInternal(tt, t-1, fixScope, false);
|
if (c == '<')
|
||||||
result += c;
|
++templdepth;
|
||||||
if (templdepth == 0) {
|
if (c == '>')
|
||||||
if (*t == '>')
|
--templdepth;
|
||||||
result += ' '; // avoid >>
|
if (templdepth == 0 || (templdepth == 1 && c == ',')) {
|
||||||
break;
|
result += normalizeTypeInternal(tt, t-1, fixScope, false);
|
||||||
|
result += c;
|
||||||
|
if (templdepth == 0) {
|
||||||
|
if (*t == '>')
|
||||||
|
result += ' '; // avoid >>
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tt = t;
|
||||||
}
|
}
|
||||||
tt = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,14 +224,7 @@ Type Moc::parseType()
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
if (test(LANGLE)) {
|
if (test(LANGLE)) {
|
||||||
QByteArray templ = lexemUntil(RANGLE);
|
type.name += 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 += ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (test(SCOPE)) {
|
if (test(SCOPE)) {
|
||||||
type.name += lexem();
|
type.name += lexem();
|
||||||
@ -1395,10 +1388,14 @@ QByteArray Moc::lexemUntil(Token target)
|
|||||||
QByteArray s;
|
QByteArray s;
|
||||||
while (from <= index) {
|
while (from <= index) {
|
||||||
QByteArray n = symbols.at(from++-1).lexem();
|
QByteArray n = symbols.at(from++-1).lexem();
|
||||||
if (s.size() && n.size()
|
if (s.size() && n.size()) {
|
||||||
&& is_ident_char(s.at(s.size()-1))
|
char prev = s.at(s.size()-1);
|
||||||
&& is_ident_char(n.at(0)))
|
char next = n.at(0);
|
||||||
s += ' ';
|
if ((is_ident_char(prev) && is_ident_char(next))
|
||||||
|
|| (prev == '<' && next == ':')
|
||||||
|
|| (prev == '>' && next == '>'))
|
||||||
|
s += ' ';
|
||||||
|
}
|
||||||
s += n;
|
s += n;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@ -1433,9 +1430,20 @@ bool Moc::until(Token target) {
|
|||||||
case RBRACK: --brackCount; break;
|
case RBRACK: --brackCount; break;
|
||||||
case LPAREN: ++parenCount; break;
|
case LPAREN: ++parenCount; break;
|
||||||
case RPAREN: --parenCount; break;
|
case RPAREN: --parenCount; break;
|
||||||
case LANGLE: ++angleCount; break;
|
case LANGLE:
|
||||||
case RANGLE: --angleCount; break;
|
if (parenCount == 0 && braceCount == 0 && parenCount == 0)
|
||||||
case GTGT: angleCount -= 2; t = RANGLE; break;
|
++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;
|
default: break;
|
||||||
}
|
}
|
||||||
if (t == target
|
if (t == target
|
||||||
|
@ -1538,13 +1538,30 @@ class QTBUG12260_defaultTemplate_Object : public QObject
|
|||||||
public slots:
|
public slots:
|
||||||
#if !(defined(Q_CC_GNU) && __GNUC__ == 4 && __GNUC_MINOR__ <= 3) || defined(Q_MOC_RUN)
|
#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 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
|
#else
|
||||||
// we want to test the previous function, but gcc < 4.4 seemed to have a bug similar to the one moc has.
|
// 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;
|
typedef QHash<QString, QVariant> WorkaroundGCCBug;
|
||||||
void doSomething(QHash<QString, QVariant> values = WorkaroundGCCBug() ) { Q_UNUSED(values); }
|
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
|
#endif
|
||||||
|
|
||||||
void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); }
|
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("doSomething(QHash<QString,QVariant>)") != -1);
|
||||||
QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doAnotherThing(bool,bool)") != -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()
|
void tst_Moc::notifyError()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user