QMetaEnum: add support for reading 64-bit flags and enums
The previous commit added support for storing them in the meta object. This complements by adding support for reading the stored values. Task-number: QTBUG-111926 Fixes: QTBUG-27451 Change-Id: I8a96935cf6c742259c9dfffd17e958aa8ed66086 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
2effeb25c0
commit
d41b87e067
@ -1258,6 +1258,18 @@ bool QMetaType::isValid() const
|
||||
}
|
||||
|
||||
|
||||
#include "qmetaobject.h"
|
||||
|
||||
const char *QMetaEnum::valueToKey(int value) const
|
||||
{
|
||||
return valueToKey(quint64(uint(value)));
|
||||
}
|
||||
|
||||
QByteArray QMetaEnum::valueToKeys(int value) const
|
||||
{
|
||||
return valueToKeys(quint64(uint(value)));
|
||||
}
|
||||
|
||||
#include "quuid.h"
|
||||
|
||||
bool QUuid::isNull() const noexcept
|
||||
|
@ -3158,15 +3158,91 @@ const char *QMetaEnum::key(int index) const
|
||||
Returns the value with the given \a index; or returns -1 if there
|
||||
is no such value.
|
||||
|
||||
\sa keyCount(), key(), keyToValue()
|
||||
If this is an enumeration with a 64-bit underlying type (see is64Bit()),
|
||||
this function returns the low 32-bit portion of the value. Use value64() to
|
||||
obtain the full value instead.
|
||||
|
||||
\sa value64(), keyCount(), key(), keyToValue()
|
||||
*/
|
||||
int QMetaEnum::value(int index) const
|
||||
{
|
||||
return value64(index).value_or(-1);
|
||||
}
|
||||
|
||||
enum EnumExtendMode {
|
||||
SignExtend = -1,
|
||||
ZeroExtend,
|
||||
Use64Bit = 64
|
||||
};
|
||||
Q_DECL_PURE_FUNCTION static inline EnumExtendMode enumExtendMode(const QMetaEnum &e)
|
||||
{
|
||||
if (e.is64Bit())
|
||||
return Use64Bit;
|
||||
if (e.isFlag())
|
||||
return ZeroExtend;
|
||||
if (e.metaType().flags() & QMetaType::IsUnsignedEnumeration)
|
||||
return ZeroExtend;
|
||||
return SignExtend;
|
||||
}
|
||||
|
||||
static constexpr bool isEnumValueSuitable(quint64 value, EnumExtendMode mode)
|
||||
{
|
||||
if (mode == Use64Bit)
|
||||
return true; // any value is suitable
|
||||
|
||||
// 32-bit QMetaEnum
|
||||
if (mode == ZeroExtend)
|
||||
return value == uint(value);
|
||||
return value == quint64(int(value));
|
||||
}
|
||||
|
||||
template <typename... Mode> inline
|
||||
quint64 QMetaEnum::value_helper(uint index, Mode... modes) const noexcept
|
||||
{
|
||||
static_assert(sizeof...(Mode) < 2);
|
||||
if constexpr (sizeof...(Mode) == 0) {
|
||||
return value_helper(index, enumExtendMode(*this));
|
||||
} else if constexpr (sizeof...(Mode) == 1) {
|
||||
auto mode = (modes, ...);
|
||||
quint64 value = mobj->d.data[data.data() + 2U * index + 1];
|
||||
if (mode > 0)
|
||||
value |= quint64(mobj->d.data[data.data() + 2U * data.keyCount() + index]) << 32;
|
||||
else if (mode < 0)
|
||||
value = int(value); // sign extend to 64-bit
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.9
|
||||
|
||||
Returns the value with the given \a index if it exists; or returns a
|
||||
\c{std::nullopt} if it doesn't.
|
||||
|
||||
//! [qmetaenum-32bit-signextend-64bit]
|
||||
This function always sign-extends the value of 32-bit enumerations to 64
|
||||
bits, if their underlying type is signed (e.g., \c int, \c short). In most
|
||||
cases, this is the expected behavior.
|
||||
|
||||
A notable exception is for flag values that have bit 31 set, like
|
||||
0x8000'0000, because some compilers (such as Microsoft Visual Studio), do
|
||||
not automatically switch to an unsigned underlying type. To avoid this
|
||||
problem, explicitly specify the underlying type in the \c enum declaration.
|
||||
|
||||
\note For QMetaObjects compiled prior to Qt 6.6, this function always
|
||||
sign-extends.
|
||||
//! [qmetaenum-32bit-signextend-64bit]
|
||||
|
||||
\sa keyCount(), key(), keyToValue(), is64Bit()
|
||||
*/
|
||||
std::optional<quint64> QMetaEnum::value64(int index) const
|
||||
{
|
||||
if (!mobj)
|
||||
return 0;
|
||||
if (index >= 0 && index < int(data.keyCount()))
|
||||
return mobj->d.data[data.data() + 2 * index + 1];
|
||||
return -1;
|
||||
return std::nullopt;
|
||||
if (index < 0 || index >= int(data.keyCount()))
|
||||
return std::nullopt;
|
||||
|
||||
return value_helper(index);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3198,6 +3274,20 @@ bool QMetaEnum::isScoped() const
|
||||
return data.flags() & EnumIsScoped;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.9
|
||||
|
||||
Returns \c true if the underlying type of this enumeration is 64 bits wide.
|
||||
|
||||
\sa value64()
|
||||
*/
|
||||
bool QMetaEnum::is64Bit() const
|
||||
{
|
||||
if (!mobj)
|
||||
return false;
|
||||
return data.flags() & EnumIs64Bit;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the scope this enumerator was declared in.
|
||||
|
||||
@ -3247,25 +3337,44 @@ static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
|
||||
|
||||
For flag types, use keysToValue().
|
||||
|
||||
\sa valueToKey(), isFlag(), keysToValue()
|
||||
If this is a 64-bit enumeration (see is64Bit()), this function returns the
|
||||
low 32-bit portion of the value. Use keyToValue64() to obtain the full value
|
||||
instead.
|
||||
|
||||
\sa keyToValue64, valueToKey(), isFlag(), keysToValue(), is64Bit()
|
||||
*/
|
||||
int QMetaEnum::keyToValue(const char *key, bool *ok) const
|
||||
{
|
||||
auto value = keyToValue64(key);
|
||||
if (ok != nullptr)
|
||||
*ok = false;
|
||||
if (!mobj || !key)
|
||||
return -1;
|
||||
*ok = value.has_value();
|
||||
return int(value.value_or(-1));
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.9
|
||||
|
||||
Returns the integer value of the given enumeration \a key, or \c
|
||||
std::nullopt if \a key is not defined.
|
||||
|
||||
For flag types, use keysToValue64().
|
||||
|
||||
\include qmetaobject.cpp qmetaenum-32bit-signextend-64bit
|
||||
|
||||
\sa valueToKey(), isFlag(), keysToValue64()
|
||||
*/
|
||||
std::optional<quint64> QMetaEnum::keyToValue64(const char *key) const
|
||||
{
|
||||
if (!mobj || !key)
|
||||
return std::nullopt;
|
||||
const auto [scope, enumKey] = parse_scope(QLatin1StringView(key));
|
||||
for (int i = 0; i < int(data.keyCount()); ++i) {
|
||||
if ((!scope || isScopeMatch(*scope, this))
|
||||
&& enumKey == stringDataView(mobj, mobj->d.data[data.data() + 2 * i])) {
|
||||
if (ok != nullptr)
|
||||
*ok = true;
|
||||
return mobj->d.data[data.data() + 2 * i + 1];
|
||||
return value_helper(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3276,13 +3385,19 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
|
||||
|
||||
\sa isFlag(), valueToKeys()
|
||||
*/
|
||||
const char *QMetaEnum::valueToKey(int value) const
|
||||
const char *QMetaEnum::valueToKey(quint64 value) const
|
||||
{
|
||||
if (!mobj)
|
||||
return nullptr;
|
||||
for (int i = 0; i < int(data.keyCount()); ++i)
|
||||
if (value == (int)mobj->d.data[data.data() + 2 * i + 1])
|
||||
|
||||
EnumExtendMode mode = enumExtendMode(*this);
|
||||
if (!isEnumValueSuitable(value, mode))
|
||||
return nullptr;
|
||||
|
||||
for (int i = 0; i < int(data.keyCount()); ++i) {
|
||||
if (value == value_helper(i, mode))
|
||||
return rawStringData(mobj, mobj->d.data[data.data() + 2 * i]);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -3339,39 +3454,57 @@ static bool parseEnumFlags(QByteArrayView v, QVarLengthArray<QByteArrayView, 10>
|
||||
If \a keys is not defined, *\a{ok} is set to false; otherwise
|
||||
*\a{ok} is set to true.
|
||||
|
||||
\sa isFlag(), valueToKey(), valueToKeys()
|
||||
If this is a 64-bit enumeration (see is64Bit()), this function returns the
|
||||
low 32-bit portion of the value. Use keyToValue64() to obtain the full value
|
||||
instead.
|
||||
|
||||
\sa keysToValue64(), isFlag(), valueToKey(), valueToKeys(), is64Bit()
|
||||
*/
|
||||
int QMetaEnum::keysToValue(const char *keys, bool *ok) const
|
||||
{
|
||||
auto value = keysToValue64(keys);
|
||||
if (ok != nullptr)
|
||||
*ok = false;
|
||||
if (!mobj || !keys)
|
||||
return -1;
|
||||
*ok = value.has_value();
|
||||
return int(value.value_or(-1));
|
||||
}
|
||||
|
||||
auto lookup = [&] (QByteArrayView key) -> std::optional<int> {
|
||||
/*!
|
||||
Returns the value derived from combining together the values of the \a keys
|
||||
using the OR operator, or \c std::nullopt if \a keys is not defined. Note
|
||||
that the strings in \a keys must be '|'-separated.
|
||||
|
||||
\include qmetaobject.cpp qmetaenum-32bit-signextend-64bit
|
||||
|
||||
\sa isFlag(), valueToKey(), valueToKeys()
|
||||
*/
|
||||
std::optional<quint64> QMetaEnum::keysToValue64(const char *keys) const
|
||||
{
|
||||
if (!mobj || !keys)
|
||||
return std::nullopt;
|
||||
|
||||
EnumExtendMode mode = enumExtendMode(*this);
|
||||
auto lookup = [&] (QByteArrayView key) -> std::optional<quint64> {
|
||||
for (int i = data.keyCount() - 1; i >= 0; --i) {
|
||||
if (key == stringDataView(mobj, mobj->d.data[data.data() + 2*i]))
|
||||
return mobj->d.data[data.data() + 2*i + 1];
|
||||
return value_helper(i, mode);
|
||||
}
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
int value = 0;
|
||||
quint64 value = 0;
|
||||
QVarLengthArray<QByteArrayView, 10> list;
|
||||
const bool r = parseEnumFlags(QByteArrayView{keys}, list);
|
||||
if (!r)
|
||||
return -1;
|
||||
return std::nullopt;
|
||||
for (const auto &untrimmed : list) {
|
||||
const auto parsed = parse_scope(untrimmed.trimmed());
|
||||
if (parsed.scope && !isScopeMatch(*parsed.scope, this))
|
||||
return -1; // wrong type name in qualified name
|
||||
return std::nullopt; // wrong type name in qualified name
|
||||
if (auto thisValue = lookup(parsed.key))
|
||||
value |= *thisValue;
|
||||
else
|
||||
return -1; // no such enumerator
|
||||
return std::nullopt; // no such enumerator
|
||||
}
|
||||
if (ok != nullptr)
|
||||
*ok = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -3401,18 +3534,28 @@ void join_reversed(String &s, const Container &c, Separator sep)
|
||||
Returns a byte array of '|'-separated keys that represents the
|
||||
given \a value.
|
||||
|
||||
\note Passing a 64-bit \a value to an enumeration whose underlying type is
|
||||
32-bit (that is, if is64Bit() returns \c false) results in an empty string
|
||||
being returned.
|
||||
|
||||
\sa isFlag(), valueToKey(), keysToValue()
|
||||
*/
|
||||
QByteArray QMetaEnum::valueToKeys(int value) const
|
||||
QByteArray QMetaEnum::valueToKeys(quint64 value) const
|
||||
{
|
||||
QByteArray keys;
|
||||
if (!mobj)
|
||||
return keys;
|
||||
|
||||
EnumExtendMode mode = enumExtendMode(*this);
|
||||
if (!isEnumValueSuitable(value, mode))
|
||||
return keys;
|
||||
|
||||
QVarLengthArray<QByteArrayView, sizeof(int) * CHAR_BIT> parts;
|
||||
int v = value;
|
||||
quint64 v = value;
|
||||
|
||||
// reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
|
||||
for (int i = data.keyCount() - 1; i >= 0; --i) {
|
||||
int k = mobj->d.data[data.data() + 2 * i + 1];
|
||||
quint64 k = value_helper(i, mode);
|
||||
if ((k != 0 && (v & k) == k) || (k == value)) {
|
||||
v = v & ~k;
|
||||
parts.push_back(stringDataView(mobj, mobj->d.data[data.data() + 2 * i]));
|
||||
|
@ -271,17 +271,25 @@ public:
|
||||
|
||||
bool isFlag() const;
|
||||
bool isScoped() const;
|
||||
bool is64Bit() const;
|
||||
|
||||
int keyCount() const;
|
||||
const char *key(int index) const;
|
||||
int value(int index) const;
|
||||
std::optional<quint64> value64(int index) const;
|
||||
|
||||
const char *scope() const;
|
||||
|
||||
int keyToValue(const char *key, bool *ok = nullptr) const;
|
||||
const char *valueToKey(int value) const;
|
||||
int keysToValue(const char *keys, bool *ok = nullptr) const;
|
||||
std::optional<quint64> keyToValue64(const char *key) const;
|
||||
std::optional<quint64> keysToValue64(const char *keys) const;
|
||||
#if QT_CORE_REMOVED_SINCE(6, 8)
|
||||
const char *valueToKey(int value) const;
|
||||
QByteArray valueToKeys(int value) const;
|
||||
#endif
|
||||
const char *valueToKey(quint64 value) const;
|
||||
QByteArray valueToKeys(quint64 value) const;
|
||||
|
||||
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
|
||||
|
||||
@ -312,6 +320,7 @@ private:
|
||||
};
|
||||
|
||||
QMetaEnum(const QMetaObject *mobj, int index);
|
||||
template <typename... Args> quint64 value_helper(uint index, Args...) const noexcept;
|
||||
|
||||
const QMetaObject *mobj;
|
||||
Data data;
|
||||
|
@ -1982,13 +1982,13 @@ static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toTy
|
||||
QMetaEnum en = metaEnumFromType(fromType);
|
||||
if (en.isValid()) {
|
||||
if (en.isFlag()) {
|
||||
const QByteArray keys = en.valueToKeys(static_cast<int>(ll));
|
||||
const QByteArray keys = en.valueToKeys(ll);
|
||||
if (toType.id() == QMetaType::QString)
|
||||
*static_cast<QString *>(to) = QString::fromUtf8(keys);
|
||||
else
|
||||
*static_cast<QByteArray *>(to) = keys;
|
||||
} else {
|
||||
const char *key = en.valueToKey(static_cast<int>(ll));
|
||||
const char *key = en.valueToKey(ll);
|
||||
if (toType.id() == QMetaType::QString)
|
||||
*static_cast<QString *>(to) = QString::fromUtf8(key);
|
||||
else
|
||||
@ -2014,7 +2014,10 @@ static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType
|
||||
QByteArray keys = (fromTypeId == QMetaType::QString)
|
||||
? static_cast<const QString *>(from)->toUtf8()
|
||||
: *static_cast<const QByteArray *>(from);
|
||||
value = en.keysToValue(keys.constData(), &ok);
|
||||
if (auto v = en.keysToValue64(keys.constData())) {
|
||||
ok = true;
|
||||
value = *v;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -11,14 +11,49 @@ class tst_QMetaEnum : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// these untyped enums are signed
|
||||
enum SuperEnum { SuperValue1 = 1, SuperValue2 = INT_MIN };
|
||||
enum Flag { Flag1 = 1, Flag2 = INT_MIN };
|
||||
|
||||
// we must force to ": unsigned" to get cross-platform behavior because
|
||||
// MSVC always chooses int to back un-fixed enums
|
||||
enum UnsignedEnum : unsigned { UnsignedValue1 = 1, UnsignedValue2 = 0x8000'0000 };
|
||||
enum Flag32 : unsigned { Flag32_1 = 1, Flag32_2 = 0x8000'0000 };
|
||||
|
||||
enum SignedEnum64 : qint64 {
|
||||
SignedValue64_0,
|
||||
SignedValue64_1 = 1,
|
||||
SignedValue64_Large = Q_INT64_C(1) << 32,
|
||||
SignedValue64_M1 = -1,
|
||||
};
|
||||
enum UnsignedEnum64 : quint64 {
|
||||
UnsignedValue64_0 = 0,
|
||||
UnsignedValue64_1 = 1,
|
||||
UnsignedValue64_Large = Q_UINT64_C(1) << 32,
|
||||
UnsignedValue64_Max = ~Q_UINT64_C(0),
|
||||
};
|
||||
|
||||
// flags should always be unsigned
|
||||
enum Flag64 : quint64 {
|
||||
Flag64_1 = 1,
|
||||
Flag64_2 = Q_UINT64_C(1) << 31,
|
||||
Flag64_3 = Q_UINT64_C(1) << 32,
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
Q_DECLARE_FLAGS(Flags32, Flag32)
|
||||
Q_DECLARE_FLAGS(Flags64, Flag64)
|
||||
Q_ENUM(SuperEnum)
|
||||
Q_ENUM(UnsignedEnum)
|
||||
Q_ENUM(SignedEnum64)
|
||||
Q_ENUM(UnsignedEnum64)
|
||||
Q_FLAG(Flags)
|
||||
Q_FLAG(Flags32)
|
||||
Q_FLAG(Flags64)
|
||||
|
||||
private slots:
|
||||
void fromType();
|
||||
void keyToValue_data();
|
||||
void keyToValue();
|
||||
void valuesToKeys_data();
|
||||
void valuesToKeys();
|
||||
void defaultConstructed();
|
||||
@ -28,23 +63,194 @@ void tst_QMetaEnum::fromType()
|
||||
{
|
||||
QMetaEnum meta = QMetaEnum::fromType<SuperEnum>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(!meta.is64Bit());
|
||||
QVERIFY(!meta.isFlag());
|
||||
QCOMPARE(meta.name(), "SuperEnum");
|
||||
QCOMPARE(meta.enumName(), "SuperEnum");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 2);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<SuperEnum>());
|
||||
|
||||
meta = QMetaEnum::fromType<UnsignedEnum>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(!meta.is64Bit());
|
||||
QVERIFY(!meta.isFlag());
|
||||
QCOMPARE(meta.name(), "UnsignedEnum");
|
||||
QCOMPARE(meta.enumName(), "UnsignedEnum");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 2);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<UnsignedEnum>());
|
||||
|
||||
meta = QMetaEnum::fromType<SignedEnum64>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(meta.is64Bit());
|
||||
QVERIFY(!meta.isFlag());
|
||||
QCOMPARE(meta.name(), "SignedEnum64");
|
||||
QCOMPARE(meta.enumName(), "SignedEnum64");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 4);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<SignedEnum64>());
|
||||
|
||||
meta = QMetaEnum::fromType<UnsignedEnum64>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(meta.is64Bit());
|
||||
QVERIFY(!meta.isFlag());
|
||||
QCOMPARE(meta.name(), "UnsignedEnum64");
|
||||
QCOMPARE(meta.enumName(), "UnsignedEnum64");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 4);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<UnsignedEnum64>());
|
||||
|
||||
meta = QMetaEnum::fromType<Flags>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(!meta.is64Bit());
|
||||
QVERIFY(meta.isFlag());
|
||||
QCOMPARE(meta.name(), "Flags");
|
||||
QCOMPARE(meta.enumName(), "Flag");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 2);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<Flags>());
|
||||
|
||||
meta = QMetaEnum::fromType<Flags32>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(!meta.is64Bit());
|
||||
QVERIFY(meta.isFlag());
|
||||
QCOMPARE(meta.name(), "Flags32");
|
||||
QCOMPARE(meta.enumName(), "Flag32");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 2);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<Flags32>());
|
||||
|
||||
meta = QMetaEnum::fromType<Flags64>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(meta.is64Bit());
|
||||
QVERIFY(meta.isFlag());
|
||||
QCOMPARE(meta.name(), "Flags64");
|
||||
QCOMPARE(meta.enumName(), "Flag64");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 3);
|
||||
QCOMPARE(meta.metaType(), QMetaType::fromType<Flags64>());
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(Qt::WindowFlags)
|
||||
|
||||
template <typename E> quint64 toUnderlying(E e, std::enable_if_t<std::is_enum_v<E>, bool> = true)
|
||||
{
|
||||
// keep signedness if it's just an enum
|
||||
return qToUnderlying(e);
|
||||
}
|
||||
|
||||
template <typename E> quint64 toUnderlying(QFlags<E> f)
|
||||
{
|
||||
// force to unsigned so we zero-extend if it's QFlags
|
||||
return typename QIntegerForSizeof<E>::Unsigned(f);
|
||||
}
|
||||
|
||||
void tst_QMetaEnum::keyToValue_data()
|
||||
{
|
||||
QTest::addColumn<QMetaEnum>("me");
|
||||
QTest::addColumn<QByteArray>("key");
|
||||
QTest::addColumn<quint64>("value");
|
||||
QTest::addColumn<bool>("success");
|
||||
|
||||
QByteArray notfoundkey = QByteArray::fromRawData("Foobar", 6);
|
||||
auto addNotFoundRow = [&](auto value) {
|
||||
QMetaEnum me = QMetaEnum::fromType<decltype(value)>();
|
||||
|
||||
QTest::addRow("notfound-%s", me.name())
|
||||
<< me << notfoundkey << quint64(value) << false;
|
||||
};
|
||||
auto addRow = [&](const char *name, auto value) {
|
||||
using T = decltype(value);
|
||||
QMetaEnum me = QMetaEnum::fromType<T>();
|
||||
QTest::addRow("%s", name) << me << QByteArray(name) << toUnderlying(value) << true;
|
||||
|
||||
if constexpr (sizeof(value) == sizeof(int)) {
|
||||
// repeat with the upper half negated
|
||||
quint64 v = toUnderlying(value);
|
||||
v ^= Q_UINT64_C(0xffff'ffff'0000'0000);
|
||||
QTest::addRow("mangled-%s", name) << me << notfoundkey << v << false;
|
||||
}
|
||||
};
|
||||
addRow("Window", Qt::Window);
|
||||
addRow("Dialog", Qt::Dialog);
|
||||
addRow("WindowFullscreenButtonHint", Qt::WindowFullscreenButtonHint);
|
||||
|
||||
addNotFoundRow(SuperEnum(2));
|
||||
addRow("SuperValue1", SuperValue1);
|
||||
addRow("SuperValue2", SuperValue2);
|
||||
|
||||
addNotFoundRow(Flags(2));
|
||||
addRow("Flag1", Flags(Flag1));
|
||||
addRow("Flag2", Flags(Flag2));
|
||||
|
||||
addNotFoundRow(UnsignedEnum(2));
|
||||
addRow("UnsignedValue1", UnsignedValue1);
|
||||
addRow("UnsignedValue2", UnsignedValue2);
|
||||
|
||||
addNotFoundRow(Flags32(2));
|
||||
addRow("Flag32_1", Flags32(Flag32_1));
|
||||
addRow("Flag32_2", Flags32(Flag32_2));
|
||||
|
||||
addNotFoundRow(SignedEnum64(2));
|
||||
addRow("SignedValue64_0", SignedValue64_0);
|
||||
addRow("SignedValue64_1", SignedValue64_1);
|
||||
addRow("SignedValue64_Large", SignedValue64_Large);
|
||||
addRow("SignedValue64_M1", SignedValue64_M1);
|
||||
|
||||
addNotFoundRow(UnsignedEnum64(2));
|
||||
addRow("UnsignedValue64_0", UnsignedValue64_0);
|
||||
addRow("UnsignedValue64_1", UnsignedValue64_1);
|
||||
addRow("UnsignedValue64_Large", UnsignedValue64_Large);
|
||||
addRow("UnsignedValue64_Max", UnsignedValue64_Max);
|
||||
|
||||
addNotFoundRow(Flags64(std::in_place, 2));
|
||||
addRow("Flag64_1", Flags64(Flag64_1));
|
||||
addRow("Flag64_2", Flags64(Flag64_2));
|
||||
addRow("Flag64_3", Flags64(Flag64_3));
|
||||
}
|
||||
|
||||
void tst_QMetaEnum::keyToValue()
|
||||
{
|
||||
QFETCH(QMetaEnum, me);
|
||||
QFETCH(quint64, value);
|
||||
QFETCH(QByteArray, key);
|
||||
QFETCH(bool, success);
|
||||
|
||||
if (!key.isEmpty()) {
|
||||
// look up value of key
|
||||
if (value == uint(value)) {
|
||||
bool ok;
|
||||
int value32 = success ? value : -1;
|
||||
int result32 = me.keyToValue(key, &ok);
|
||||
QCOMPARE(ok, success);
|
||||
QCOMPARE(result32, value32);
|
||||
|
||||
result32 = me.keysToValue(key, &ok);
|
||||
QCOMPARE(ok, success);
|
||||
QCOMPARE(result32, value32);
|
||||
}
|
||||
|
||||
std::optional value64 = me.keyToValue64(key);
|
||||
QCOMPARE(value64.has_value(), success);
|
||||
if (success)
|
||||
QCOMPARE(*value64, value);
|
||||
|
||||
value64 = me.keysToValue64(key);
|
||||
QCOMPARE(value64.has_value(), success);
|
||||
if (success)
|
||||
QCOMPARE(*value64, value);
|
||||
}
|
||||
|
||||
// look up value
|
||||
QByteArray expected = success ? key : QByteArray();
|
||||
QByteArray result = me.valueToKey(value);
|
||||
QCOMPARE(result, expected);
|
||||
|
||||
result = me.valueToKeys(value);
|
||||
QCOMPARE(result, expected);
|
||||
}
|
||||
|
||||
void tst_QMetaEnum::valuesToKeys_data()
|
||||
{
|
||||
QTest::addColumn<QMetaEnum>("me");
|
||||
@ -69,10 +275,43 @@ void tst_QMetaEnum::valuesToKeys_data()
|
||||
<< quint64(Qt::Tool | Qt::WindowMinMaxButtonsHint | Qt::WindowStaysOnTopHint)
|
||||
<< QByteArrayLiteral("Tool|WindowMinMaxButtonsHint|WindowStaysOnTopHint");
|
||||
|
||||
QTest::newRow("INT_MIN")
|
||||
// Verify that upper bits set don't cause a mistaken detection
|
||||
QTest::newRow("upperbits-Window")
|
||||
<< QMetaEnum::fromType<Qt::WindowFlags>()
|
||||
<< (quint64(Qt::Window) | Q_UINT64_C(0x1'0000'0000))
|
||||
<< QByteArray();
|
||||
|
||||
QTest::newRow("INT_MIN-as-enum")
|
||||
<< QMetaEnum::fromType<SuperEnum>()
|
||||
<< quint64(SuperValue2)
|
||||
<< QByteArrayLiteral("SuperValue2");
|
||||
QTest::newRow("mangled-INT_MIN-as-enum")
|
||||
<< QMetaEnum::fromType<SuperEnum>()
|
||||
<< quint64(uint(SuperValue2))
|
||||
<< QByteArray();
|
||||
|
||||
QTest::newRow("INT_MIN-as-flags")
|
||||
<< QMetaEnum::fromType<Flags>()
|
||||
<< quint64(uint(Flag2))
|
||||
<< QByteArrayLiteral("Flag2");
|
||||
QTest::newRow("mangled-INT_MIN-as-flags")
|
||||
<< QMetaEnum::fromType<Flags>()
|
||||
<< quint64(Flag2)
|
||||
<< QByteArray();
|
||||
|
||||
QTest::newRow("Flag32_2")
|
||||
<< QMetaEnum::fromType<Flags32>()
|
||||
<< quint64(uint(Flag32_2))
|
||||
<< QByteArrayLiteral("Flag32_2");
|
||||
QTest::newRow("mangled-Flag32_2")
|
||||
<< QMetaEnum::fromType<Flags32>()
|
||||
<< quint64(int(Flag32_2))
|
||||
<< QByteArray();
|
||||
|
||||
QTest::newRow("Flag64_all")
|
||||
<< QMetaEnum::fromType<Flags64>()
|
||||
<< quint64(Flag64_1 | Flag64_2 | Flag64_3)
|
||||
<< QByteArrayLiteral("Flag64_1|Flag64_2|Flag64_3");
|
||||
}
|
||||
|
||||
void tst_QMetaEnum::valuesToKeys()
|
||||
@ -82,9 +321,12 @@ void tst_QMetaEnum::valuesToKeys()
|
||||
QFETCH(QByteArray, expected);
|
||||
|
||||
QCOMPARE(me.valueToKeys(flags), expected);
|
||||
if (!expected.isEmpty()) {
|
||||
bool ok = false;
|
||||
QCOMPARE(uint(me.keysToValue(expected, &ok)), flags);
|
||||
QCOMPARE(uint(me.keysToValue(expected, &ok)), uint(flags));
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(me.keysToValue64(expected), flags);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QMetaEnum::defaultConstructed()
|
||||
@ -93,7 +335,12 @@ void tst_QMetaEnum::defaultConstructed()
|
||||
QVERIFY(!e.isValid());
|
||||
QVERIFY(!e.isScoped());
|
||||
QVERIFY(!e.isFlag());
|
||||
QVERIFY(!e.is64Bit());
|
||||
QCOMPARE(e.name(), QByteArray());
|
||||
QCOMPARE(e.scope(), QByteArray());
|
||||
QCOMPARE(e.enclosingMetaObject(), nullptr);
|
||||
QCOMPARE(e.keyCount(), 0);
|
||||
QCOMPARE(e.metaType(), QMetaType());
|
||||
}
|
||||
|
||||
static_assert(QtPrivate::IsQEnumHelper<tst_QMetaEnum::SuperEnum>::Value);
|
||||
|
@ -2371,16 +2371,22 @@ void tst_QMetaObject::keysToValue()
|
||||
QVERIFY(me.isValid());
|
||||
QVERIFY(!me.isFlag());
|
||||
QCOMPARE(QByteArray(me.scope()), QByteArray("MyNamespace::" + name));
|
||||
QCOMPARE(me.keyToValue64("MyNamespace::" + name + "::MyEnum2"), 1U);
|
||||
QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum2", &ok), 1);
|
||||
// Fully qualified unscoped enumerator
|
||||
QCOMPARE(me.keyToValue64("MyNamespace::" + name + "::MyEnum::MyEnum2"), 1U);
|
||||
QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum::MyEnum2", &ok), 1);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(me.keyToValue64(name + "::MyEnum2"), std::nullopt);
|
||||
QCOMPARE(me.keyToValue(name + "::MyEnum2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(me.keyToValue64("MyNamespace::MyEnum2"), std::nullopt);
|
||||
QCOMPARE(me.keyToValue("MyNamespace::MyEnum2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(me.keyToValue64("MyEnum2"), 1U);
|
||||
QCOMPARE(me.keyToValue("MyEnum2", &ok), 1);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(me.keyToValue64("MyEnum"), std::nullopt);
|
||||
QCOMPARE(me.keyToValue("MyEnum", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(QLatin1String(me.valueToKey(1)), QLatin1String("MyEnum2"));
|
||||
@ -2388,12 +2394,16 @@ void tst_QMetaObject::keysToValue()
|
||||
QMetaEnum me2 = mo->enumerator(mo->indexOfEnumerator("MyAnotherEnum"));
|
||||
QVERIFY(me2.isValid());
|
||||
QVERIFY(!me2.isFlag());
|
||||
QCOMPARE(me2.keyToValue64("MyAnotherEnum1"), 1U);
|
||||
QCOMPARE(me2.keyToValue("MyAnotherEnum1", &ok), 1);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(me2.keyToValue64("MyAnotherEnum2"), 2U);
|
||||
QCOMPARE(me2.keyToValue("MyAnotherEnum2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(me2.keyToValue64("MyAnotherEnum3"), quint64(-1));
|
||||
QCOMPARE(me2.keyToValue("MyAnotherEnum3", &ok), -1);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(me2.keyToValue64("MyAnotherEnum"), std::nullopt);
|
||||
QCOMPARE(me2.keyToValue("MyAnotherEnum", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
|
||||
@ -2401,55 +2411,80 @@ void tst_QMetaObject::keysToValue()
|
||||
QVERIFY(mf.isValid());
|
||||
QVERIFY(mf.isFlag());
|
||||
QCOMPARE(QByteArray(mf.scope()), QByteArray("MyNamespace::" + name));
|
||||
QCOMPARE(mf.keysToValue64("MyNamespace::" + name + "::MyFlag2"), 2U);
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
// Fully qualified
|
||||
QCOMPARE(mf.keysToValue64("MyNamespace::" + name + "::MyFlag::MyFlag2"), 2U);
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue64(name + "::MyFlag2"), std::nullopt);
|
||||
QCOMPARE(mf.keysToValue(name + "::MyFlag2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(mf.keysToValue64("MyNamespace::MyFlag2"), std::nullopt);
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::MyFlag2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(mf.keysToValue64("MyFlag2"), 2U);
|
||||
QCOMPARE(mf.keysToValue("MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue64("MyFlag"), std::nullopt);
|
||||
QCOMPARE(mf.keysToValue("MyFlag", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(QLatin1String(mf.valueToKey(2)), QLatin1String("MyFlag2"));
|
||||
|
||||
const QByteArray prefix = "MyNamespace::" + name;
|
||||
QCOMPARE(mf.keysToValue64(prefix + "::MyFlag1|" + prefix + "::MyFlag2"), 3U);
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag1|" + prefix + "::MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
// Fully qualified
|
||||
QCOMPARE(mf.keysToValue64(prefix + "::MyFlag::MyFlag1|" + prefix + "::MyFlag::MyFlag2"), 3U);
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag::MyFlag1|" + prefix + "::MyFlag::MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue64(name + "::MyFlag1|" + name + "::MyFlag2"), std::nullopt);
|
||||
QCOMPARE(mf.keysToValue(name + "::MyFlag1|" + name + "::MyFlag2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(mf.keysToValue64("MyNamespace::MyFlag1|MyNamespace::MyFlag2"), std::nullopt);
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::MyFlag1|MyNamespace::MyFlag2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(mf.keysToValue64("MyFlag1|MyFlag2"), 3U);
|
||||
QCOMPARE(mf.keysToValue("MyFlag1|MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue64("MyFlag2|MyFlag2"), 2U);
|
||||
QCOMPARE(mf.keysToValue("MyFlag2|MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue64("MyFlag1|MyNamespace::" + name + "::MyFlag2"), 3U);
|
||||
QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue64(prefix + "::MyFlag2|" + prefix + "::MyFlag2"), 2U);
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag2|" + prefix + "::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
// Fully qualified
|
||||
QCOMPARE(mf.keysToValue64(prefix + "::MyFlag::MyFlag2|" + prefix + "::MyFlag::MyFlag2"), 2U);
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag::MyFlag2|" + prefix + "::MyFlag::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2"));
|
||||
|
||||
// Test flags with extra '|'
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
QRegularExpression(u"QMetaEnum::keysToValue: malformed keys string, ends with '|'.+"_s));
|
||||
QCOMPARE(mf.keysToValue64("MyFlag1|MyFlag2|"), std::nullopt);
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
QRegularExpression(u"QMetaEnum::keysToValue: malformed keys string, ends with '|'.+"_s));
|
||||
QCOMPARE(mf.keysToValue("MyFlag1|MyFlag2|", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
QRegularExpression(u"QMetaEnum::keysToValue: malformed keys string, starts with '|'.+"_s));
|
||||
QCOMPARE(mf.keysToValue64("|MyFlag1|MyFlag2|"), std::nullopt);
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
QRegularExpression(u"QMetaEnum::keysToValue: malformed keys string, starts with '|'.+"_s));
|
||||
QCOMPARE(mf.keysToValue("|MyFlag1|MyFlag2|", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
QRegularExpression(
|
||||
u"QMetaEnum::keysToValue: malformed keys string, has two consecutive '|'.+"_s));
|
||||
QCOMPARE(mf.keysToValue64("MyFlag1||MyFlag2"), std::nullopt);
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
QRegularExpression(
|
||||
u"QMetaEnum::keysToValue: malformed keys string, has two consecutive '|'.+"_s));
|
||||
@ -2458,6 +2493,8 @@ void tst_QMetaObject::keysToValue()
|
||||
|
||||
// Test empty string
|
||||
QTest::ignoreMessage(QtWarningMsg, "QMetaEnum::keysToValue: empty keys string.");
|
||||
QCOMPARE(mf.keysToValue64(""), std::nullopt);
|
||||
QTest::ignoreMessage(QtWarningMsg, "QMetaEnum::keysToValue: empty keys string.");
|
||||
QCOMPARE(mf.keysToValue("", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
}
|
||||
|
@ -5371,10 +5371,6 @@ template <typename Enum, auto Value> static void testVariantMetaEnum()
|
||||
|
||||
QVariant strVar = string;
|
||||
QVERIFY(strVar.canConvert<Enum>());
|
||||
// unary + to silence gcc warning
|
||||
if ((+static_cast<qint64>(value) > INT_MAX) || (+static_cast<qint64>(value) < INT_MIN)) {
|
||||
QEXPECT_FAIL("", "QMetaEnum api uses 'int' as return type QTBUG-27451", Abort);
|
||||
}
|
||||
QCOMPARE(strVar.value<Enum>(), value);
|
||||
strVar = string.toLatin1();
|
||||
QVERIFY(strVar.canConvert<Enum>());
|
||||
|
@ -38,6 +38,7 @@ set(JSON_HEADERS
|
||||
plugin_metadata.h
|
||||
pointery_to_incomplete.h
|
||||
pure-virtual-signals.h
|
||||
qflags64object.h
|
||||
qinvokable.h
|
||||
qprivateslots.h
|
||||
qtbug-35657-gadget.h
|
||||
|
@ -2071,6 +2071,75 @@
|
||||
"inputFile": "pure-virtual-signals.h",
|
||||
"outputRevision": 68
|
||||
},
|
||||
{
|
||||
"classes": [
|
||||
{
|
||||
"className": "QEnum64Object",
|
||||
"enums": [
|
||||
{
|
||||
"isClass": false,
|
||||
"isFlag": false,
|
||||
"name": "LargeEnum",
|
||||
"type": "qint64",
|
||||
"values": [
|
||||
"Value0",
|
||||
"ValueMixed",
|
||||
"ValueMinus1"
|
||||
]
|
||||
}
|
||||
],
|
||||
"lineNumber": 8,
|
||||
"object": true,
|
||||
"qualifiedClassName": "QEnum64Object",
|
||||
"superClasses": [
|
||||
{
|
||||
"access": "public",
|
||||
"name": "QObject"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"className": "QFlags64Object",
|
||||
"enums": [
|
||||
{
|
||||
"alias": "LargeFlag",
|
||||
"isClass": false,
|
||||
"isFlag": true,
|
||||
"name": "LargeFlags",
|
||||
"type": "qint64",
|
||||
"values": [
|
||||
"Value0",
|
||||
"ValueMixed",
|
||||
"ValueMinus1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"alias": "ScopedLargeFlag",
|
||||
"isClass": true,
|
||||
"isFlag": true,
|
||||
"name": "ScopedLargeFlags",
|
||||
"type": "quint64",
|
||||
"values": [
|
||||
"Value0",
|
||||
"ValueMixed",
|
||||
"ValueMinus1"
|
||||
]
|
||||
}
|
||||
],
|
||||
"lineNumber": 20,
|
||||
"object": true,
|
||||
"qualifiedClassName": "QFlags64Object",
|
||||
"superClasses": [
|
||||
{
|
||||
"access": "public",
|
||||
"name": "QObject"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputFile": "qflags64object.h",
|
||||
"outputRevision": 68
|
||||
},
|
||||
{
|
||||
"classes": [
|
||||
{
|
||||
|
41
tests/auto/tools/moc/qflags64object.h
Normal file
41
tests/auto/tools/moc/qflags64object.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2024 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#ifndef QFLAGS64OBJECT_H
|
||||
#define QFLAGS64OBJECT_H
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QEnum64Object : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum LargeEnum : qint64 {
|
||||
Value0 = 0,
|
||||
ValueMixed = Q_INT64_C(0x1122'3344'5566'7788),
|
||||
ValueMinus1 = -1,
|
||||
};
|
||||
Q_ENUM(LargeEnum)
|
||||
};
|
||||
|
||||
class QFlags64Object : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum LargeFlag : qint64 {
|
||||
Value0 = 0,
|
||||
ValueMixed = Q_INT64_C(0x1122'3344'5566'7788),
|
||||
ValueMinus1 = -1,
|
||||
};
|
||||
Q_DECLARE_FLAGS(LargeFlags, LargeFlag)
|
||||
Q_FLAG(LargeFlags)
|
||||
|
||||
enum class ScopedLargeFlag : quint64 {
|
||||
Value0 = 0,
|
||||
ValueMixed = Q_UINT64_C(0x1122'3344'5566'7788),
|
||||
ValueMinus1 = quint64(-1),
|
||||
};
|
||||
Q_DECLARE_FLAGS(ScopedLargeFlags, ScopedLargeFlag)
|
||||
Q_FLAG(ScopedLargeFlags)
|
||||
};
|
||||
|
||||
#endif // QFLAGS64OBJECT_H
|
@ -1,5 +1,6 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// Copyright (C) 2020 Olivier Goffart <ogoffart@woboq.com>
|
||||
// Copyright (C) 2024 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <QTest>
|
||||
@ -49,6 +50,7 @@
|
||||
|
||||
#include "non-gadget-parent-class.h"
|
||||
#include "grand-parent-gadget-class.h"
|
||||
#include "qflags64object.h"
|
||||
#include "namespace.h"
|
||||
#include "cxx17-namespaces.h"
|
||||
#include "cxx-attributes.h"
|
||||
@ -861,6 +863,7 @@ private slots:
|
||||
void gadgetHierarchy();
|
||||
void optionsFileError_data();
|
||||
void optionsFileError();
|
||||
void enumAndFlags64();
|
||||
void testQNamespace();
|
||||
void testNestedQNamespace();
|
||||
void cxx17Namespaces();
|
||||
@ -4168,11 +4171,51 @@ static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name,
|
||||
QCOMPARE(enumerator.metaType(), enumType);
|
||||
for (int i = 0; i < enumerator.keyCount(); ++i) {
|
||||
QCOMPARE(QByteArray{enumerator.key(i)}, keys[i].first);
|
||||
QCOMPARE(enumerator.value(i), keys[i].second);
|
||||
QCOMPARE(enumerator.value(i), int(keys[i].second));
|
||||
QCOMPARE(*enumerator.value64(i), keys[i].second);
|
||||
}
|
||||
// out of range
|
||||
QVERIFY(!enumerator.key(keys.size()));
|
||||
QCOMPARE(enumerator.value(keys.size()), -1);
|
||||
QVERIFY(!enumerator.value64(keys.size()));
|
||||
}
|
||||
|
||||
void tst_Moc::enumAndFlags64()
|
||||
{
|
||||
const QList<QPair<QByteArray, quint64>> values = {
|
||||
{ "Value0", 0 },
|
||||
{ "ValueMixed", Q_UINT64_C(0x1122'3344'5566'7788) },
|
||||
{ "ValueMinus1", quint64(-1) },
|
||||
};
|
||||
QCOMPARE(QEnum64Object::staticMetaObject.enumeratorCount(), 1);
|
||||
QCOMPARE(QFlags64Object::staticMetaObject.enumeratorCount(), 2);
|
||||
|
||||
QMetaEnum me = QMetaEnum::fromType<QEnum64Object::LargeEnum>();
|
||||
QVERIFY(!me.isFlag());
|
||||
QVERIFY(me.is64Bit());
|
||||
QVERIFY(!me.isScoped());
|
||||
checkEnum(me, "LargeEnum", values,
|
||||
QMetaType::fromType<QEnum64Object::LargeEnum>());
|
||||
|
||||
if (QTest::currentTestFailed()) return;
|
||||
|
||||
me = QMetaEnum::fromType<QFlags64Object::LargeFlags>();
|
||||
QVERIFY(me.isFlag());
|
||||
QVERIFY(me.is64Bit());
|
||||
QVERIFY(!me.isScoped());
|
||||
QCOMPARE(me.enumName(), "LargeFlag");
|
||||
checkEnum(me, "LargeFlags", values,
|
||||
QMetaType::fromType<QFlags64Object::LargeFlags>());
|
||||
|
||||
if (QTest::currentTestFailed()) return;
|
||||
|
||||
me = QMetaEnum::fromType<QFlags64Object::ScopedLargeFlags>();
|
||||
QVERIFY(me.isFlag());
|
||||
QVERIFY(me.is64Bit());
|
||||
QVERIFY(me.isScoped());
|
||||
QCOMPARE(me.enumName(), "ScopedLargeFlag");
|
||||
checkEnum(me, "ScopedLargeFlags", values,
|
||||
QMetaType::fromType<QFlags64Object::ScopedLargeFlags>());
|
||||
}
|
||||
|
||||
class EnumFromNamespaceClass : public QObject
|
||||
@ -4277,6 +4320,7 @@ void tst_Moc::cxx17Namespaces()
|
||||
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().name(), "NamEn");
|
||||
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().keyCount(), 1);
|
||||
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().value(0), 4);
|
||||
QCOMPARE(*QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().value64(0), 4U);
|
||||
|
||||
QCOMPARE(CXX17Namespace::A::B::C::D::ClassInNamespace::staticMetaObject.className(),
|
||||
"CXX17Namespace::A::B::C::D::ClassInNamespace");
|
||||
@ -4285,6 +4329,7 @@ void tst_Moc::cxx17Namespaces()
|
||||
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().name(), "GadEn");
|
||||
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().keyCount(), 1);
|
||||
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().value(0), 3);
|
||||
QCOMPARE(*QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().value64(0), 3U);
|
||||
}
|
||||
|
||||
void tst_Moc::cxxAttributes()
|
||||
|
Loading…
x
Reference in New Issue
Block a user