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, '(');
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user