moc: Record types of enumerations
This will be helpful in a number of places, in particular in order to support enums of different sizes in QML. We record the type as string in the JSON output and as QMetaTypeInterface in the generated C++. Task-number: QTBUG-112180 Change-Id: I943fac67f8b25b013d3860301416cdd293c0c69e Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
ecd7ddcc3e
commit
b83de5f9a4
@ -419,10 +419,30 @@ QMetaType QMetaObject::metaType() const
|
||||
return QMetaType::fromName(className());
|
||||
} else {
|
||||
/* in the metatype array, we store
|
||||
idx: 0 propertyCount - 1 propertyCount
|
||||
data:QMetaType(prop0), ..., QMetaType(propPropCount-1), QMetaType(class),...
|
||||
*/
|
||||
auto iface = this->d.metaTypes[d->propertyCount];
|
||||
|
||||
| index | data |
|
||||
|----------------------------------------------------------------------|
|
||||
| 0 | QMetaType(property0) |
|
||||
| ... | ... |
|
||||
| propertyCount - 1 | QMetaType(propertyCount - 1) |
|
||||
| propertyCount | QMetaType(enumerator0) |
|
||||
| ... | ... |
|
||||
| propertyCount + enumeratorCount - 1 | QMetaType(enumeratorCount - 1) |
|
||||
| propertyCount + enumeratorCount | QMetaType(class) |
|
||||
|
||||
*/
|
||||
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
|
||||
// Before revision 12 we only stored metatypes for enums if they showed
|
||||
// up as types of properties or method arguments or return values.
|
||||
// From revision 12 on, we always store them in a predictable place.
|
||||
const qsizetype offset = d->revision < 12
|
||||
? d->propertyCount
|
||||
: d->propertyCount + d->enumeratorCount;
|
||||
#else
|
||||
const qsizetype offset = d->propertyCount + d->enumeratorCount;
|
||||
#endif
|
||||
|
||||
auto iface = this->d.metaTypes[offset];
|
||||
if (iface && QtMetaTypePrivate::isInterfaceFor<void>(iface))
|
||||
return QMetaType(); // return invalid meta-type for namespaces
|
||||
if (iface)
|
||||
@ -3036,6 +3056,33 @@ const char *QMetaEnum::enumName() const
|
||||
return rawStringData(mobj, data.alias());
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the meta type of the enum.
|
||||
|
||||
If the QMetaObject this enum is part of was generated with Qt 6.5 or
|
||||
earlier this will be the invalid metatype.
|
||||
|
||||
\note This is the meta type of the enum itself, not of its underlying
|
||||
numeric type. You can retrieve the meta type of the underlying type of the
|
||||
enum using \l{QMetaType::underlyingType()}.
|
||||
|
||||
\since 6.6
|
||||
\sa QMetaType::underlyingType()
|
||||
*/
|
||||
QMetaType QMetaEnum::metaType() const
|
||||
{
|
||||
if (!mobj)
|
||||
return {};
|
||||
|
||||
const QMetaObjectPrivate *p = priv(mobj->d.data);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
|
||||
if (p->revision < 12)
|
||||
QMetaType();
|
||||
#endif
|
||||
|
||||
return QMetaType(mobj->d.metaTypes[data.index(mobj) + p->propertyCount]);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of keys.
|
||||
|
||||
@ -3285,6 +3332,11 @@ QMetaEnum::QMetaEnum(const QMetaObject *mobj, int index)
|
||||
Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->enumeratorCount);
|
||||
}
|
||||
|
||||
int QMetaEnum::Data::index(const QMetaObject *mobj) const
|
||||
{
|
||||
return (d - mobj->d.data - priv(mobj->d.data)->enumeratorData) / Size;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QMetaEnum QMetaEnum::fromType()
|
||||
\since 5.5
|
||||
|
@ -265,6 +265,8 @@ public:
|
||||
|
||||
const char *name() const;
|
||||
const char *enumName() const;
|
||||
QMetaType metaType() const;
|
||||
|
||||
bool isFlag() const;
|
||||
bool isScoped() const;
|
||||
|
||||
@ -302,6 +304,7 @@ private:
|
||||
quint32 flags() const { return d[2]; }
|
||||
qint32 keyCount() const { return static_cast<qint32>(d[3]); }
|
||||
quint32 data() const { return d[4]; }
|
||||
int index(const QMetaObject *mobj) const;
|
||||
|
||||
const uint *d;
|
||||
};
|
||||
|
@ -175,7 +175,8 @@ struct QMetaObjectPrivate
|
||||
// revision 10 is Qt 6.2: The metatype of the metaobject is stored in the metatypes array
|
||||
// and metamethods store a flag stating whether they are const
|
||||
// revision 11 is Qt 6.5: The metatype for void is stored in the metatypes array
|
||||
enum { OutputRevision = 11 }; // Used by moc, qmetaobjectbuilder and qdbus
|
||||
// revision 12 is Qt 6.6: It adds the metatype for enums
|
||||
enum { OutputRevision = 12 }; // Used by moc, qmetaobjectbuilder and qdbus
|
||||
enum { IntsPerMethod = QMetaMethod::Data::Size };
|
||||
enum { IntsPerEnum = QMetaEnum::Data::Size };
|
||||
enum { IntsPerProperty = QMetaProperty::Data::Size };
|
||||
|
@ -159,6 +159,7 @@ public:
|
||||
|
||||
QByteArray name;
|
||||
QByteArray enumName;
|
||||
QMetaType metaType;
|
||||
bool isFlag;
|
||||
bool isScoped;
|
||||
QList<QByteArray> keys;
|
||||
@ -597,6 +598,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum &prototype)
|
||||
{
|
||||
QMetaEnumBuilder en = addEnumerator(prototype.name());
|
||||
en.setEnumName(prototype.enumName());
|
||||
en.setMetaType(prototype.metaType());
|
||||
en.setIsFlag(prototype.isFlag());
|
||||
en.setIsScoped(prototype.isScoped());
|
||||
int count = prototype.keyCount();
|
||||
@ -1170,7 +1172,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
- int(d->methods.size()) // return "parameters" don't have names
|
||||
- int(d->constructors.size()); // "this" parameters don't have names
|
||||
if constexpr (mode == Construct) {
|
||||
static_assert(QMetaObjectPrivate::OutputRevision == 11, "QMetaObjectBuilder should generate the same version as moc");
|
||||
static_assert(QMetaObjectPrivate::OutputRevision == 12, "QMetaObjectBuilder should generate the same version as moc");
|
||||
pmeta->revision = QMetaObjectPrivate::OutputRevision;
|
||||
pmeta->flags = d->flags.toInt();
|
||||
pmeta->className = 0; // Class name is always the first string.
|
||||
@ -2305,6 +2307,31 @@ void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
|
||||
d->enumName = alias;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the meta type of the enumerator.
|
||||
|
||||
\since 6.6
|
||||
*/
|
||||
QMetaType QMetaEnumBuilder::metaType() const
|
||||
{
|
||||
if (QMetaEnumBuilderPrivate *d = d_func())
|
||||
return d->metaType;
|
||||
return QMetaType();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets this enumerator to have the given \c metaType.
|
||||
|
||||
\since 6.6
|
||||
\sa metaType()
|
||||
*/
|
||||
void QMetaEnumBuilder::setMetaType(QMetaType metaType)
|
||||
{
|
||||
QMetaEnumBuilderPrivate *d = d_func();
|
||||
if (d)
|
||||
d->metaType = metaType;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if this enumerator is used as a flag; otherwise returns
|
||||
false.
|
||||
|
@ -258,6 +258,9 @@ public:
|
||||
QByteArray enumName() const;
|
||||
void setEnumName(const QByteArray &alias);
|
||||
|
||||
QMetaType metaType() const;
|
||||
void setMetaType(QMetaType metaType);
|
||||
|
||||
bool isFlag() const;
|
||||
void setIsFlag(bool value);
|
||||
|
||||
|
@ -391,7 +391,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
- methods.size(); // ditto
|
||||
|
||||
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
||||
static_assert(QMetaObjectPrivate::OutputRevision == 11, "QtDBus meta-object generator should generate the same version as moc");
|
||||
static_assert(QMetaObjectPrivate::OutputRevision == 12, "QtDBus meta-object generator should generate the same version as moc");
|
||||
header->revision = QMetaObjectPrivate::OutputRevision;
|
||||
header->className = 0;
|
||||
header->classInfoCount = 0;
|
||||
|
@ -378,7 +378,7 @@ void Generator::generateCode()
|
||||
|
||||
int enumsIndex = index;
|
||||
for (int i = 0; i < cdef->enumList.size(); ++i)
|
||||
index += 5 + (cdef->enumList.at(i).values.size() * 2);
|
||||
index += QMetaObjectPrivate::IntsPerEnum + (cdef->enumList.at(i).values.size() * 2);
|
||||
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? int(cdef->constructorList.size()) : 0,
|
||||
isConstructible ? index : 0);
|
||||
|
||||
@ -397,8 +397,8 @@ void Generator::generateCode()
|
||||
//
|
||||
generateClassInfos();
|
||||
|
||||
// all property metatypes, + 1 for the type of the current class itself
|
||||
int initialMetaTypeOffset = cdef->propertyList.size() + 1;
|
||||
// all property metatypes + all enum metatypes + 1 for the type of the current class itself
|
||||
int initialMetaTypeOffset = cdef->propertyList.size() + cdef->enumList.size() + 1;
|
||||
|
||||
//
|
||||
// Build signals array first, otherwise the signal indices would be wrong
|
||||
@ -576,6 +576,15 @@ void Generator::generateCode()
|
||||
comma = ",";
|
||||
}
|
||||
|
||||
// metatypes for enums
|
||||
for (int i = 0; i < cdef->enumList.size(); ++i) {
|
||||
const EnumDef &e = cdef->enumList.at(i);
|
||||
fprintf(out, "%s\n // enum '%s'\n %s",
|
||||
comma, e.name.constData(),
|
||||
stringForType(cdef->classname % "::" % e.name, true).constData());
|
||||
comma = ",";
|
||||
}
|
||||
|
||||
// type name for the Q_OJBECT/GADGET itself, void for namespaces
|
||||
auto ownType = !cdef->hasQNamespace ? cdef->classname.data() : "void";
|
||||
fprintf(out, "%s\n // Q_OBJECT / Q_GADGET\n %s",
|
||||
@ -943,7 +952,7 @@ void Generator::generateEnums(int index)
|
||||
return;
|
||||
|
||||
fprintf(out, "\n // enums: name, alias, flags, count, data\n");
|
||||
index += 5 * cdef->enumList.size();
|
||||
index += QMetaObjectPrivate::IntsPerEnum * cdef->enumList.size();
|
||||
int i;
|
||||
for (i = 0; i < cdef->enumList.size(); ++i) {
|
||||
const EnumDef &e = cdef->enumList.at(i);
|
||||
|
@ -243,7 +243,7 @@ bool Moc::parseEnum(EnumDef *def)
|
||||
}
|
||||
if (test(COLON)) { // C++11 strongly typed enum
|
||||
// enum Foo : unsigned long { ... };
|
||||
parseType(); //ignore the result
|
||||
def->type = normalizeType(parseType().name);
|
||||
}
|
||||
if (!test(LBRACE))
|
||||
return false;
|
||||
@ -2107,6 +2107,8 @@ QJsonObject EnumDef::toJson(const ClassDef &cdef) const
|
||||
def["name"_L1] = QString::fromUtf8(name);
|
||||
if (!enumName.isEmpty())
|
||||
def["alias"_L1] = QString::fromUtf8(enumName);
|
||||
if (!type.isEmpty())
|
||||
def["type"_L1] = QString::fromUtf8(type);
|
||||
def["isFlag"_L1] = cdef.enumDeclarations.value(name);
|
||||
def["isClass"_L1] = isEnumClass;
|
||||
|
||||
|
@ -43,6 +43,7 @@ struct EnumDef
|
||||
{
|
||||
QByteArray name;
|
||||
QByteArray enumName;
|
||||
QByteArray type;
|
||||
QList<QByteArray> values;
|
||||
bool isEnumClass; // c++11 enum class
|
||||
EnumDef() : isEnumClass(false) {}
|
||||
|
@ -779,6 +779,26 @@ void tst_QMetaObjectBuilder::notifySignal()
|
||||
|
||||
void tst_QMetaObjectBuilder::enumerator()
|
||||
{
|
||||
static const QtPrivate::QMetaTypeInterface fooFlagMetaType = {
|
||||
0,
|
||||
8,
|
||||
8,
|
||||
QMetaType::IsEnumeration | QMetaType::IsUnsignedEnumeration | QMetaType::RelocatableType,
|
||||
{},
|
||||
nullptr,
|
||||
"fooFlag",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
QMetaObjectBuilder builder;
|
||||
|
||||
// Add an enumerator and check its attributes.
|
||||
@ -810,6 +830,7 @@ void tst_QMetaObjectBuilder::enumerator()
|
||||
enum1.setIsFlag(true);
|
||||
enum1.setIsScoped(true);
|
||||
enum1.setEnumName(QByteArrayLiteral("fooFlag"));
|
||||
enum1.setMetaType(QMetaType(&fooFlagMetaType));
|
||||
QCOMPARE(enum1.addKey("ABC", 0), 0);
|
||||
QCOMPARE(enum1.addKey("DEF", 1), 1);
|
||||
QCOMPARE(enum1.addKey("GHI", -1), 2);
|
||||
@ -819,6 +840,7 @@ void tst_QMetaObjectBuilder::enumerator()
|
||||
QVERIFY(enum1.isFlag());
|
||||
QVERIFY(enum1.isScoped());
|
||||
QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
|
||||
QCOMPARE(enum1.metaType(), QMetaType(&fooFlagMetaType));
|
||||
QCOMPARE(enum1.keyCount(), 3);
|
||||
QCOMPARE(enum1.index(), 0);
|
||||
QCOMPARE(enum1.key(0), QByteArray("ABC"));
|
||||
|
@ -91,6 +91,7 @@
|
||||
"isClass": false,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnum",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"B0",
|
||||
"B1",
|
||||
@ -102,6 +103,7 @@
|
||||
"isClass": true,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnumClass",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"C0",
|
||||
"C1",
|
||||
@ -147,6 +149,7 @@
|
||||
"isClass": true,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnumStruct",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"H0",
|
||||
"H1",
|
||||
@ -188,6 +191,7 @@
|
||||
"isClass": false,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnum",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"B0",
|
||||
"B1",
|
||||
@ -199,6 +203,7 @@
|
||||
"isClass": true,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnumClass",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"C0",
|
||||
"C1",
|
||||
@ -232,6 +237,65 @@
|
||||
],
|
||||
"gadget": true,
|
||||
"qualifiedClassName": "CXX11Enums2"
|
||||
},
|
||||
{
|
||||
"className": "CXX11Enums3",
|
||||
"enums": [
|
||||
{
|
||||
"isClass": true,
|
||||
"isFlag": false,
|
||||
"name": "EnumClass",
|
||||
"values": [
|
||||
"A0",
|
||||
"A1",
|
||||
"A2",
|
||||
"A3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"isClass": false,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnum",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"B0",
|
||||
"B1",
|
||||
"B2",
|
||||
"B3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"isClass": true,
|
||||
"isFlag": false,
|
||||
"name": "TypedEnumClass",
|
||||
"type": "char",
|
||||
"values": [
|
||||
"C0",
|
||||
"C1",
|
||||
"C2",
|
||||
"C3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"isClass": false,
|
||||
"isFlag": false,
|
||||
"name": "NormalEnum",
|
||||
"values": [
|
||||
"D2",
|
||||
"D3",
|
||||
"D0",
|
||||
"D1"
|
||||
]
|
||||
}
|
||||
],
|
||||
"object": true,
|
||||
"qualifiedClassName": "CXX11Enums3",
|
||||
"superClasses": [
|
||||
{
|
||||
"access": "public",
|
||||
"name": "QObject"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputFile": "cxx11-enums.h",
|
||||
|
@ -47,4 +47,20 @@ public:
|
||||
Q_FLAGS(ClassFlags)
|
||||
};
|
||||
|
||||
class CXX11Enums3 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class EnumClass { A0, A1, A2, A3 };
|
||||
enum TypedEnum : char { B0, B1 , B2, B3 };
|
||||
enum class TypedEnumClass : char { C0, C1, C2, C3 };
|
||||
enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
|
||||
enum class ClassFlag { F0 = 1, F1 = 2, F2 = 4, F3 = 8 };
|
||||
|
||||
Q_ENUM(EnumClass)
|
||||
Q_ENUM(TypedEnum)
|
||||
Q_ENUM(TypedEnumClass)
|
||||
Q_ENUM(NormalEnum)
|
||||
};
|
||||
|
||||
#endif // CXX11_ENUMS_H
|
||||
|
@ -98,6 +98,12 @@ public:
|
||||
Key2
|
||||
};
|
||||
Q_ENUM(TestGEnum2)
|
||||
|
||||
enum TestGEnum3: quint8 {
|
||||
Key1 = 23,
|
||||
Key2
|
||||
};
|
||||
Q_ENUM(TestGEnum3)
|
||||
};
|
||||
|
||||
}
|
||||
@ -116,6 +122,12 @@ namespace TestQNamespace {
|
||||
};
|
||||
Q_ENUM_NS(TestEnum2)
|
||||
|
||||
enum TestEnum3: qint8 {
|
||||
Key1 = 23,
|
||||
Key2
|
||||
};
|
||||
Q_ENUM_NS(TestEnum3)
|
||||
|
||||
// try to dizzy moc by adding a struct in between
|
||||
struct TestGadget {
|
||||
Q_GADGET
|
||||
@ -128,8 +140,13 @@ namespace TestQNamespace {
|
||||
Key1 = 23,
|
||||
Key2
|
||||
};
|
||||
enum TestGEnum3: qint16 {
|
||||
Key1 = 33,
|
||||
Key2
|
||||
};
|
||||
Q_ENUM(TestGEnum1)
|
||||
Q_ENUM(TestGEnum2)
|
||||
Q_ENUM(TestGEnum3)
|
||||
};
|
||||
|
||||
struct TestGadgetExport {
|
||||
@ -146,6 +163,12 @@ namespace TestQNamespace {
|
||||
Key2
|
||||
};
|
||||
Q_ENUM(TestGeEnum2)
|
||||
enum TestGeEnum3: quint16 {
|
||||
Key1 = 26,
|
||||
Key2
|
||||
};
|
||||
Q_ENUM(TestGeEnum3)
|
||||
|
||||
};
|
||||
|
||||
enum class TestFlag1 {
|
||||
@ -2428,23 +2451,29 @@ void tst_Moc::cxx11Enums_data()
|
||||
QTest::addColumn<QByteArray>("enumName");
|
||||
QTest::addColumn<char>("prefix");
|
||||
QTest::addColumn<bool>("isScoped");
|
||||
QTest::addColumn<bool>("isTyped");
|
||||
|
||||
const QMetaObject *meta1 = &CXX11Enums::staticMetaObject;
|
||||
const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject;
|
||||
const QMetaObject *meta3 = &CXX11Enums3::staticMetaObject;
|
||||
|
||||
QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
|
||||
QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
|
||||
QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
|
||||
QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
|
||||
QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
|
||||
QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
|
||||
QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
|
||||
QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
|
||||
QTest::newRow("ClassFlags") << meta1 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
|
||||
QTest::newRow("ClassFlags 2") << meta2 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
|
||||
QTest::newRow("EnumStruct") << meta1 << QByteArray("EnumStruct") << QByteArray("EnumStruct") << 'G' << true;
|
||||
QTest::newRow("TypedEnumStruct") << meta1 << QByteArray("TypedEnumStruct") << QByteArray("TypedEnumStruct") << 'H' << true;
|
||||
QTest::newRow("StructFlags") << meta1 << QByteArray("StructFlags") << QByteArray("StructFlag") << 'I' << true;
|
||||
QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true << false;
|
||||
QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true << false;
|
||||
QTest::newRow("EnumClass 3") << meta3 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true << false;
|
||||
QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false << true;
|
||||
QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false << true;
|
||||
QTest::newRow("TypedEnum 3") << meta3 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false << true;
|
||||
QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true << true;
|
||||
QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true << true;
|
||||
QTest::newRow("TypedEnumClass 3") << meta3 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true << true;
|
||||
QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false << false;
|
||||
QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false << false;
|
||||
QTest::newRow("NormalEnum 3") << meta3 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false << false;
|
||||
QTest::newRow("ClassFlags") << meta1 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true << false;
|
||||
QTest::newRow("ClassFlags 2") << meta2 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true << false;
|
||||
QTest::newRow("EnumStruct") << meta1 << QByteArray("EnumStruct") << QByteArray("EnumStruct") << 'G' << true << false;
|
||||
QTest::newRow("TypedEnumStruct") << meta1 << QByteArray("TypedEnumStruct") << QByteArray("TypedEnumStruct") << 'H' << true << true;
|
||||
QTest::newRow("StructFlags") << meta1 << QByteArray("StructFlags") << QByteArray("StructFlag") << 'I' << true << false;
|
||||
}
|
||||
|
||||
void tst_Moc::cxx11Enums()
|
||||
@ -2456,24 +2485,39 @@ void tst_Moc::cxx11Enums()
|
||||
QFETCH(QByteArray, enumName);
|
||||
QFETCH(char, prefix);
|
||||
QFETCH(bool, isScoped);
|
||||
QFETCH(bool, isTyped);
|
||||
|
||||
int idx = meta->indexOfEnumerator(typeName);
|
||||
QVERIFY(idx != -1);
|
||||
QCOMPARE(meta->indexOfEnumerator(enumName), idx);
|
||||
|
||||
QCOMPARE(meta->enumerator(idx).enclosingMetaObject(), meta);
|
||||
QCOMPARE(meta->enumerator(idx).isValid(), true);
|
||||
QCOMPARE(meta->enumerator(idx).keyCount(), 4);
|
||||
QCOMPARE(meta->enumerator(idx).name(), typeName.constData());
|
||||
QCOMPARE(meta->enumerator(idx).enumName(), enumName.constData());
|
||||
bool isFlag = meta->enumerator(idx).isFlag();
|
||||
const QMetaEnum metaEnum = meta->enumerator(idx);
|
||||
QCOMPARE(metaEnum.enclosingMetaObject(), meta);
|
||||
QCOMPARE(metaEnum.isValid(), true);
|
||||
QCOMPARE(metaEnum.keyCount(), 4);
|
||||
QCOMPARE(metaEnum.name(), typeName.constData());
|
||||
QCOMPARE(metaEnum.enumName(), enumName.constData());
|
||||
|
||||
const QMetaType metaType = metaEnum.metaType();
|
||||
const bool isUnsigned = metaType.flags() & QMetaType::IsUnsignedEnumeration;
|
||||
if (isTyped) {
|
||||
QCOMPARE(metaType.sizeOf(), sizeof(char));
|
||||
QCOMPARE(isUnsigned, !std::is_signed_v<char>);
|
||||
} else if (isScoped) {
|
||||
QCOMPARE(metaType.sizeOf(), sizeof(int));
|
||||
QCOMPARE(isUnsigned, !std::is_signed_v<int>);
|
||||
} else {
|
||||
// underlying type is implementation defined
|
||||
}
|
||||
|
||||
bool isFlag = metaEnum.isFlag();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
QByteArray v = prefix + QByteArray::number(i);
|
||||
const int value = isFlag ? (1 << i) : i;
|
||||
QCOMPARE(meta->enumerator(idx).keyToValue(v), value);
|
||||
QCOMPARE(meta->enumerator(idx).valueToKey(value), v.constData());
|
||||
QCOMPARE(metaEnum.keyToValue(v), value);
|
||||
QCOMPARE(metaEnum.valueToKey(value), v.constData());
|
||||
}
|
||||
QCOMPARE(meta->enumerator(idx).isScoped(), isScoped);
|
||||
QCOMPARE(metaEnum.isScoped(), isScoped);
|
||||
}
|
||||
|
||||
void tst_Moc::cxx11TrailingReturn()
|
||||
@ -3994,10 +4038,12 @@ void tst_Moc::optionsFileError()
|
||||
}
|
||||
|
||||
static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name,
|
||||
const QList<QPair<QByteArray, int>> &keys)
|
||||
const QList<QPair<QByteArray, int>> &keys,
|
||||
const QMetaType underlyingType = QMetaType::fromType<int>())
|
||||
{
|
||||
QCOMPARE(name, QByteArray{enumerator.name()});
|
||||
QCOMPARE(keys.size(), enumerator.keyCount());
|
||||
QCOMPARE(underlyingType, enumerator.metaType().underlyingType());
|
||||
for (int i = 0; i < enumerator.keyCount(); ++i) {
|
||||
QCOMPARE(keys[i].first, QByteArray{enumerator.key(i)});
|
||||
QCOMPARE(keys[i].second, enumerator.value(i));
|
||||
@ -4014,27 +4060,33 @@ public:
|
||||
|
||||
void tst_Moc::testQNamespace()
|
||||
{
|
||||
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 4);
|
||||
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 5);
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(0), "TestEnum1",
|
||||
{{"Key1", 11}, {"Key2", 12}});
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(1), "TestEnum2",
|
||||
{{"Key1", 17}, {"Key2", 18}});
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(2), "TestFlag1",
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(2), "TestEnum3",
|
||||
{{"Key1", 23}, {"Key2", 24}}, QMetaType::fromType<qint8>());
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(3), "TestFlag1",
|
||||
{{"None", 0}, {"Flag1", 1}, {"Flag2", 2}, {"Any", 1 | 2}});
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(3), "TestFlag2",
|
||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(4), "TestFlag2",
|
||||
{{"None", 0}, {"Flag1", 4}, {"Flag2", 8}, {"Any", 4 | 8}});
|
||||
|
||||
QCOMPARE(TestQNamespace::TestGadget::staticMetaObject.enumeratorCount(), 2);
|
||||
QCOMPARE(TestQNamespace::TestGadget::staticMetaObject.enumeratorCount(), 3);
|
||||
checkEnum(TestQNamespace::TestGadget::staticMetaObject.enumerator(0), "TestGEnum1",
|
||||
{{"Key1", 13}, {"Key2", 14}});
|
||||
checkEnum(TestQNamespace::TestGadget::staticMetaObject.enumerator(1), "TestGEnum2",
|
||||
{{"Key1", 23}, {"Key2", 24}});
|
||||
checkEnum(TestQNamespace::TestGadget::staticMetaObject.enumerator(2), "TestGEnum3",
|
||||
{{"Key1", 33}, {"Key2", 34}}, QMetaType::fromType<qint16>());
|
||||
|
||||
QCOMPARE(TestQNamespace::TestGadgetExport::staticMetaObject.enumeratorCount(), 2);
|
||||
QCOMPARE(TestQNamespace::TestGadgetExport::staticMetaObject.enumeratorCount(), 3);
|
||||
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(0), "TestGeEnum1",
|
||||
{{"Key1", 20}, {"Key2", 21}});
|
||||
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(1), "TestGeEnum2",
|
||||
{{"Key1", 23}, {"Key2", 24}});
|
||||
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(2), "TestGeEnum3",
|
||||
{{"Key1", 26}, {"Key2", 27}}, QMetaType::fromType<quint16>());
|
||||
|
||||
QMetaEnum meta = QMetaEnum::fromType<TestQNamespace::TestEnum1>();
|
||||
QVERIFY(meta.isValid());
|
||||
|
Loading…
x
Reference in New Issue
Block a user