summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-11-17 11:51:16 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-11-30 14:58:31 (GMT)
commitb881d8fb99972f1bd04ab4c84843cc8d43ddbeed (patch)
treef415bc8c76ecc388d05f940a02e2c863dc96f111 /src
parentf3ac20ac8100142cde0accfb72eab48590303c4a (diff)
downloadQt-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.cpp58
-rw-r--r--src/corelib/kernel/qmetaobject_p.h24
-rw-r--r--src/corelib/kernel/qobject.cpp36
-rw-r--r--src/tools/moc/generator.cpp2
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;