From ac9be327f8dc788a964b77c6bcdf0391c85c9cbd Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 20 Sep 2012 15:06:11 +0200 Subject: QFlags: use unsigned int when the enum's underlying is unsigned Replace storage and operator int() return types with unsigned int if the enum is unsigned. This fixes a number of exisiting warnings, in particular with Qt::MouseButton under GCC. Change-Id: Ia12d36212329aec3e9d62a5fbd38809a6c2b36d0 Reviewed-by: Thiago Macieira --- dist/changes-5.0.0 | 5 +++++ src/corelib/global/qflags.h | 16 +++++++++++++--- src/corelib/global/qglobal.cpp | 13 ++++++++++++- tests/auto/corelib/global/qflags/tst_qflags.cpp | 18 ++++++++++++++++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index b5f63c3600..795cb88935 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -62,6 +62,11 @@ information about a particular change. - qIsDetached<> has been removed without replacement. +- The return type of QFlags::operator int() now matches the Enum's underlying + type in signedness instead of always being 'int'. This was done in order to allow + QFlags over enums whose underlying type is unsigned (Qt::MouseButton is one such + enum). + - QMetaType: * QMetaType::construct() has been renamed to QMetaType::create(). * QMetaType::unregisterType() has been removed. diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index faacf7321c..3edbef3bd6 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -82,11 +83,18 @@ class QFlags "long long would overflow. Qt 5.1 will have support for 64bit enums."); struct Private; typedef int (Private::*Zero); - int i; public: +#ifndef qdoc + typedef typename QtPrivate::if_< + QtPrivate::is_unsigned::value, + unsigned int, + signed int + >::type Int; +#endif typedef Enum enum_type; // compiler-generated copy/move ctor/assignment operators are fine! #ifdef qdoc + typedef int Int; // the real typedef above is too complex for qdoc inline QFlags(const QFlags &other); inline QFlags &operator=(const QFlags &other); #endif @@ -101,7 +109,7 @@ public: inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; } inline QFlags &operator^=(Enum f) { i ^= f; return *this; } - Q_DECL_CONSTEXPR inline operator int() const { return i; } + Q_DECL_CONSTEXPR inline operator Int() const { return i; } Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); } @@ -114,7 +122,9 @@ public: Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } - Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); } + Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == Int(f) ); } +private: + Int i; }; #define Q_DECLARE_FLAGS(Flags, Enum)\ diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index ef211cfce2..805868f4c6 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -171,6 +171,15 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); \sa QFlag */ +/*! + \typedef QFlags::Int + \since 5.0 + + Typedef for the integer type used for storage as well as for + implicit conversion. Either \c int or \c{unsigned int}, depending + on whether the enum's underlying type is signed or unsigned. +*/ + /*! \typedef QFlags::enum_type @@ -261,9 +270,11 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); */ /*! - \fn QFlags::operator int() const + \fn QFlags::operator Int() const Returns the value stored in the QFlags object as an integer. + + \sa Int */ /*! diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp index f608dd6f93..215462606b 100644 --- a/tests/auto/corelib/global/qflags/tst_qflags.cpp +++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp @@ -48,6 +48,7 @@ private slots: void testFlagZeroFlag() const; void testFlagMultiBits() const; void constExpr(); + void signedness(); }; void tst_QFlags::testFlag() const @@ -123,10 +124,23 @@ void tst_QFlags::constExpr() #endif } +void tst_QFlags::signedness() +{ + // these are all 'true' on GCC, but since the std says the + // underlying type is implementation-defined, we need to allow for + // a different signedness, so we only check that the relative + // signedness of the types matches: + Q_STATIC_ASSERT((QtPrivate::is_unsigned::value == + QtPrivate::is_unsigned::value)); + + Q_STATIC_ASSERT((QtPrivate::is_signed::value == + QtPrivate::is_signed::value)); +} + // (statically) check QTypeInfo for QFlags instantiations: enum MyEnum { Zero, One, Two, Four=4 }; -Q_DECLARE_FLAGS( MyFlags, MyEnum ); -Q_DECLARE_OPERATORS_FOR_FLAGS( MyFlags ); +Q_DECLARE_FLAGS( MyFlags, MyEnum ) +Q_DECLARE_OPERATORS_FOR_FLAGS( MyFlags ) Q_STATIC_ASSERT( !QTypeInfo::isComplex ); Q_STATIC_ASSERT( !QTypeInfo::isStatic ); -- cgit v1.2.3