diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-11-17 11:51:16 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-11-30 14:58:31 (GMT) |
commit | b881d8fb99972f1bd04ab4c84843cc8d43ddbeed (patch) | |
tree | f415bc8c76ecc388d05f940a02e2c863dc96f111 /src | |
parent | f3ac20ac8100142cde0accfb72eab48590303c4a (diff) | |
download | Qt-b881d8fb99972f1bd04ab4c84843cc8d43ddbeed.zip Qt-b881d8fb99972f1bd04ab4c84843cc8d43ddbeed.tar.gz Qt-b881d8fb99972f1bd04ab4c84843cc8d43ddbeed.tar.bz2 |
Fix certain type-const-ref syntax not recognized by normalizedSignature()
Normally, const Type & is normalized to just Type, but this didn't
work for Template<T>const& or Type*const& types. This now works as
expected.
However, this changes the way these types are normalized, and existing
code using the old syntax will break. We can prevent this breakage by
also normalizing the method signature in the metaobject when looking
up signals and slots in QObject::connect(). I have added an autotest
for this, which includes moc output generated by Qt 4.6's moc. This
means we need to bump the metaobject revision number even though we
are not adding any new data (only changing the normalized strings we
store).
Task-number: QTBUG-2407
Task-number: QTBUG-3722
Reviewed-by: ogoffart
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 58 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 24 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 36 | ||||
-rw-r--r-- | src/tools/moc/generator.cpp | 2 |
4 files changed, 93 insertions, 27 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index ad9db09..bc1e8dcc 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -488,18 +488,30 @@ int QMetaObject::classInfoCount() const * \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything. */ template<int MethodType> -static inline int indexOfMethodRelative(const QMetaObject **baseObject, const char *method) +static inline int indexOfMethodRelative(const QMetaObject **baseObject, + const char *method, + bool normalizeStringData) { while (*baseObject) { const QMetaObject *const m = *baseObject; int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4) - ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1); + ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1); const int end = (MethodType == MethodSlot && priv(m->d.data)->revision >= 4) - ? (priv(m->d.data)->signalCount - 1) : 0; - for (; i >= end; --i) { - if ((MethodType == 0 || (m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodType) - && strcmp(method, m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) - return i; + ? (priv(m->d.data)->signalCount - 1) : 0; + if (!normalizeStringData) { + for (; i >= end; --i) { + if ((MethodType == 0 || (m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodType) + && strcmp(method, m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) + return i; + } + } else if (priv(m->d.data)->revision < 5) { + const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]); + const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata); + for (; i >= end; --i) { + if ((MethodType == 0|| (m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodType) + && normalizedSignature == method) + return i; + } } *baseObject = m->d.superdata; } @@ -541,7 +553,11 @@ int QMetaObject::indexOfConstructor(const char *constructor) const int QMetaObject::indexOfMethod(const char *method) const { const QMetaObject *m = this; - int i = indexOfMethodRelative<0>(&m, method); + int i = indexOfMethodRelative<0>(&m, method, false); + if (i < 0) { + m = this; + i = indexOfMethodRelative<0>(&m, method, true); + } if (i >= 0) i += m->methodOffset(); return i; @@ -561,7 +577,11 @@ int QMetaObject::indexOfMethod(const char *method) const int QMetaObject::indexOfSignal(const char *signal) const { const QMetaObject *m = this; - int i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal); + int i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, false); + if (i < 0) { + m = this; + i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, true); + } if (i >= 0) i += m->methodOffset(); return i; @@ -572,9 +592,11 @@ int QMetaObject::indexOfSignal(const char *signal) const \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found */ -int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject, const char *signal) +int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject, + const char *signal, + bool normalizeStringData) { - int i = indexOfMethodRelative<MethodSignal>(baseObject, signal); + int i = indexOfMethodRelative<MethodSignal>(baseObject, signal, normalizeStringData); #ifndef QT_NO_DEBUG const QMetaObject *m = *baseObject; if (i >= 0 && m && m->d.superdata) { @@ -587,7 +609,6 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject, co return i; } - /*! Finds \a slot and returns its index; otherwise returns -1. @@ -598,8 +619,17 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject, co */ int QMetaObject::indexOfSlot(const char *slot) const { - const QMetaObject *m = this; - int i = indexOfMethodRelative<MethodSlot>(&m, slot); + int i = QMetaObjectPrivate::indexOfSlot(this, slot, false); + if (i < 0) + i = QMetaObjectPrivate::indexOfSlot(this, slot, true); + return i; +} + +int QMetaObjectPrivate::indexOfSlot(const QMetaObject *m, + const char *slot, + bool normalizeStringData) +{ + int i = indexOfMethodRelative<MethodSlot>(&m, slot, normalizeStringData); if (i >= 0) i += m->methodOffset(); return i; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index b5a7530..7afb70b 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -115,11 +115,17 @@ struct QMetaObjectPrivate int constructorCount, constructorData; //since revision 2 int flags; //since revision 3 int signalCount; //since revision 4 + // revision 5 introduces changes in normalized signatures, no new members static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject) { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); } - static int indexOfSignalRelative(const QMetaObject **baseObject, const char* name); + static int indexOfSignalRelative(const QMetaObject **baseObject, + const char* name, + bool normalizeStringData); + static int indexOfSlot(const QMetaObject *m, + const char *slot, + bool normalizeStringData); static int originalClone(const QMetaObject *obj, int local_method_index); #ifndef QT_NO_QOBJECT @@ -245,6 +251,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc } while (optional[++i].keyword != 0); } + bool star = false; while (t != e) { char c = *t++; if (fixScope && c == ':' && *t == ':' ) { @@ -255,6 +262,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc --i; result.resize(i + 1); } + star = star || c == '*'; result += c; if (c == '<') { //template recursion @@ -275,6 +283,20 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc } } } + + // cv qualifers can appear after the type as well + if (t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)) { + t += 5; + while (t != e && is_space(*t)) + ++t; + if (adjustConst && t != e && *t == '&') { + // treat const ref as value + ++t; + } else if (!star) { + // move const to the front (but not if const comes after a *) + result.prepend("const "); + } + } } return result; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 95602d9..52c94e9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2522,20 +2522,25 @@ bool QObject::connect(const QObject *sender, const char *signal, const QMetaObject *smeta = sender->metaObject(); const char *signal_arg = signal; ++signal; //skip code - int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal); + int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false); if (signal_index < 0) { // check for normalized signatures tmp_signal_name = QMetaObject::normalizedSignature(signal - 1); signal = tmp_signal_name.constData() + 1; smeta = sender->metaObject(); - signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false); + } + if (signal_index < 0) { + // re-use tmp_signal_name and signal from above - if (signal_index < 0) { - err_method_notfound(sender, signal_arg, "connect"); - err_info_about_objects("connect", sender, receiver); - return false; - } + smeta = sender->metaObject(); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true); + } + if (signal_index < 0) { + err_method_notfound(sender, signal_arg, "connect"); + err_info_about_objects("connect", sender, receiver); + return false; } signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index); int signalOffset, methodOffset; @@ -2555,16 +2560,21 @@ bool QObject::connect(const QObject *sender, const char *signal, int method_index = -1; switch (membcode) { case QSLOT_CODE: - method_index = rmeta->indexOfSlot(method); + method_index = QMetaObjectPrivate::indexOfSlot(rmeta, method, false); break; case QSIGNAL_CODE: - method_index = rmeta->indexOfSignal(method); + method_index = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false); + if (method_index >= 0) + method_index += rmeta->methodOffset(); break; } if (method_index < 0) { // check for normalized methods tmp_method_name = QMetaObject::normalizedSignature(method); method = tmp_method_name.constData(); + + // rmeta may have been modified above + rmeta = receiver->metaObject(); switch (membcode) { case QSLOT_CODE: method_index = rmeta->indexOfSlot(method); @@ -2752,7 +2762,9 @@ bool QObject::disconnect(const QObject *sender, const char *signal, do { int signal_index = -1; if (signal) { - signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false); + if (signal_index < 0) + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true); if (signal_index < 0) break; signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index); @@ -3361,7 +3373,9 @@ int QObjectPrivate::signalIndex(const char *signalName) const { Q_Q(const QObject); const QMetaObject *base = q->metaObject(); - int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName); + int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false); + if (relative_index < 0) + relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true); if (relative_index < 0) return relative_index; relative_index = QMetaObjectPrivate::originalClone(base, relative_index); diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 1ed6586..b99cb28 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -173,7 +173,7 @@ void Generator::generateCode() int index = 14; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); - fprintf(out, " %4d, // revision\n", 4); + fprintf(out, " %4d, // revision\n", 5); fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; |