diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2012-07-25 09:08:33 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-12-11 11:12:08 +0100 |
commit | 98b77f9faa14822479deb20cd6fe0ce4fe9b56da (patch) | |
tree | 8f1df1dea05ec907eb7ce86dd42e574ff5b724d9 | |
parent | 90c3340356e641958528007e838eab981f090fdf (diff) |
QMetaType: remember whether a type was registered with Q_DECLARE_METATYPE
There are two ways to register a type: using Q_DECLARE_METATYPE(T) and
using qRegisterMetaType<T>("T"). Doing one thing in one translation
unit and another thing in another TU constitutes an ODR violation,
because the value of QMetaTypeId<T>::Defined will differ in the two
TUs.
By adding the information whether a type was declared with
Q_DECLARE_METATYPE to the typeFlags(), such a use will trigger
the existing binary-incompatibility failure that checks for
equality of the incoming type flags with the stored ones (if any).
I had to encode the type as a defaulted function argument in order
to avoid the linker merging instantiations of the function templates
and therefore rendering the detection moot.
Change-Id: I82017caf300458b411cc8ac2f6653536fac64117
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 17 | ||||
-rw-r--r-- | tests/manual/qmetatype/declare_metatype_noninline.cpp | 49 | ||||
-rw-r--r-- | tests/manual/qmetatype/declare_metatype_noninline.h | 52 | ||||
-rw-r--r-- | tests/manual/qmetatype/qmetatype.pro | 5 | ||||
-rw-r--r-- | tests/manual/qmetatype/tst_qmetatype.cpp | 55 |
5 files changed, 176 insertions, 2 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 06d325f383..09c641e4a3 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -252,7 +252,8 @@ public: IsEnumeration = 0x10, SharedPointerToQObject = 0x20, WeakPointerToQObject = 0x40, - TrackingPointerToQObject = 0x80 + TrackingPointerToQObject = 0x80, + WasDeclaredAsMetaType = 0x100 }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) @@ -563,12 +564,19 @@ namespace QtPrivate { | (Q_IS_ENUM(T) ? QMetaType::IsEnumeration : 0) }; }; + + template<typename T, bool defined> + struct MetaTypeDefinedHelper + { + enum DefinedType { Defined = defined }; + }; } template <typename T> int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName #ifndef qdoc , T * dummy = 0 + , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined #endif ) { @@ -580,6 +588,10 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf); QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags); + + if (defined) + flags |= QMetaType::WasDeclaredAsMetaType; + return QMetaType::registerNormalizedType(normalizedTypeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Delete, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Create, @@ -594,6 +606,7 @@ template <typename T> int qRegisterMetaType(const char *typeName #ifndef qdoc , T * dummy = 0 + , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined #endif ) { @@ -602,7 +615,7 @@ int qRegisterMetaType(const char *typeName #else QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); #endif - return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy); + return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined); } #ifndef QT_NO_DATASTREAM diff --git a/tests/manual/qmetatype/declare_metatype_noninline.cpp b/tests/manual/qmetatype/declare_metatype_noninline.cpp new file mode 100644 index 0000000000..8054daba06 --- /dev/null +++ b/tests/manual/qmetatype/declare_metatype_noninline.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "declare_metatype_noninline.h" + +Q_DECLARE_METATYPE(ToBeDeclaredMetaTypeNonInline) + +int ToBeDeclaredMetaTypeNonInline::triggerRegistration() +{ + return qMetaTypeId<ToBeDeclaredMetaTypeNonInline>(); +} diff --git a/tests/manual/qmetatype/declare_metatype_noninline.h b/tests/manual/qmetatype/declare_metatype_noninline.h new file mode 100644 index 0000000000..74244a3fcf --- /dev/null +++ b/tests/manual/qmetatype/declare_metatype_noninline.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DECLARE_METATYPE_NONINLINE_H +#define DECLARE_METATYPE_NONINLINE_H + +#include <QtCore/qmetatype.h> + +struct ToBeDeclaredMetaTypeNonInline { + static int triggerRegistration(); +}; + +#endif // DECLARE_METATYPE_NONINLINE_H + diff --git a/tests/manual/qmetatype/qmetatype.pro b/tests/manual/qmetatype/qmetatype.pro new file mode 100644 index 0000000000..a4f941e577 --- /dev/null +++ b/tests/manual/qmetatype/qmetatype.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +TARGET = tst_qmetatype_expect_fail +QT = core +HEADERS = declare_metatype_noninline.h +SOURCES = tst_qmetatype.cpp declare_metatype_noninline.cpp diff --git a/tests/manual/qmetatype/tst_qmetatype.cpp b/tests/manual/qmetatype/tst_qmetatype.cpp new file mode 100644 index 0000000000..bd17ca260c --- /dev/null +++ b/tests/manual/qmetatype/tst_qmetatype.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> + +#include "declare_metatype_noninline.h" + +int main(int argc, char **argv) +{ + qDebug("expect no warning here"); + const int id = qRegisterMetaType<ToBeDeclaredMetaTypeNonInline>("ToBeDeclaredMetaTypeNonInline"); + qDebug("expect a qfatal now"); + const int result = ToBeDeclaredMetaTypeNonInline::triggerRegistration(); + Q_ASSERT(id == result); + qDebug("if you read this, check that a qFatal was seen, " + "otherwise the test failed."); +} |