Introduce QMetaType::UnknownType.
authorJędrzej Nowacki <jedrzej.nowacki@nokia.com>
Mon, 13 Feb 2012 15:26:35 +0000 (16:26 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 2 Mar 2012 11:57:29 +0000 (12:57 +0100)
QMetaType::Void was ambiguous, it was pointing to a valid type (void)
and in the same time it was signaling errors in QMetaType. There was
no clean way to check if returned type was valid void or some
unregistered type.

This feature will be used by new QMetaObject revision which will
store type ids instead of type names. So it will be easy to
distinguish between:
 void mySlot();
 MyUnregisteredType mySlot();

Change-Id: I73ff097f75585a95e12df74d50c6f3141153e771
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
20 files changed:
dist/changes-5.0.0
doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp
src/corelib/kernel/qmetaobject.cpp
src/corelib/kernel/qmetatype.cpp
src/corelib/kernel/qmetatype.h
src/corelib/kernel/qmetatypeswitcher_p.h
src/corelib/kernel/qvariant.cpp
src/corelib/kernel/qvariant.h
src/corelib/kernel/qvariant_p.h
src/dbus/qdbusintegrator.cpp
src/dbus/qdbusmetaobject.cpp
src/dbus/qdbusmetatype.cpp
src/dbus/qdbusmisc.cpp
src/testlib/qsignaldumper.cpp
src/testlib/qsignalspy.h
src/tools/moc/generator.cpp
src/tools/moc/moc.cpp
tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp

index cb1f8f4..95dbe0b 100644 (file)
@@ -516,6 +516,20 @@ Qt for Windows CE
     QMetaType::User, which means that it points to the first registered custom
     type, instead of a nonexistent type.
 
+- QMetaType
+
+  * Interpretation of QMetaType::Void was changed. Before, in some cases
+    it was returned as an invalid type id, but sometimes it was used as a valid
+    type (C++ "void"). In Qt5, new QMetaType::UnknownType was introduced to
+    distinguish between these two. QMetaType::UnknownType is an invalid type id
+    signaling that a type is unknown to QMetaType, and QMetaType::Void
+    is a valid type id of C++ void type. The difference will be visible for
+    example in call to QMetaType::typeName(), this function will return null for
+    QMetaType::UnknownType and a pointer to "void" string for
+    QMetaType::Void.
+    Please, notice that QMetaType::UnknownType has value 0, which previously was
+    reserved for QMetaType::Void.
+
 
 - QMessageBox
 
index 9d72c42..d0a7a69 100644 (file)
@@ -73,7 +73,7 @@ MyStruct s2 = var.value<MyStruct>();
 
 //! [3]
 int id = QMetaType::type("MyClass");
-if (id != 0) {
+if (id != QMetaType::UnknownType) {
     void *myClassPtr = QMetaType::create(id);
     ...
     QMetaType::destroy(id, myClassPtr);
index b38e7f9..e446d8b 100644 (file)
@@ -1792,14 +1792,14 @@ QByteArray QMetaMethod::name() const
     Returns the return type of this method.
 
     The return value is one of the types that are registered
-    with QMetaType, or 0 if the type is not registered.
+    with QMetaType, or QMetaType::UnknownType if the type is not registered.
 
     \sa parameterType(), QMetaType, typeName()
 */
 int QMetaMethod::returnType() const
  {
      if (!mobj)
-         return 0;
+         return QMetaType::UnknownType;
     return QMetaMethodPrivate::get(this)->returnType();
 }
 
@@ -1823,16 +1823,16 @@ int QMetaMethod::parameterCount() const
     Returns the type of the parameter at the given \a index.
 
     The return value is one of the types that are registered
-    with QMetaType, or 0 if the type is not registered.
+    with QMetaType, or QMetaType::UnknownType if the type is not registered.
 
     \sa parameterCount(), returnType(), QMetaType
 */
 int QMetaMethod::parameterType(int index) const
 {
     if (!mobj || index < 0)
-        return 0;
+        return QMetaType::UnknownType;
     if (index >= QMetaMethodPrivate::get(this)->parameterCount())
-        return 0;
+        return QMetaType::UnknownType;
     return QMetaMethodPrivate::get(this)->parameterType(index);
 }
 
@@ -2241,7 +2241,7 @@ bool QMetaMethod::invoke(QObject *object,
 
         for (int i = 1; i < paramCount; ++i) {
             types[i] = QMetaType::type(typeNames[i]);
-            if (types[i]) {
+            if (types[i] != QMetaType::UnknownType) {
                 args[i] = QMetaType::create(types[i], param[i]);
                 ++nargs;
             } else if (param[i]) {
@@ -2715,11 +2715,11 @@ QVariant::Type QMetaProperty::type() const
         uint flags = mobj->d.data[handle + 2];
         type = flags >> 24;
     }
-    if (type)
+    if (type != QMetaType::UnknownType)
         return QVariant::Type(type);
     if (isEnumType()) {
         int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
-        if (enumMetaTypeId == 0)
+        if (enumMetaTypeId == QMetaType::UnknownType)
             return QVariant::Int;
     }
 #ifdef QT_COORD_TYPE
@@ -2735,7 +2735,7 @@ QVariant::Type QMetaProperty::type() const
     \since 4.2
 
     Returns this property's user type. The return value is one
-    of the values that are registered with QMetaType, or 0 if
+    of the values that are registered with QMetaType, or QMetaType::UnknownType if
     the type is not registered.
 
     \sa type(), QMetaType, typeName()
@@ -2743,11 +2743,11 @@ QVariant::Type QMetaProperty::type() const
 int QMetaProperty::userType() const
 {
     if (!mobj)
-        return 0;
+        return QMetaType::UnknownType;
     if (priv(mobj->d.data)->revision >= 7) {
         int handle = priv(mobj->d.data)->propertyData + 3*idx;
         int type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
-        if (type)
+        if (type != QMetaType::UnknownType)
             return type;
     } else {
         QVariant::Type tp = type();
@@ -2756,7 +2756,7 @@ int QMetaProperty::userType() const
     }
     if (isEnumType()) {
         int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
-        if (enumMetaTypeId == 0)
+        if (enumMetaTypeId == QMetaType::UnknownType)
             return QVariant::Int; // Match behavior of QMetaType::type()
         return enumMetaTypeId;
     }
@@ -2853,7 +2853,7 @@ QVariant QMetaProperty::read(const QObject *object) const
           with QMetaType)
         */
         int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
-        if (enumMetaTypeId != 0)
+        if (enumMetaTypeId != QMetaType::UnknownType)
             t = enumMetaTypeId;
     } else {
         int handle = priv(mobj->d.data)->propertyData + 3*idx;
@@ -2869,14 +2869,14 @@ QVariant QMetaProperty::read(const QObject *object) const
         } else {
             uint flags = mobj->d.data[handle + 2];
             t = (flags >> 24);
-            if (t == QVariant::Invalid) {
+            if (t == QMetaType::UnknownType) {
                 typeName = legacyString(mobj, mobj->d.data[handle + 1]);
                 t = QMetaType::type(typeName);
-                if (t == QVariant::Invalid)
+                if (t == QMetaType::UnknownType)
                     t = QVariant::nameToType(typeName);
             }
         }
-        if (t == QVariant::Invalid) {
+        if (t == QMetaType::UnknownType) {
             qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
             return QVariant();
         }
@@ -2931,7 +2931,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
                 return false;
         } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
             int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
-            if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+            if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
                 return false;
             v = QVariant(*reinterpret_cast<const int *>(v.constData()));
         }
@@ -2952,7 +2952,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
             t = flags >> 24;
             typeName = legacyString(mobj, mobj->d.data[handle + 1]);
         }
-        if (t == QVariant::Invalid) {
+        if (t == QMetaType::UnknownType) {
             const char *typeName = rawStringData(mobj, mobj->d.data[handle + 1]);
             const char *vtypeName = value.typeName();
             if (vtypeName && strcmp(typeName, vtypeName) == 0)
index 003ad1c..6d5973a 100644 (file)
@@ -242,6 +242,7 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals
     \value QEasingCurve QEasingCurve
 
     \value User  Base value for user types
+    \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
 
     \omitvalue FirstGuiType
     \omitvalue FirstWidgetsType
@@ -311,7 +312,7 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
     QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
     QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
     QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
-    {0, 0, QMetaType::Void}
+    {0, 0, QMetaType::UnknownType}
 };
 
 Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = 0;
@@ -348,10 +349,7 @@ Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
 void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
                                         LoadOperator loadOp)
 {
-    int idx = type(typeName);
-    if (!idx)
-        return;
-    registerStreamOperators(idx, saveOp, loadOp);
+    registerStreamOperators(type(typeName), saveOp, loadOp);
 }
 
 /*! \internal
@@ -434,7 +432,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
 {
     const QVector<QCustomTypeInfo> * const ct = customTypes();
     if (!ct)
-        return 0;
+        return QMetaType::UnknownType;
 
     for (int v = 0; v < ct->count(); ++v) {
         const QCustomTypeInfo &customInfo = ct->at(v);
@@ -445,7 +443,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
             return v + QMetaType::User;
         }
     }
-    return 0;
+    return QMetaType::UnknownType;
 }
 
 /*! \internal
@@ -488,11 +486,11 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
 
     int previousSize = 0;
     int previousFlags = 0;
-    if (!idx) {
+    if (idx == UnknownType) {
         QWriteLocker locker(customTypesLock());
         idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
                                            normalizedTypeName.size());
-        if (!idx) {
+        if (idx == UnknownType) {
             QCustomTypeInfo inf;
             inf.typeName = normalizedTypeName;
             inf.creator = creator;
@@ -558,12 +556,12 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
     int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
                                   normalizedTypeName.size());
 
-    if (!idx) {
+    if (idx == UnknownType) {
         QWriteLocker locker(customTypesLock());
         idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
                                                normalizedTypeName.size());
 
-        if (!idx) {
+        if (idx == UnknownType) {
             QCustomTypeInfo inf;
             inf.typeName = normalizedTypeName;
             inf.alias = aliasId;
@@ -592,17 +590,20 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
 */
 bool QMetaType::isRegistered(int type)
 {
-    if (type >= 0 && type < User) {
-        // predefined type
+    // predefined type
+    if ((type >= FirstCoreType && type <= LastCoreType)
+        || (type >= FirstGuiType && type <= LastGuiType)
+        || (type >= FirstWidgetsType && type <= LastWidgetsType)) {
         return true;
     }
+
     QReadLocker locker(customTypesLock());
     const QVector<QCustomTypeInfo> * const ct = customTypes();
     return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
 }
 
 /*!
-    Returns a handle to the type called \a typeName, or 0 if there is
+    Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
     no such type.
 
     \sa isRegistered(), typeName(), Type
@@ -611,17 +612,17 @@ int QMetaType::type(const char *typeName)
 {
     int length = qstrlen(typeName);
     if (!length)
-        return 0;
+        return UnknownType;
     int type = qMetaTypeStaticType(typeName, length);
-    if (!type) {
+    if (type == UnknownType) {
         QReadLocker locker(customTypesLock());
         type = qMetaTypeCustomType_unlocked(typeName, length);
 #ifndef QT_NO_QOBJECT
-        if (!type) {
+        if (type == UnknownType) {
             const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
             type = qMetaTypeStaticType(normalizedTypeName.constData(),
                                        normalizedTypeName.size());
-            if (!type) {
+            if (type == UnknownType) {
                 type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
                                                     normalizedTypeName.size());
             }
@@ -652,6 +653,7 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
         return false;
 
     switch(type) {
+    case QMetaType::UnknownType:
     case QMetaType::Void:
     case QMetaType::VoidStar:
     case QMetaType::QObjectStar:
@@ -857,6 +859,7 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
         return false;
 
     switch(type) {
+    case QMetaType::UnknownType:
     case QMetaType::Void:
     case QMetaType::VoidStar:
     case QMetaType::QObjectStar:
@@ -1154,6 +1157,7 @@ void *QMetaType::create(int type, const void *copy)
         case QMetaType::QModelIndex:
             return new NS(QModelIndex)(*static_cast<const NS(QModelIndex)*>(copy));
 #endif
+        case QMetaType::UnknownType:
         case QMetaType::Void:
             return 0;
         default:
@@ -1257,6 +1261,7 @@ void *QMetaType::create(int type, const void *copy)
         case QMetaType::QModelIndex:
             return new NS(QModelIndex);
 #endif
+        case QMetaType::UnknownType:
         case QMetaType::Void:
             return 0;
         default:
@@ -1318,6 +1323,7 @@ public:
     template<typename T>
     void delegate(const T *where) { DestroyerImpl<T>::Destroy(m_type, const_cast<T*>(where)); }
     void delegate(const void *) {}
+    void delegate(const QMetaTypeSwitcher::UnknownType*) {}
     void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestroyer(m_type, (void*)where); }
 
 private:
@@ -1380,6 +1386,7 @@ public:
     template<typename T>
     void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); }
     void *delegate(const void *) { return m_where; }
+    void *delegate(const QMetaTypeSwitcher::UnknownType*) { return m_where; }
     void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(m_type, m_where, copy); }
 
 private:
@@ -1468,6 +1475,7 @@ public:
     template<typename T>
     void delegate(const T *where) { DestructorImpl<T>::Destruct(m_type, const_cast<T*>(where)); }
     void delegate(const void *) {}
+    void delegate(const QMetaTypeSwitcher::UnknownType*) {}
     void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestructor(m_type, (void*)where); }
 
 private:
@@ -1536,6 +1544,7 @@ public:
 
     template<typename T>
     int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); }
+    int delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
     int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(m_type); }
 private:
     static int customTypeSizeOf(const int type)
@@ -1606,13 +1615,14 @@ public:
     template<typename T>
     quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
     quint32 delegate(const void*) { return 0; }
+    quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
     quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(m_type); }
 private:
     const int m_type;
     static quint32 customTypeFlags(const int type)
     {
         const QVector<QCustomTypeInfo> * const ct = customTypes();
-        if (Q_UNLIKELY(!ct))
+        if (Q_UNLIKELY(!ct || type < QMetaType::User))
             return 0;
         QReadLocker locker(customTypesLock());
         if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
@@ -1793,6 +1803,7 @@ public:
     template<typename T>
     void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
     void delegate(const void*) {}
+    void delegate(const QMetaTypeSwitcher::UnknownType*) {}
     void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(m_type); }
 private:
     void customTypeInfo(const uint type)
@@ -1813,7 +1824,7 @@ QMetaType QMetaType::typeInfo(const int type)
 {
     TypeInfo typeInfo(type);
     QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
-    return typeInfo.info.creator || !type ? QMetaType(QMetaType::NoExtensionFlags
+    return typeInfo.info.creator || type == Void ? QMetaType(QMetaType::NoExtensionFlags
                                  , static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
                                  , typeInfo.info.creator
                                  , typeInfo.info.deleter
@@ -1824,26 +1835,23 @@ QMetaType QMetaType::typeInfo(const int type)
                                  , typeInfo.info.size
                                  , typeInfo.info.flags
                                  , type)
-                : QMetaType(-1);
+                : QMetaType(UnknownType);
 }
 
 QMetaType::QMetaType(const int typeId)
     : m_typeId(typeId)
 {
-    if (Q_UNLIKELY(typeId == -1)) {
+    if (Q_UNLIKELY(typeId == UnknownType)) {
         // Constructs invalid QMetaType instance.
         m_extensionFlags = 0xffffffff;
         Q_ASSERT(!isValid());
     } else {
         // TODO it can be better.
         *this = QMetaType::typeInfo(typeId);
-        if (m_typeId > 0 && !m_creator) {
+        if (m_typeId == UnknownType)
             m_extensionFlags = 0xffffffff;
-            m_typeId = -1;
-        }
-        if (m_typeId ==  QMetaType::Void) {
+        else if (m_typeId == QMetaType::Void)
             m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
-        }
     }
 }
 
index beb7294..0f069dc 100644 (file)
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
 
 // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
 #define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
-    F(Void, 0, void) \
+    F(Void, 43, void) \
     F(Bool, 1, bool) \
     F(Int, 2, int) \
     F(UInt, 3, uint) \
@@ -192,8 +192,8 @@ public:
         // these are merged with QVariant
         QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
 
-        FirstCoreType = Void,
-        LastCoreType = QModelIndex,
+        FirstCoreType = Bool,
+        LastCoreType = Void,
         FirstGuiType = QFont,
         LastGuiType = QPolygonF,
         FirstWidgetsType = QIcon,
@@ -202,6 +202,7 @@ public:
 
         QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
 
+        UnknownType = 0,
         User = 256
     };
 
@@ -627,7 +628,7 @@ inline QMetaType::~QMetaType()
 
 inline bool QMetaType::isValid() const
 {
-    return m_typeId >= 0;
+    return m_typeId != UnknownType;
 }
 
 inline bool QMetaType::isRegistered() const
index e9c15ea..ffd188c 100644 (file)
@@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE
 
 class QMetaTypeSwitcher {
 public:
-    class NotBuiltinType;
+    class NotBuiltinType;   // type is not a built-in type, but it may be a custom type or an unknown type
+    class UnknownType;      // type not known to QMetaType system
     template<class ReturnType, class DelegateObject>
     static ReturnType switcher(DelegateObject &logic, int type, const void *data);
 };
@@ -74,7 +75,11 @@ ReturnType QMetaTypeSwitcher::switcher(DelegateObject &logic, int type, const vo
     switch (QMetaType::Type(type)) {
     QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_SWICHER_CASE)
 
+    case QMetaType::UnknownType:
+        return logic.delegate(static_cast<UnknownType const *>(data));
     default:
+        if (type < QMetaType::User)
+            return logic.delegate(static_cast<UnknownType const *>(data));
         return logic.delegate(static_cast<NotBuiltinType const *>(data));
     }
 }
index 1c18883..ae51764 100644 (file)
@@ -1697,7 +1697,7 @@ void QVariant::load(QDataStream &s)
         QByteArray name;
         s >> name;
         typeId = QMetaType::type(name);
-        if (!typeId) {
+        if (typeId == QMetaType::UnknownType) {
             s.setStatus(QDataStream::ReadCorruptData);
             return;
         }
index 5da482d..4d4b2d5 100644 (file)
@@ -126,7 +126,7 @@ class Q_CORE_EXPORT QVariant
 {
  public:
     enum Type {
-        Invalid = QMetaType::Void,
+        Invalid = QMetaType::UnknownType,
         Bool = QMetaType::Bool,
         Int = QMetaType::Int,
         UInt = QMetaType::UInt,
index a754bc4..b28aaf3 100644 (file)
@@ -187,7 +187,11 @@ public:
         return FilteredComparator<T>::compare(m_a, m_b);
     }
 
-    bool delegate(const void*) { return true; }
+    bool delegate(const void*) { Q_ASSERT(false); return true; }
+    bool delegate(const QMetaTypeSwitcher::UnknownType*)
+    {
+        return true; // for historical reason invalid variant == invalid variant
+    }
     bool delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return false; }
 protected:
     const QVariant::Private *m_a;
@@ -281,7 +285,8 @@ public:
         return CallIsNull<T>::isNull(m_d);
     }
     // we need that as sizof(void) is undefined and it is needed in HasIsNullMethod
-    bool delegate(const void *) { return m_d->is_null; }
+    bool delegate(const void *) { Q_ASSERT(false); return m_d->is_null; }
+    bool delegate(const QMetaTypeSwitcher::UnknownType *) { return m_d->is_null; }
     bool delegate(const QMetaTypeSwitcher::NotBuiltinType *) { return m_d->is_null; }
 protected:
     const QVariant::Private *m_d;
@@ -354,8 +359,18 @@ public:
 
     void delegate(const void*)
     {
-        // QMetaType::Void == QVariant::Invalid, creating an invalid value creates invalid QVariant
-        // TODO it might go away, check is needed
+        qWarning("Trying to create a QVariant instance of QMetaType::Void type, an invalid QVariant will be constructed instead");
+        m_x->type = QMetaType::UnknownType;
+        m_x->is_shared = false;
+        m_x->is_null = !m_copy;
+    }
+
+    void delegate(const QMetaTypeSwitcher::UnknownType*)
+    {
+        if (m_x->type != QMetaType::UnknownType) {
+            qWarning("Trying to construct an instance of an invalid type, type id: %i", m_x->type);
+            m_x->type = QMetaType::UnknownType;
+        }
         m_x->is_shared = false;
         m_x->is_null = !m_copy;
     }
@@ -401,7 +416,8 @@ public:
         qWarning("Trying to destruct an instance of an invalid type, type id: %i", m_d->type);
     }
     // Ignore nonconstructible type
-    void delegate(const void*) {}
+    void delegate(const QMetaTypeSwitcher::UnknownType*) {}
+    void delegate(const void*) { Q_ASSERT(false); }
 private:
     QVariant::Private *m_d;
 };
@@ -446,10 +462,11 @@ public:
     {
         qWarning("Trying to stream an instance of an invalid type, type id: %i", m_d->type);
     }
-    void delegate(const void*)
+    void delegate(const QMetaTypeSwitcher::UnknownType*)
     {
         m_debugStream.nospace() << "QVariant::Invalid";
     }
+    void delegate(const void*) { Q_ASSERT(false); }
 private:
     QDebug m_debugStream;
     QVariant::Private *m_d;
index f863650..8d46ee4 100644 (file)
@@ -686,7 +686,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
             ++i;
 
         // make sure that the output parameters have signatures too
-        if (returnType != 0 && QDBusMetaType::typeToSignature(returnType) == 0)
+        if (returnType != QMetaType::UnknownType && returnType != QMetaType::Void && QDBusMetaType::typeToSignature(returnType) == 0)
             continue;
 
         bool ok = true;
@@ -919,7 +919,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
     // output arguments
     QVariantList outputArgs;
     void *null = 0;
-    if (metaTypes[0] != QMetaType::Void) {
+    if (metaTypes[0] != QMetaType::Void && metaTypes[0] != QMetaType::UnknownType) {
         QVariant arg(metaTypes[0], null);
         outputArgs.append( arg );
         params[0] = const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData());
index 7b8a67f..ce8146f 100644 (file)
@@ -71,7 +71,6 @@ public:
 private:
     struct Method {
         QList<QByteArray> parameterNames;
-        QByteArray typeName;
         QByteArray tag;
         QByteArray name;
         QVarLengthArray<int, 4> inputTypes;
@@ -266,10 +265,7 @@ void QDBusMetaObjectGenerator::parseMethods()
 
             mm.outputTypes.append(type.id);
 
-            if (i == 0) {
-                // return value
-                mm.typeName = type.name;
-            } else {
+            if (i != 0) {
                 // non-const ref parameter
                 mm.parameterNames.append(arg.name.toLatin1());
 
@@ -477,7 +473,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
                     typeName = QMetaType::typeName(type);
                     typeName.append('&');
                 }
-                Q_ASSERT(type || (i < 0));
+                Q_ASSERT(type != QMetaType::UnknownType);
                 int typeInfo;
                 if (!typeName.isEmpty())
                     typeInfo = IsUnresolvedType | strings.enter(typeName);
@@ -516,7 +512,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
 
         // form is name, typeinfo, flags
         idata[offset++] = strings.enter(it.key()); // name
-        Q_ASSERT(mp.type != 0);
+        Q_ASSERT(mp.type != QMetaType::UnknownType);
         idata[offset++] = mp.type;
         idata[offset++] = mp.flags;
 
index b0d6406..7c8d8cf 100644 (file)
@@ -311,7 +311,7 @@ bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
 int QDBusMetaType::signatureToType(const char *signature)
 {
     if (!signature)
-        return QVariant::Invalid;
+        return QMetaType::UnknownType;
 
     QDBusMetaTypeId::init();
     switch (signature[0])
@@ -378,7 +378,7 @@ int QDBusMetaType::signatureToType(const char *signature)
         }
         // fall through
     default:
-        return QVariant::Invalid;
+        return QMetaType::UnknownType;
     }
 }
 
index 0a5da60..88bab88 100644 (file)
@@ -170,7 +170,7 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
         }
 
         int id = QMetaType::type(type);
-        if (id == 0) {
+        if (id == QMetaType::UnknownType) {
             //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
             // invalid type in method parameter list
             return -1;
index e15add0..c7b9f31 100644 (file)
@@ -112,7 +112,8 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv
 
             quintptr addr = quintptr(*reinterpret_cast<void **>(argv[i + 1]));
             str.append(QByteArray::number(addr, 16));
-        } else if (typeId != QMetaType::Void) {
+        } else if (typeId != QMetaType::UnknownType) {
+            Q_ASSERT(typeId != QMetaType::Void); // void parameter => metaobject is corrupt
             str.append(arg)
                 .append('(')
                 .append(QVariant(typeId, argv[i + 1]).toString().toLocal8Bit())
index eb52ebf..70944ba 100644 (file)
@@ -122,9 +122,11 @@ private:
         QList<QByteArray> params = member.parameterTypes();
         for (int i = 0; i < params.count(); ++i) {
             int tp = QMetaType::type(params.at(i).constData());
-            if (tp == QMetaType::Void)
+            if (tp == QMetaType::UnknownType) {
+                Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
                 qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
                          params.at(i).constData());
+            }
             args << tp;
         }
     }
index 73a0605..1284518 100644 (file)
@@ -60,7 +60,7 @@ uint nameToBuiltinType(const QByteArray &name)
         return 0;
 
     uint tp = QMetaType::type(name.constData());
-    return tp < QMetaType::User ? tp : 0;
+    return tp < uint(QMetaType::User) ? tp : QMetaType::UnknownType;
 }
 
 /*
@@ -69,7 +69,7 @@ uint nameToBuiltinType(const QByteArray &name)
 bool isBuiltinType(const QByteArray &type)
  {
     int id = QMetaType::type(type.constData());
-    if (!id && !type.isEmpty() && type != "void")
+    if (id == QMetaType::UnknownType)
         return false;
     return (id < QMetaType::User);
 }
@@ -632,7 +632,7 @@ void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const
                 else
                     fprintf(out, "%4d", type);
             } else {
-                Q_ASSERT(!typeName.isEmpty());
+                Q_ASSERT(!typeName.isEmpty() || f.isConstructor);
                 fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(typeName));
             }
             fputc(',', out);
@@ -1097,8 +1097,9 @@ void Generator::generateStaticMetacall()
         fprintf(out, "        switch (_id) {\n");
         for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
             const FunctionDef &f = methodList.at(methodindex);
+            Q_ASSERT(!f.normalizedType.isEmpty());
             fprintf(out, "        case %d: ", methodindex);
-            if (f.normalizedType.size())
+            if (f.normalizedType != "void")
                 fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData());
             fprintf(out, "_t->");
             if (f.inPrivateClass.size())
@@ -1113,7 +1114,7 @@ void Generator::generateStaticMetacall()
                 isUsed_a = true;
             }
             fprintf(out, ");");
-            if (f.normalizedType.size()) {
+            if (f.normalizedType != "void") {
                 fprintf(out, "\n            if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
                         noRef(f.normalizedType).constData());
                 isUsed_a = true;
@@ -1192,7 +1193,8 @@ void Generator::generateSignal(FunctionDef *def,int index)
         constQualifier = "const";
     }
 
-    if (def->arguments.isEmpty() && def->normalizedType.isEmpty()) {
+    Q_ASSERT(!def->normalizedType.isEmpty());
+    if (def->arguments.isEmpty() && def->normalizedType == "void") {
         fprintf(out, ")%s\n{\n"
                 "    QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n"
                 "}\n", constQualifier, thisPtr.constData(), index);
@@ -1207,11 +1209,11 @@ void Generator::generateSignal(FunctionDef *def,int index)
         fprintf(out, "%s _t%d%s", a.type.name.constData(), offset++, a.rightType.constData());
     }
     fprintf(out, ")%s\n{\n", constQualifier);
-    if (def->type.name.size() && def->normalizedType.size())
+    if (def->type.name.size() && def->normalizedType != "void")
         fprintf(out, "    %s _t0 = %s();\n", noRef(def->normalizedType).constData(), noRef(def->normalizedType).constData());
 
     fprintf(out, "    void *_a[] = { ");
-    if (def->normalizedType.isEmpty()) {
+    if (def->normalizedType == "void") {
         fprintf(out, "0");
     } else {
         if (def->returnTypeIsVolatile)
@@ -1227,7 +1229,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
             fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i);
     fprintf(out, " };\n");
     fprintf(out, "    QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index);
-    if (def->normalizedType.size())
+    if (def->normalizedType != "void")
         fprintf(out, "    return _t0;\n");
     fprintf(out, "}\n");
 }
index 49fc295..467f85c 100644 (file)
@@ -75,9 +75,7 @@ static QByteArray normalizeType(const QByteArray &ba, bool fixScope = false)
         }
     }
     *d = '\0';
-    QByteArray result;
-    if (strncmp("void", buf, d - buf) != 0)
-        result = normalizeTypeInternal(buf, d, fixScope);
+    QByteArray result = normalizeTypeInternal(buf, d, fixScope);
     if (buf != stackbuf)
         delete [] buf;
     return result;
index 60c8fdb..f44a671 100644 (file)
@@ -223,7 +223,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject()")
             << QByteArray("MethodTestObject()")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>())
             << (QList<QByteArray>())
             << (QList<QByteArray>())
@@ -259,7 +259,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject(int)")
             << QByteArray("MethodTestObject(int)")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>() << int(QMetaType::Int))
             << (QList<QByteArray>() << QByteArray("int"))
             << (QList<QByteArray>() << QByteArray("constructorIntArg"))
@@ -295,7 +295,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject(qreal)")
             << QByteArray("MethodTestObject(qreal)")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>() << qMetaTypeId<qreal>())
             << (QList<QByteArray>() << QByteArray("qreal"))
             << (QList<QByteArray>() << QByteArray("constructorQRealArg"))
@@ -331,7 +331,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject(QString)")
             << QByteArray("MethodTestObject(QString)")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>() << int(QMetaType::QString))
             << (QList<QByteArray>() << QByteArray("QString"))
             << (QList<QByteArray>() << QByteArray("constructorQStringArg"))
@@ -367,7 +367,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject(CustomType)")
             << QByteArray("MethodTestObject(CustomType)")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>() << qMetaTypeId<CustomType>())
             << (QList<QByteArray>() << QByteArray("CustomType"))
             << (QList<QByteArray>() << QByteArray("constructorCustomTypeArg"))
@@ -403,7 +403,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject(CustomUnregisteredType)")
             << QByteArray("MethodTestObject(CustomUnregisteredType)")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>() << 0)
             << (QList<QByteArray>() << QByteArray("CustomUnregisteredType"))
             << (QList<QByteArray>() << QByteArray("constructorCustomUnregisteredTypeArg"))
@@ -536,7 +536,7 @@ void tst_QMetaMethod::method_data()
 
         QTest::newRow("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)")
                 << QByteArray("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)")
-                << int(QMetaType::Void) << QByteArray("")
+                << int(QMetaType::UnknownType) << QByteArray("")
                 << parameterTypes << parameterTypeNames << parameterNames
                 << QMetaMethod::Public
                 << QMetaMethod::Constructor;
@@ -571,7 +571,7 @@ void tst_QMetaMethod::method_data()
 
     QTest::newRow("MethodTestObject(bool,int)")
             << QByteArray("MethodTestObject(bool,int)")
-            << int(QMetaType::Void) << QByteArray("")
+            << int(QMetaType::UnknownType) << QByteArray("")
             << (QList<int>() << int(QMetaType::Bool) << int(QMetaType::Int))
             << (QList<QByteArray>() << QByteArray("bool") << QByteArray("int"))
             << (QList<QByteArray>() << QByteArray("") << QByteArray(""))
@@ -616,7 +616,6 @@ void tst_QMetaMethod::method()
     QCOMPARE(method.name(), computedName);
 
     QCOMPARE(method.tag(), "");
-
     QCOMPARE(method.returnType(), returnType);
     if (QByteArray(method.typeName()) != returnTypeName) {
         // QMetaMethod should always produce a semantically equivalent typename
index 72913d1..4f283ce 100644 (file)
@@ -315,6 +315,7 @@ void tst_QMetaType::typeName_data()
 
     QT_FOR_EACH_STATIC_TYPE(TYPENAME_DATA)
     QT_FOR_EACH_STATIC_ALIAS_TYPE(TYPENAME_DATA_ALIAS)
+    QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << static_cast<const char*>(0);
 }
 
 void tst_QMetaType::typeName()
@@ -625,6 +626,8 @@ void tst_QMetaType::sizeOf_data()
 {
     QTest::addColumn<QMetaType::Type>("type");
     QTest::addColumn<int>("size");
+
+    QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << 0;
 #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
     QTest::newRow(#RealType) << QMetaType::MetaTypeName << int(QTypeInfo<RealType>::sizeOf);
 FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW)
@@ -984,6 +987,7 @@ void tst_QMetaType::isRegistered_data()
     QTest::newRow("-1") << -1 << false;
     QTest::newRow("-42") << -42 << false;
     QTest::newRow("IsRegisteredDummyType + 1") << (dummyTypeId + 1) << false;
+    QTest::newRow("QMetaType::UnknownType") << int(QMetaType::UnknownType) << false;
 }
 
 void tst_QMetaType::isRegistered()
index ccdab17..ffe1d2b 100644 (file)
@@ -3542,6 +3542,10 @@ void tst_QVariant::loadQVariantFromDataStream(QDataStream::Version version)
     stream >> typeName >> loadedVariant;
 
     const int id = QMetaType::type(typeName.toLatin1());
+    if (id == QMetaType::Void) {
+        // Void type is not supported by QVariant
+        return;
+    }
 
     QVariant constructedVariant(static_cast<QVariant::Type>(id));
     QCOMPARE(constructedVariant.userType(), id);
@@ -3561,6 +3565,10 @@ void tst_QVariant::saveQVariantFromDataStream(QDataStream::Version version)
     dataFileStream >> typeName;
     QByteArray data = file.readAll();
     const int id = QMetaType::type(typeName.toLatin1());
+    if (id == QMetaType::Void) {
+        // Void type is not supported by QVariant
+        return;
+    }
 
     QBuffer buffer;
     buffer.open(QIODevice::ReadWrite);
@@ -3621,7 +3629,9 @@ void tst_QVariant::debugStream_data()
         const char *tagName = QMetaType::typeName(id);
         if (!tagName)
             continue;
-        QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
+        if (id != QMetaType::Void) {
+            QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
+        }
     }
     QTest::newRow("QBitArray(111)") << QVariant(QBitArray(3, true)) << qMetaTypeId<QBitArray>();
     QTest::newRow("CustomStreamableClass") << QVariant(qMetaTypeId<CustomStreamableClass>(), 0) << qMetaTypeId<CustomStreamableClass>();