summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/global/global.pri4
-rw-r--r--src/corelib/global/qisenum.h64
-rw-r--r--src/corelib/global/qtypetraits.h420
-rw-r--r--src/corelib/kernel/qmetatype.h6
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp122
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp34
6 files changed, 648 insertions, 2 deletions
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 <QtCore/qglobal.h>
+
+#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 <QtCore/qtypetraits.h>
+# define Q_IS_ENUM(x) QtPrivate::is_enum<x>::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 <utility> // 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 <class T>
+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<class T, T v>
+struct integral_constant {
+ static const T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::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<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+typedef true_type true_;
+typedef false_type false_;
+
+// if_ is a templatized conditional statement.
+// if_<cond, A, B> is a compile time evaluation of cond.
+// if_<>::type contains A if cond is true, B otherwise.
+template<bool cond, typename A, typename B>
+struct if_{
+ typedef A type;
+};
+
+template<typename A, typename B>
+struct if_<false, A, B> {
+ typedef B type;
+};
+
+
+// type_equals_ is a template type comparator, similar to Loki IsSameType.
+// type_equals_<A, B>::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<typename A, typename B>
+struct type_equals_ : public false_ {
+};
+
+template<typename A>
+struct type_equals_<A, A> : public true_ {
+};
+
+// and_ is a template && operator.
+// and_<A, B>::value evaluates "A::value && B::value".
+template<typename A, typename B>
+struct and_ : public integral_constant<bool, (A::value && B::value)> {
+};
+
+// or_ is a template || operator.
+// or_<A, B>::value evaluates "A::value || B::value".
+template<typename A, typename B>
+struct or_ : public integral_constant<bool, (A::value || B::value)> {
+};
+
+template <class T> struct is_integral;
+template <class T> struct is_floating_point;
+template <class T> 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 <class T> struct is_enum;
+#endif
+template <class T> struct is_reference;
+template <class T> struct is_pod;
+template <class T> struct has_trivial_constructor;
+template <class T> struct has_trivial_copy;
+template <class T> struct has_trivial_assign;
+template <class T> struct has_trivial_destructor;
+template <class T> struct remove_const;
+template <class T> struct remove_volatile;
+template <class T> struct remove_cv;
+template <class T> struct remove_reference;
+template <class T> struct add_reference;
+template <class T> struct remove_pointer;
+template <class T, class U> struct is_same;
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+template <class From, class To> 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 <class T> struct is_integral : false_type { };
+template<> struct is_integral<bool> : true_type { };
+template<> struct is_integral<char> : true_type { };
+template<> struct is_integral<unsigned char> : true_type { };
+template<> struct is_integral<signed char> : 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<wchar_t> : true_type { };
+#endif
+template<> struct is_integral<short> : true_type { };
+template<> struct is_integral<unsigned short> : true_type { };
+template<> struct is_integral<int> : true_type { };
+template<> struct is_integral<unsigned int> : true_type { };
+template<> struct is_integral<long> : true_type { };
+template<> struct is_integral<unsigned long> : true_type { };
+#if defined(Q_OS_WIN) && !defined(Q_CC_GNU)
+template<> struct is_integral<__int64> : true_type { };
+template<> struct is_integral<unsigned __int64> : true_type { };
+#else
+template<> struct is_integral<long long> : true_type { };
+template<> struct is_integral<unsigned long long> : true_type { };
+#endif
+template <class T> struct is_integral<const T> : is_integral<T> { };
+template <class T> struct is_integral<volatile T> : is_integral<T> { };
+template <class T> struct is_integral<const volatile T> : is_integral<T> { };
+
+// 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 <class T> struct is_floating_point : false_type { };
+template<> struct is_floating_point<float> : true_type { };
+template<> struct is_floating_point<double> : true_type { };
+template<> struct is_floating_point<long double> : true_type { };
+template <class T> struct is_floating_point<const T>
+ : is_floating_point<T> { };
+template <class T> struct is_floating_point<volatile T>
+ : is_floating_point<T> { };
+template <class T> struct is_floating_point<const volatile T>
+ : is_floating_point<T> { };
+
+// 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 <class T> struct is_pointer : false_type { };
+template <class T> struct is_pointer<T*> : true_type { };
+template <class T> struct is_pointer<const T> : is_pointer<T> { };
+template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
+template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
+
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+
+namespace internal {
+
+template <class T> struct is_class_or_union {
+ template <class U> static small_ tester(void (U::*)());
+ template <class U> static big_ tester(...);
+ static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
+};
+
+// is_convertible chokes if the first argument is an array. That's why
+// we use add_reference here.
+template <bool NotUnum, class T> struct is_enum_impl
+ : is_convertible<typename add_reference<T>::type, int> { };
+
+template <class T> struct is_enum_impl<true, T> : 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 <class T> struct is_enum
+ : internal::is_enum_impl<
+ is_same<T, void>::value ||
+ is_integral<T>::value ||
+ is_floating_point<T>::value ||
+ is_reference<T>::value ||
+ internal::is_class_or_union<T>::value,
+ T> { };
+
+template <class T> struct is_enum<const T> : is_enum<T> { };
+template <class T> struct is_enum<volatile T> : is_enum<T> { };
+template <class T> struct is_enum<const volatile T> : is_enum<T> { };
+
+#endif
+
+// is_reference is false except for reference types.
+template<typename T> struct is_reference : false_type {};
+template<typename T> struct is_reference<T&> : 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<T,U>
+// is not a POD even if T and U are PODs.
+template <class T> struct is_pod
+ : integral_constant<bool, (is_integral<T>::value ||
+ is_floating_point<T>::value ||
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+ // is_enum is not available on MSVC.
+ is_enum<T>::value ||
+#endif
+ is_pointer<T>::value)> { };
+template <class T> struct is_pod<const T> : is_pod<T> { };
+template <class T> struct is_pod<volatile T> : is_pod<T> { };
+template <class T> struct is_pod<const volatile T> : is_pod<T> { };
+
+
+// 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 <class T> struct has_trivial_constructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_constructor<T>::value &&
+ has_trivial_constructor<U>::value)> { };
+template <class A, int N> struct has_trivial_constructor<A[N]>
+ : has_trivial_constructor<A> { };
+template <class T> struct has_trivial_constructor<const T>
+ : has_trivial_constructor<T> { };
+
+// 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 <class T> struct has_trivial_copy : is_pod<T> { };
+template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_copy<T>::value &&
+ has_trivial_copy<U>::value)> { };
+template <class A, int N> struct has_trivial_copy<A[N]>
+ : has_trivial_copy<A> { };
+template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
+
+// 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 <class T> struct has_trivial_assign : is_pod<T> { };
+template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_assign<T>::value &&
+ has_trivial_assign<U>::value)> { };
+template <class A, int N> struct has_trivial_assign<A[N]>
+ : has_trivial_assign<A> { };
+
+// 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 <class T> struct has_trivial_destructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_destructor<T>::value &&
+ has_trivial_destructor<U>::value)> { };
+template <class A, int N> struct has_trivial_destructor<A[N]>
+ : has_trivial_destructor<A> { };
+template <class T> struct has_trivial_destructor<const T>
+ : has_trivial_destructor<T> { };
+
+// Specified by TR1 [4.7.1]
+template<typename T> struct remove_const { typedef T type; };
+template<typename T> struct remove_const<T const> { typedef T type; };
+template<typename T> struct remove_volatile { typedef T type; };
+template<typename T> struct remove_volatile<T volatile> { typedef T type; };
+template<typename T> struct remove_cv {
+ typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
+
+// Specified by TR1 [4.7.2] Reference modifications.
+template<typename T> struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+
+template <typename T> struct add_reference { typedef T& type; };
+template <typename T> struct add_reference<T&> { typedef T& type; };
+
+// Specified by TR1 [4.7.4] Pointer modifications.
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T*> { typedef T type; };
+template<typename T> struct remove_pointer<T* const> { typedef T type; };
+template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
+template<typename T> struct remove_pointer<T* const volatile> {
+ typedef T type; };
+
+// Specified by TR1 [4.6] Relationships between types
+template<typename T, typename U> struct is_same : public false_type { };
+template<typename T> struct is_same<T, T> : 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 <typename From, typename To>
+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 <typename From, typename To>
+struct is_convertible
+ : integral_constant<bool,
+ sizeof(internal::ConvertHelper<From, To>::Test(
+ internal::ConvertHelper<From, To>::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 <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qisenum.h>
#include <new>
@@ -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<T>::Value)
flags |= QMetaType::PointerToQObject;
+ if (Q_IS_ENUM(T))
+ flags |= QMetaType::IsEnumeration;
return QMetaType::registerType(typeName, qMetaTypeDeleteHelper<T>,
qMetaTypeCreateHelper<T>,
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 <QtTest/QtTest>
+#include <QtCore/qtypetraits.h>
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<x>::value == true)
+#define IS_ENUM_FALSE(x) (Q_IS_ENUM(x) == false && QtPrivate::is_enum<x>::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>("int");
+ QVERIFY((QMetaType::typeFlags(type0) & QMetaType::IsEnumeration) == 0);
+
+ int type1 = qRegisterMetaType<isEnumTest_Enum0>("isEnumTest_Enum0");
+ QVERIFY((QMetaType::typeFlags(type1) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration);
+
+ int type2 = qRegisterMetaType<isEnumTest_Struct0>("isEnumTest_Struct0");
+ QVERIFY((QMetaType::typeFlags(type2) & QMetaType::IsEnumeration) == 0);
+
+ int type3 = qRegisterMetaType<isEnumTest_Enum0 *>("isEnumTest_Enum0 *");
+ QVERIFY((QMetaType::typeFlags(type3) & QMetaType::IsEnumeration) == 0);
+
+ int type4 = qRegisterMetaType<isEnumTest_Struct0::A>("isEnumTest_Struct0::A");
+ QVERIFY((QMetaType::typeFlags(type4) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration);
+
+ int type5 = ::qMetaTypeId<isEnumTest_Struct1>();
+ QVERIFY((QMetaType::typeFlags(type5) & QMetaType::IsEnumeration) == 0);
+
+ int type6 = ::qMetaTypeId<isEnumTest_Enum1>();
+ QVERIFY((QMetaType::typeFlags(type6) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration);
+}
+
void tst_QMetaType::isRegisteredStaticLess_data()
{
isRegistered_data();