From 15c13b91e66b0bd0d179f0303bb17c7793f80a07 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 7 Feb 2012 12:25:07 +1000 Subject: Add Q_IS_ENUM(), and provide as flag in QMetaType::typeFlags() Add Q_IS_ENUM() macro to determine if a given type is an enumeration. Use information from that in QMetaType::registerType() to store whether custom registered metatypes are enums or not. This information can then be accessed by calling QMetaType::typeFlags(int type). This is used by the declarative code to determine whether a custom type in a variant can be safely cast to an integer, which is required to allow passing non-local enums as signal/slot params. Change-Id: I9733837f56af201fa3017b4a22b761437a3c0de4 Reviewed-by: Lars Knoll --- src/corelib/global/global.pri | 4 +- src/corelib/global/qisenum.h | 64 ++++ src/corelib/global/qtypetraits.h | 420 +++++++++++++++++++++ src/corelib/kernel/qmetatype.h | 6 +- tests/auto/corelib/global/qglobal/tst_qglobal.cpp | 122 ++++++ .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 34 ++ 6 files changed, 648 insertions(+), 2 deletions(-) create mode 100644 src/corelib/global/qisenum.h create mode 100644 src/corelib/global/qtypetraits.h diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 49128374e0..58cff6b81c 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -11,7 +11,9 @@ HEADERS += \ global/qnumeric.h \ global/qlogging.h \ global/qtypeinfo.h \ - global/qsysinfo.h + global/qsysinfo.h \ + global/qisenum.h \ + global/qtypetraits.h SOURCES += \ global/qglobal.cpp \ diff --git a/src/corelib/global/qisenum.h b/src/corelib/global/qisenum.h new file mode 100644 index 0000000000..c9b6ec6695 --- /dev/null +++ b/src/corelib/global/qisenum.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QISENUM_H +#define QISENUM_H + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef Q_IS_ENUM +# if defined(Q_CC_GNU) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +# define Q_IS_ENUM(x) __is_enum(x) +# elif defined(Q_CC_MSVC) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER >=140050215) +# define Q_IS_ENUM(x) __is_enum(x) +# else +# include +# define Q_IS_ENUM(x) QtPrivate::is_enum::value +# endif +#endif + +QT_END_HEADER +QT_END_NAMESPACE + +#endif // QISENUM_H diff --git a/src/corelib/global/qtypetraits.h b/src/corelib/global/qtypetraits.h new file mode 100644 index 0000000000..92bd949570 --- /dev/null +++ b/src/corelib/global/qtypetraits.h @@ -0,0 +1,420 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ---- +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. +// +// Define a small subset of tr1 type traits. The traits we define are: +// is_integral +// is_floating_point +// is_pointer +// is_enum +// is_reference +// is_pod +// has_trivial_constructor +// has_trivial_copy +// has_trivial_assign +// has_trivial_destructor +// remove_const +// remove_volatile +// remove_cv +// remove_reference +// add_reference +// remove_pointer +// is_same +// is_convertible +// We can add more type traits as required. + +// Changes from the original implementation: +// - Move base types from template_util.h directly into this header. +// - Use Qt macros for long long type differences on Windows. +// - Enclose in QtPrivate namespace. + +#ifndef QTYPETRAITS_H +#define QTYPETRAITS_H + +#include // For pair +#include "QtCore/qglobal.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QtPrivate { + +// Types small_ and big_ are guaranteed such that sizeof(small_) < +// sizeof(big_) +typedef char small_; + +struct big_ { + char dummy[2]; +}; + +// Identity metafunction. +template +struct identity_ { + typedef T type; +}; + +// integral_constant, defined in tr1, is a wrapper for an integer +// value. We don't really need this generality; we could get away +// with hardcoding the integer type to bool. We use the fully +// general integer_constant for compatibility with tr1. + +template +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + + +// Abbreviations: true_type and false_type are structs that represent boolean +// true and false values. Also define the boost::mpl versions of those names, +// true_ and false_. +typedef integral_constant true_type; +typedef integral_constant false_type; +typedef true_type true_; +typedef false_type false_; + +// if_ is a templatized conditional statement. +// if_ is a compile time evaluation of cond. +// if_<>::type contains A if cond is true, B otherwise. +template +struct if_{ + typedef A type; +}; + +template +struct if_ { + typedef B type; +}; + + +// type_equals_ is a template type comparator, similar to Loki IsSameType. +// type_equals_::value is true iff "A" is the same type as "B". +// +// New code should prefer base::is_same, defined in base/type_traits.h. +// It is functionally identical, but is_same is the standard spelling. +template +struct type_equals_ : public false_ { +}; + +template +struct type_equals_ : public true_ { +}; + +// and_ is a template && operator. +// and_::value evaluates "A::value && B::value". +template +struct and_ : public integral_constant { +}; + +// or_ is a template || operator. +// or_::value evaluates "A::value || B::value". +template +struct or_ : public integral_constant { +}; + +template struct is_integral; +template struct is_floating_point; +template struct is_pointer; +// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least) +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +// is_enum uses is_convertible, which is not available on MSVC. +template struct is_enum; +#endif +template struct is_reference; +template struct is_pod; +template struct has_trivial_constructor; +template struct has_trivial_copy; +template struct has_trivial_assign; +template struct has_trivial_destructor; +template struct remove_const; +template struct remove_volatile; +template struct remove_cv; +template struct remove_reference; +template struct add_reference; +template struct remove_pointer; +template struct is_same; +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +template struct is_convertible; +#endif + +// is_integral is false except for the built-in integer types. A +// cv-qualified type is integral if and only if the underlying type is. +template struct is_integral : false_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#if defined(_MSC_VER) +// wchar_t is not by default a distinct type from unsigned short in +// Microsoft C. +// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx +template<> struct is_integral<__wchar_t> : true_type { }; +#else +template<> struct is_integral : true_type { }; +#endif +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#if defined(Q_OS_WIN) && !defined(Q_CC_GNU) +template<> struct is_integral<__int64> : true_type { }; +template<> struct is_integral : true_type { }; +#else +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#endif +template struct is_integral : is_integral { }; +template struct is_integral : is_integral { }; +template struct is_integral : is_integral { }; + +// is_floating_point is false except for the built-in floating-point types. +// A cv-qualified type is integral if and only if the underlying type is. +template struct is_floating_point : false_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template struct is_floating_point + : is_floating_point { }; +template struct is_floating_point + : is_floating_point { }; +template struct is_floating_point + : is_floating_point { }; + +// is_pointer is false except for pointer types. A cv-qualified type (e.g. +// "int* const", as opposed to "int const*") is cv-qualified if and only if +// the underlying type is. +template struct is_pointer : false_type { }; +template struct is_pointer : true_type { }; +template struct is_pointer : is_pointer { }; +template struct is_pointer : is_pointer { }; +template struct is_pointer : is_pointer { }; + +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + +namespace internal { + +template struct is_class_or_union { + template static small_ tester(void (U::*)()); + template static big_ tester(...); + static const bool value = sizeof(tester(0)) == sizeof(small_); +}; + +// is_convertible chokes if the first argument is an array. That's why +// we use add_reference here. +template struct is_enum_impl + : is_convertible::type, int> { }; + +template struct is_enum_impl : false_type { }; + +} // namespace internal + +// Specified by TR1 [4.5.1] primary type categories. + +// Implementation note: +// +// Each type is either void, integral, floating point, array, pointer, +// reference, member object pointer, member function pointer, enum, +// union or class. Out of these, only integral, floating point, reference, +// class and enum types are potentially convertible to int. Therefore, +// if a type is not a reference, integral, floating point or class and +// is convertible to int, it's a enum. Adding cv-qualification to a type +// does not change whether it's an enum. +// +// Is-convertible-to-int check is done only if all other checks pass, +// because it can't be used with some types (e.g. void or classes with +// inaccessible conversion operators). +template struct is_enum + : internal::is_enum_impl< + is_same::value || + is_integral::value || + is_floating_point::value || + is_reference::value || + internal::is_class_or_union::value, + T> { }; + +template struct is_enum : is_enum { }; +template struct is_enum : is_enum { }; +template struct is_enum : is_enum { }; + +#endif + +// is_reference is false except for reference types. +template struct is_reference : false_type {}; +template struct is_reference : true_type {}; + + +// We can't get is_pod right without compiler help, so fail conservatively. +// We will assume it's false except for arithmetic types, enumerations, +// pointers and cv-qualified versions thereof. Note that std::pair +// is not a POD even if T and U are PODs. +template struct is_pod + : integral_constant::value || + is_floating_point::value || +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + // is_enum is not available on MSVC. + is_enum::value || +#endif + is_pointer::value)> { }; +template struct is_pod : is_pod { }; +template struct is_pod : is_pod { }; +template struct is_pod : is_pod { }; + + +// We can't get has_trivial_constructor right without compiler help, so +// fail conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial +// constructors. (3) array of a type with a trivial constructor. +// (4) const versions thereof. +template struct has_trivial_constructor : is_pod { }; +template struct has_trivial_constructor > + : integral_constant::value && + has_trivial_constructor::value)> { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; + +// We can't get has_trivial_copy right without compiler help, so fail +// conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial copy +// constructors. (3) array of a type with a trivial copy constructor. +// (4) const versions thereof. +template struct has_trivial_copy : is_pod { }; +template struct has_trivial_copy > + : integral_constant::value && + has_trivial_copy::value)> { }; +template struct has_trivial_copy + : has_trivial_copy { }; +template struct has_trivial_copy : has_trivial_copy { }; + +// We can't get has_trivial_assign right without compiler help, so fail +// conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial copy +// constructors. (3) array of a type with a trivial assign constructor. +template struct has_trivial_assign : is_pod { }; +template struct has_trivial_assign > + : integral_constant::value && + has_trivial_assign::value)> { }; +template struct has_trivial_assign + : has_trivial_assign { }; + +// We can't get has_trivial_destructor right without compiler help, so +// fail conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial +// destructors. (3) array of a type with a trivial destructor. +// (4) const versions thereof. +template struct has_trivial_destructor : is_pod { }; +template struct has_trivial_destructor > + : integral_constant::value && + has_trivial_destructor::value)> { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; + +// Specified by TR1 [4.7.1] +template struct remove_const { typedef T type; }; +template struct remove_const { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_cv { + typedef typename remove_const::type>::type type; +}; + + +// Specified by TR1 [4.7.2] Reference modifications. +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template struct add_reference { typedef T& type; }; +template struct add_reference { typedef T& type; }; + +// Specified by TR1 [4.7.4] Pointer modifications. +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { + typedef T type; }; + +// Specified by TR1 [4.6] Relationships between types +template struct is_same : public false_type { }; +template struct is_same : public true_type { }; + +// Specified by TR1 [4.6] Relationships between types +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +namespace internal { + +// This class is an implementation detail for is_convertible, and you +// don't need to know how it works to use is_convertible. For those +// who care: we declare two different functions, one whose argument is +// of type To and one with a variadic argument list. We give them +// return types of different size, so we can use sizeof to trick the +// compiler into telling us which function it would have chosen if we +// had called it with an argument of type From. See Alexandrescu's +// _Modern C++ Design_ for more details on this sort of trick. + +template +struct ConvertHelper { + static small_ Test(To); + static big_ Test(...); + static From Create(); +}; +} // namespace internal + +// Inherits from true_type if From is convertible to To, false_type otherwise. +template +struct is_convertible + : integral_constant::Test( + internal::ConvertHelper::Create())) + == sizeof(small_)> { +}; +#endif + +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QTYPETRAITS_H diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index eacb8403dc..0010c27beb 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -209,7 +210,8 @@ public: NeedsConstruction = 0x1, NeedsDestruction = 0x2, MovableType = 0x4, - PointerToQObject = 0x8 + PointerToQObject = 0x8, + IsEnumeration = 0x10 }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) @@ -455,6 +457,8 @@ int qRegisterMetaType(const char *typeName } if (QtPrivate::IsPointerToTypeDerivedFromQObject::Value) flags |= QMetaType::PointerToQObject; + if (Q_IS_ENUM(T)) + flags |= QMetaType::IsEnumeration; return QMetaType::registerType(typeName, qMetaTypeDeleteHelper, qMetaTypeCreateHelper, diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 8fedaf427a..b3d76bef8a 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -41,10 +41,12 @@ #include +#include class tst_QGlobal: public QObject { Q_OBJECT + private slots: void qIsNull(); void for_each(); @@ -53,6 +55,7 @@ private slots: void checkptr(); void qstaticassert(); void qConstructorFunction(); + void isEnum(); }; void tst_QGlobal::qIsNull() @@ -293,5 +296,124 @@ void tst_QGlobal::qConstructorFunction() QCOMPARE(qConstructorFunctionValue, 123); } +struct isEnum_A { + int n_; +}; + +enum isEnum_B_Byte { isEnum_B_Byte_x = 63 }; +enum isEnum_B_Short { isEnum_B_Short_x = 1024 }; +enum isEnum_B_Int { isEnum_B_Int_x = 1 << 20 }; + +union isEnum_C {}; + +class isEnum_D { +public: + operator int() const; +}; + +class isEnum_E { +private: + operator int() const; +}; + +class isEnum_F { +public: + enum AnEnum {}; +}; + +#if defined (Q_COMPILER_CLASS_ENUM) +enum class isEnum_G : qint64 {}; +#endif + +void tst_QGlobal::isEnum() +{ +#if defined (Q_CC_MSVC) +#define IS_ENUM_TRUE(x) (Q_IS_ENUM(x) == true) +#define IS_ENUM_FALSE(x) (Q_IS_ENUM(x) == false) +#else +#define IS_ENUM_TRUE(x) (Q_IS_ENUM(x) == true && QtPrivate::is_enum::value == true) +#define IS_ENUM_FALSE(x) (Q_IS_ENUM(x) == false && QtPrivate::is_enum::value == false) +#endif + + QVERIFY(IS_ENUM_TRUE(isEnum_B_Byte)); + QVERIFY(IS_ENUM_TRUE(const isEnum_B_Byte)); + QVERIFY(IS_ENUM_TRUE(volatile isEnum_B_Byte)); + QVERIFY(IS_ENUM_TRUE(const volatile isEnum_B_Byte)); + + QVERIFY(IS_ENUM_TRUE(isEnum_B_Short)); + QVERIFY(IS_ENUM_TRUE(const isEnum_B_Short)); + QVERIFY(IS_ENUM_TRUE(volatile isEnum_B_Short)); + QVERIFY(IS_ENUM_TRUE(const volatile isEnum_B_Short)); + + QVERIFY(IS_ENUM_TRUE(isEnum_B_Int)); + QVERIFY(IS_ENUM_TRUE(const isEnum_B_Int)); + QVERIFY(IS_ENUM_TRUE(volatile isEnum_B_Int)); + QVERIFY(IS_ENUM_TRUE(const volatile isEnum_B_Int)); + + QVERIFY(IS_ENUM_TRUE(isEnum_F::AnEnum)); + QVERIFY(IS_ENUM_TRUE(const isEnum_F::AnEnum)); + QVERIFY(IS_ENUM_TRUE(volatile isEnum_F::AnEnum)); + QVERIFY(IS_ENUM_TRUE(const volatile isEnum_F::AnEnum)); + + QVERIFY(IS_ENUM_FALSE(void)); + QVERIFY(IS_ENUM_FALSE(isEnum_B_Byte &)); + QVERIFY(IS_ENUM_FALSE(isEnum_B_Byte[1])); + QVERIFY(IS_ENUM_FALSE(const isEnum_B_Byte[1])); + QVERIFY(IS_ENUM_FALSE(isEnum_B_Byte[])); + QVERIFY(IS_ENUM_FALSE(int)); + QVERIFY(IS_ENUM_FALSE(float)); + QVERIFY(IS_ENUM_FALSE(isEnum_A)); + QVERIFY(IS_ENUM_FALSE(isEnum_A *)); + QVERIFY(IS_ENUM_FALSE(const isEnum_A)); + QVERIFY(IS_ENUM_FALSE(isEnum_C)); + QVERIFY(IS_ENUM_FALSE(isEnum_D)); + QVERIFY(IS_ENUM_FALSE(isEnum_E)); + QVERIFY(IS_ENUM_FALSE(void())); + QVERIFY(IS_ENUM_FALSE(void(*)())); + QVERIFY(IS_ENUM_FALSE(int isEnum_A::*)); + QVERIFY(IS_ENUM_FALSE(void (isEnum_A::*)())); + + QVERIFY(IS_ENUM_FALSE(size_t)); + QVERIFY(IS_ENUM_FALSE(bool)); + QVERIFY(IS_ENUM_FALSE(wchar_t)); + + QVERIFY(IS_ENUM_FALSE(char)); + QVERIFY(IS_ENUM_FALSE(unsigned char)); + QVERIFY(IS_ENUM_FALSE(short)); + QVERIFY(IS_ENUM_FALSE(unsigned short)); + QVERIFY(IS_ENUM_FALSE(int)); + QVERIFY(IS_ENUM_FALSE(unsigned int)); + QVERIFY(IS_ENUM_FALSE(long)); + QVERIFY(IS_ENUM_FALSE(unsigned long)); + + QVERIFY(IS_ENUM_FALSE(qint8)); + QVERIFY(IS_ENUM_FALSE(quint8)); + QVERIFY(IS_ENUM_FALSE(qint16)); + QVERIFY(IS_ENUM_FALSE(quint16)); + QVERIFY(IS_ENUM_FALSE(qint32)); + QVERIFY(IS_ENUM_FALSE(quint32)); + QVERIFY(IS_ENUM_FALSE(qint64)); + QVERIFY(IS_ENUM_FALSE(quint64)); + + QVERIFY(IS_ENUM_FALSE(void *)); + QVERIFY(IS_ENUM_FALSE(int *)); + +#if defined (Q_COMPILER_UNICODE_STRINGS) + QVERIFY(IS_ENUM_FALSE(char16_t)); + QVERIFY(IS_ENUM_FALSE(char32_t)); +#endif + +#if defined (Q_COMPILER_CLASS_ENUM) + // Strongly type class enums are not handled by the + // fallback type traits implementation. Any compiler + // supported by Qt that supports C++0x class enums + // should also support the __is_enum intrinsic. + QVERIFY(Q_IS_ENUM(isEnum_G) == true); +#endif + +#undef IS_ENUM_TRUE +#undef IS_ENUM_FALSE +} + QTEST_MAIN(tst_QGlobal) #include "tst_qglobal.moc" diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 3c21a5053f..bc5fa2716b 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -94,6 +94,7 @@ private slots: void isRegistered(); void isRegisteredStaticLess_data(); void isRegisteredStaticLess(); + void isEnum(); void registerStreamBuiltin(); void automaticTemplateRegistration(); }; @@ -1042,6 +1043,39 @@ void tst_QMetaType::isRegistered() QCOMPARE(QMetaType::isRegistered(typeId), registered); } +enum isEnumTest_Enum0 {}; +struct isEnumTest_Struct0 { enum A{}; }; + +enum isEnumTest_Enum1 {}; +struct isEnumTest_Struct1 {}; + +Q_DECLARE_METATYPE(isEnumTest_Struct1) +Q_DECLARE_METATYPE(isEnumTest_Enum1) + +void tst_QMetaType::isEnum() +{ + int type0 = qRegisterMetaType("int"); + QVERIFY((QMetaType::typeFlags(type0) & QMetaType::IsEnumeration) == 0); + + int type1 = qRegisterMetaType("isEnumTest_Enum0"); + QVERIFY((QMetaType::typeFlags(type1) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration); + + int type2 = qRegisterMetaType("isEnumTest_Struct0"); + QVERIFY((QMetaType::typeFlags(type2) & QMetaType::IsEnumeration) == 0); + + int type3 = qRegisterMetaType("isEnumTest_Enum0 *"); + QVERIFY((QMetaType::typeFlags(type3) & QMetaType::IsEnumeration) == 0); + + int type4 = qRegisterMetaType("isEnumTest_Struct0::A"); + QVERIFY((QMetaType::typeFlags(type4) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration); + + int type5 = ::qMetaTypeId(); + QVERIFY((QMetaType::typeFlags(type5) & QMetaType::IsEnumeration) == 0); + + int type6 = ::qMetaTypeId(); + QVERIFY((QMetaType::typeFlags(type6) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration); +} + void tst_QMetaType::isRegisteredStaticLess_data() { isRegistered_data(); -- cgit v1.2.3