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());
|
return QMetaType::fromName(className());
|
||||||
} else {
|
} else {
|
||||||
/* in the metatype array, we store
|
/* in the metatype array, we store
|
||||||
idx: 0 propertyCount - 1 propertyCount
|
|
||||||
data:QMetaType(prop0), ..., QMetaType(propPropCount-1), QMetaType(class),...
|
| index | data |
|
||||||
|
|----------------------------------------------------------------------|
|
||||||
|
| 0 | QMetaType(property0) |
|
||||||
|
| ... | ... |
|
||||||
|
| propertyCount - 1 | QMetaType(propertyCount - 1) |
|
||||||
|
| propertyCount | QMetaType(enumerator0) |
|
||||||
|
| ... | ... |
|
||||||
|
| propertyCount + enumeratorCount - 1 | QMetaType(enumeratorCount - 1) |
|
||||||
|
| propertyCount + enumeratorCount | QMetaType(class) |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
auto iface = this->d.metaTypes[d->propertyCount];
|
#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))
|
if (iface && QtMetaTypePrivate::isInterfaceFor<void>(iface))
|
||||||
return QMetaType(); // return invalid meta-type for namespaces
|
return QMetaType(); // return invalid meta-type for namespaces
|
||||||
if (iface)
|
if (iface)
|
||||||
@ -3036,6 +3056,33 @@ const char *QMetaEnum::enumName() const
|
|||||||
return rawStringData(mobj, data.alias());
|
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.
|
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);
|
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()
|
\fn QMetaEnum QMetaEnum::fromType()
|
||||||
\since 5.5
|
\since 5.5
|
||||||
|
@ -265,6 +265,8 @@ public:
|
|||||||
|
|
||||||
const char *name() const;
|
const char *name() const;
|
||||||
const char *enumName() const;
|
const char *enumName() const;
|
||||||
|
QMetaType metaType() const;
|
||||||
|
|
||||||
bool isFlag() const;
|
bool isFlag() const;
|
||||||
bool isScoped() const;
|
bool isScoped() const;
|
||||||
|
|
||||||
@ -302,6 +304,7 @@ private:
|
|||||||
quint32 flags() const { return d[2]; }
|
quint32 flags() const { return d[2]; }
|
||||||
qint32 keyCount() const { return static_cast<qint32>(d[3]); }
|
qint32 keyCount() const { return static_cast<qint32>(d[3]); }
|
||||||
quint32 data() const { return d[4]; }
|
quint32 data() const { return d[4]; }
|
||||||
|
int index(const QMetaObject *mobj) const;
|
||||||
|
|
||||||
const uint *d;
|
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
|
// 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
|
// 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
|
// 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 { IntsPerMethod = QMetaMethod::Data::Size };
|
||||||
enum { IntsPerEnum = QMetaEnum::Data::Size };
|
enum { IntsPerEnum = QMetaEnum::Data::Size };
|
||||||
enum { IntsPerProperty = QMetaProperty::Data::Size };
|
enum { IntsPerProperty = QMetaProperty::Data::Size };
|
||||||
|
@ -159,6 +159,7 @@ public:
|
|||||||
|
|
||||||
QByteArray name;
|
QByteArray name;
|
||||||
QByteArray enumName;
|
QByteArray enumName;
|
||||||
|
QMetaType metaType;
|
||||||
bool isFlag;
|
bool isFlag;
|
||||||
bool isScoped;
|
bool isScoped;
|
||||||
QList<QByteArray> keys;
|
QList<QByteArray> keys;
|
||||||
@ -597,6 +598,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum &prototype)
|
|||||||
{
|
{
|
||||||
QMetaEnumBuilder en = addEnumerator(prototype.name());
|
QMetaEnumBuilder en = addEnumerator(prototype.name());
|
||||||
en.setEnumName(prototype.enumName());
|
en.setEnumName(prototype.enumName());
|
||||||
|
en.setMetaType(prototype.metaType());
|
||||||
en.setIsFlag(prototype.isFlag());
|
en.setIsFlag(prototype.isFlag());
|
||||||
en.setIsScoped(prototype.isScoped());
|
en.setIsScoped(prototype.isScoped());
|
||||||
int count = prototype.keyCount();
|
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->methods.size()) // return "parameters" don't have names
|
||||||
- int(d->constructors.size()); // "this" parameters don't have names
|
- int(d->constructors.size()); // "this" parameters don't have names
|
||||||
if constexpr (mode == Construct) {
|
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->revision = QMetaObjectPrivate::OutputRevision;
|
||||||
pmeta->flags = d->flags.toInt();
|
pmeta->flags = d->flags.toInt();
|
||||||
pmeta->className = 0; // Class name is always the first string.
|
pmeta->className = 0; // Class name is always the first string.
|
||||||
@ -2305,6 +2307,31 @@ void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
|
|||||||
d->enumName = 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
|
Returns \c true if this enumerator is used as a flag; otherwise returns
|
||||||
false.
|
false.
|
||||||
|
@ -258,6 +258,9 @@ public:
|
|||||||
QByteArray enumName() const;
|
QByteArray enumName() const;
|
||||||
void setEnumName(const QByteArray &alias);
|
void setEnumName(const QByteArray &alias);
|
||||||
|
|
||||||
|
QMetaType metaType() const;
|
||||||
|
void setMetaType(QMetaType metaType);
|
||||||
|
|
||||||
bool isFlag() const;
|
bool isFlag() const;
|
||||||
void setIsFlag(bool value);
|
void setIsFlag(bool value);
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
|||||||
- methods.size(); // ditto
|
- methods.size(); // ditto
|
||||||
|
|
||||||
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
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->revision = QMetaObjectPrivate::OutputRevision;
|
||||||
header->className = 0;
|
header->className = 0;
|
||||||
header->classInfoCount = 0;
|
header->classInfoCount = 0;
|
||||||
|
@ -378,7 +378,7 @@ void Generator::generateCode()
|
|||||||
|
|
||||||
int enumsIndex = index;
|
int enumsIndex = index;
|
||||||
for (int i = 0; i < cdef->enumList.size(); ++i)
|
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,
|
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? int(cdef->constructorList.size()) : 0,
|
||||||
isConstructible ? index : 0);
|
isConstructible ? index : 0);
|
||||||
|
|
||||||
@ -397,8 +397,8 @@ void Generator::generateCode()
|
|||||||
//
|
//
|
||||||
generateClassInfos();
|
generateClassInfos();
|
||||||
|
|
||||||
// all property metatypes, + 1 for the type of the current class itself
|
// all property metatypes + all enum metatypes + 1 for the type of the current class itself
|
||||||
int initialMetaTypeOffset = cdef->propertyList.size() + 1;
|
int initialMetaTypeOffset = cdef->propertyList.size() + cdef->enumList.size() + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Build signals array first, otherwise the signal indices would be wrong
|
// Build signals array first, otherwise the signal indices would be wrong
|
||||||
@ -576,6 +576,15 @@ void Generator::generateCode()
|
|||||||
comma = ",";
|
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
|
// type name for the Q_OJBECT/GADGET itself, void for namespaces
|
||||||
auto ownType = !cdef->hasQNamespace ? cdef->classname.data() : "void";
|
auto ownType = !cdef->hasQNamespace ? cdef->classname.data() : "void";
|
||||||
fprintf(out, "%s\n // Q_OBJECT / Q_GADGET\n %s",
|
fprintf(out, "%s\n // Q_OBJECT / Q_GADGET\n %s",
|
||||||
@ -943,7 +952,7 @@ void Generator::generateEnums(int index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(out, "\n // enums: name, alias, flags, count, data\n");
|
fprintf(out, "\n // enums: name, alias, flags, count, data\n");
|
||||||
index += 5 * cdef->enumList.size();
|
index += QMetaObjectPrivate::IntsPerEnum * cdef->enumList.size();
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < cdef->enumList.size(); ++i) {
|
for (i = 0; i < cdef->enumList.size(); ++i) {
|
||||||
const EnumDef &e = cdef->enumList.at(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
|
if (test(COLON)) { // C++11 strongly typed enum
|
||||||
// enum Foo : unsigned long { ... };
|
// enum Foo : unsigned long { ... };
|
||||||
parseType(); //ignore the result
|
def->type = normalizeType(parseType().name);
|
||||||
}
|
}
|
||||||
if (!test(LBRACE))
|
if (!test(LBRACE))
|
||||||
return false;
|
return false;
|
||||||
@ -2107,6 +2107,8 @@ QJsonObject EnumDef::toJson(const ClassDef &cdef) const
|
|||||||
def["name"_L1] = QString::fromUtf8(name);
|
def["name"_L1] = QString::fromUtf8(name);
|
||||||
if (!enumName.isEmpty())
|
if (!enumName.isEmpty())
|
||||||
def["alias"_L1] = QString::fromUtf8(enumName);
|
def["alias"_L1] = QString::fromUtf8(enumName);
|
||||||
|
if (!type.isEmpty())
|
||||||
|
def["type"_L1] = QString::fromUtf8(type);
|
||||||
def["isFlag"_L1] = cdef.enumDeclarations.value(name);
|
def["isFlag"_L1] = cdef.enumDeclarations.value(name);
|
||||||
def["isClass"_L1] = isEnumClass;
|
def["isClass"_L1] = isEnumClass;
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ struct EnumDef
|
|||||||
{
|
{
|
||||||
QByteArray name;
|
QByteArray name;
|
||||||
QByteArray enumName;
|
QByteArray enumName;
|
||||||
|
QByteArray type;
|
||||||
QList<QByteArray> values;
|
QList<QByteArray> values;
|
||||||
bool isEnumClass; // c++11 enum class
|
bool isEnumClass; // c++11 enum class
|
||||||
EnumDef() : isEnumClass(false) {}
|
EnumDef() : isEnumClass(false) {}
|
||||||
|
@ -779,6 +779,26 @@ void tst_QMetaObjectBuilder::notifySignal()
|
|||||||
|
|
||||||
void tst_QMetaObjectBuilder::enumerator()
|
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;
|
QMetaObjectBuilder builder;
|
||||||
|
|
||||||
// Add an enumerator and check its attributes.
|
// Add an enumerator and check its attributes.
|
||||||
@ -810,6 +830,7 @@ void tst_QMetaObjectBuilder::enumerator()
|
|||||||
enum1.setIsFlag(true);
|
enum1.setIsFlag(true);
|
||||||
enum1.setIsScoped(true);
|
enum1.setIsScoped(true);
|
||||||
enum1.setEnumName(QByteArrayLiteral("fooFlag"));
|
enum1.setEnumName(QByteArrayLiteral("fooFlag"));
|
||||||
|
enum1.setMetaType(QMetaType(&fooFlagMetaType));
|
||||||
QCOMPARE(enum1.addKey("ABC", 0), 0);
|
QCOMPARE(enum1.addKey("ABC", 0), 0);
|
||||||
QCOMPARE(enum1.addKey("DEF", 1), 1);
|
QCOMPARE(enum1.addKey("DEF", 1), 1);
|
||||||
QCOMPARE(enum1.addKey("GHI", -1), 2);
|
QCOMPARE(enum1.addKey("GHI", -1), 2);
|
||||||
@ -819,6 +840,7 @@ void tst_QMetaObjectBuilder::enumerator()
|
|||||||
QVERIFY(enum1.isFlag());
|
QVERIFY(enum1.isFlag());
|
||||||
QVERIFY(enum1.isScoped());
|
QVERIFY(enum1.isScoped());
|
||||||
QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
|
QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
|
||||||
|
QCOMPARE(enum1.metaType(), QMetaType(&fooFlagMetaType));
|
||||||
QCOMPARE(enum1.keyCount(), 3);
|
QCOMPARE(enum1.keyCount(), 3);
|
||||||
QCOMPARE(enum1.index(), 0);
|
QCOMPARE(enum1.index(), 0);
|
||||||
QCOMPARE(enum1.key(0), QByteArray("ABC"));
|
QCOMPARE(enum1.key(0), QByteArray("ABC"));
|
||||||
|
@ -91,6 +91,7 @@
|
|||||||
"isClass": false,
|
"isClass": false,
|
||||||
"isFlag": false,
|
"isFlag": false,
|
||||||
"name": "TypedEnum",
|
"name": "TypedEnum",
|
||||||
|
"type": "char",
|
||||||
"values": [
|
"values": [
|
||||||
"B0",
|
"B0",
|
||||||
"B1",
|
"B1",
|
||||||
@ -102,6 +103,7 @@
|
|||||||
"isClass": true,
|
"isClass": true,
|
||||||
"isFlag": false,
|
"isFlag": false,
|
||||||
"name": "TypedEnumClass",
|
"name": "TypedEnumClass",
|
||||||
|
"type": "char",
|
||||||
"values": [
|
"values": [
|
||||||
"C0",
|
"C0",
|
||||||
"C1",
|
"C1",
|
||||||
@ -147,6 +149,7 @@
|
|||||||
"isClass": true,
|
"isClass": true,
|
||||||
"isFlag": false,
|
"isFlag": false,
|
||||||
"name": "TypedEnumStruct",
|
"name": "TypedEnumStruct",
|
||||||
|
"type": "char",
|
||||||
"values": [
|
"values": [
|
||||||
"H0",
|
"H0",
|
||||||
"H1",
|
"H1",
|
||||||
@ -188,6 +191,7 @@
|
|||||||
"isClass": false,
|
"isClass": false,
|
||||||
"isFlag": false,
|
"isFlag": false,
|
||||||
"name": "TypedEnum",
|
"name": "TypedEnum",
|
||||||
|
"type": "char",
|
||||||
"values": [
|
"values": [
|
||||||
"B0",
|
"B0",
|
||||||
"B1",
|
"B1",
|
||||||
@ -199,6 +203,7 @@
|
|||||||
"isClass": true,
|
"isClass": true,
|
||||||
"isFlag": false,
|
"isFlag": false,
|
||||||
"name": "TypedEnumClass",
|
"name": "TypedEnumClass",
|
||||||
|
"type": "char",
|
||||||
"values": [
|
"values": [
|
||||||
"C0",
|
"C0",
|
||||||
"C1",
|
"C1",
|
||||||
@ -232,6 +237,65 @@
|
|||||||
],
|
],
|
||||||
"gadget": true,
|
"gadget": true,
|
||||||
"qualifiedClassName": "CXX11Enums2"
|
"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",
|
"inputFile": "cxx11-enums.h",
|
||||||
|
@ -47,4 +47,20 @@ public:
|
|||||||
Q_FLAGS(ClassFlags)
|
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
|
#endif // CXX11_ENUMS_H
|
||||||
|
@ -98,6 +98,12 @@ public:
|
|||||||
Key2
|
Key2
|
||||||
};
|
};
|
||||||
Q_ENUM(TestGEnum2)
|
Q_ENUM(TestGEnum2)
|
||||||
|
|
||||||
|
enum TestGEnum3: quint8 {
|
||||||
|
Key1 = 23,
|
||||||
|
Key2
|
||||||
|
};
|
||||||
|
Q_ENUM(TestGEnum3)
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -116,6 +122,12 @@ namespace TestQNamespace {
|
|||||||
};
|
};
|
||||||
Q_ENUM_NS(TestEnum2)
|
Q_ENUM_NS(TestEnum2)
|
||||||
|
|
||||||
|
enum TestEnum3: qint8 {
|
||||||
|
Key1 = 23,
|
||||||
|
Key2
|
||||||
|
};
|
||||||
|
Q_ENUM_NS(TestEnum3)
|
||||||
|
|
||||||
// try to dizzy moc by adding a struct in between
|
// try to dizzy moc by adding a struct in between
|
||||||
struct TestGadget {
|
struct TestGadget {
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
@ -128,8 +140,13 @@ namespace TestQNamespace {
|
|||||||
Key1 = 23,
|
Key1 = 23,
|
||||||
Key2
|
Key2
|
||||||
};
|
};
|
||||||
|
enum TestGEnum3: qint16 {
|
||||||
|
Key1 = 33,
|
||||||
|
Key2
|
||||||
|
};
|
||||||
Q_ENUM(TestGEnum1)
|
Q_ENUM(TestGEnum1)
|
||||||
Q_ENUM(TestGEnum2)
|
Q_ENUM(TestGEnum2)
|
||||||
|
Q_ENUM(TestGEnum3)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestGadgetExport {
|
struct TestGadgetExport {
|
||||||
@ -146,6 +163,12 @@ namespace TestQNamespace {
|
|||||||
Key2
|
Key2
|
||||||
};
|
};
|
||||||
Q_ENUM(TestGeEnum2)
|
Q_ENUM(TestGeEnum2)
|
||||||
|
enum TestGeEnum3: quint16 {
|
||||||
|
Key1 = 26,
|
||||||
|
Key2
|
||||||
|
};
|
||||||
|
Q_ENUM(TestGeEnum3)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TestFlag1 {
|
enum class TestFlag1 {
|
||||||
@ -2428,23 +2451,29 @@ void tst_Moc::cxx11Enums_data()
|
|||||||
QTest::addColumn<QByteArray>("enumName");
|
QTest::addColumn<QByteArray>("enumName");
|
||||||
QTest::addColumn<char>("prefix");
|
QTest::addColumn<char>("prefix");
|
||||||
QTest::addColumn<bool>("isScoped");
|
QTest::addColumn<bool>("isScoped");
|
||||||
|
QTest::addColumn<bool>("isTyped");
|
||||||
|
|
||||||
const QMetaObject *meta1 = &CXX11Enums::staticMetaObject;
|
const QMetaObject *meta1 = &CXX11Enums::staticMetaObject;
|
||||||
const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject;
|
const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject;
|
||||||
|
const QMetaObject *meta3 = &CXX11Enums3::staticMetaObject;
|
||||||
|
|
||||||
QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
|
QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true << false;
|
||||||
QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
|
QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true << false;
|
||||||
QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
|
QTest::newRow("EnumClass 3") << meta3 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true << false;
|
||||||
QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
|
QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false << true;
|
||||||
QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
|
QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false << true;
|
||||||
QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
|
QTest::newRow("TypedEnum 3") << meta3 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false << true;
|
||||||
QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
|
QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true << true;
|
||||||
QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
|
QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true << true;
|
||||||
QTest::newRow("ClassFlags") << meta1 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
|
QTest::newRow("TypedEnumClass 3") << meta3 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true << true;
|
||||||
QTest::newRow("ClassFlags 2") << meta2 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
|
QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false << false;
|
||||||
QTest::newRow("EnumStruct") << meta1 << QByteArray("EnumStruct") << QByteArray("EnumStruct") << 'G' << true;
|
QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false << false;
|
||||||
QTest::newRow("TypedEnumStruct") << meta1 << QByteArray("TypedEnumStruct") << QByteArray("TypedEnumStruct") << 'H' << true;
|
QTest::newRow("NormalEnum 3") << meta3 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false << false;
|
||||||
QTest::newRow("StructFlags") << meta1 << QByteArray("StructFlags") << QByteArray("StructFlag") << 'I' << true;
|
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()
|
void tst_Moc::cxx11Enums()
|
||||||
@ -2456,24 +2485,39 @@ void tst_Moc::cxx11Enums()
|
|||||||
QFETCH(QByteArray, enumName);
|
QFETCH(QByteArray, enumName);
|
||||||
QFETCH(char, prefix);
|
QFETCH(char, prefix);
|
||||||
QFETCH(bool, isScoped);
|
QFETCH(bool, isScoped);
|
||||||
|
QFETCH(bool, isTyped);
|
||||||
|
|
||||||
int idx = meta->indexOfEnumerator(typeName);
|
int idx = meta->indexOfEnumerator(typeName);
|
||||||
QVERIFY(idx != -1);
|
QVERIFY(idx != -1);
|
||||||
QCOMPARE(meta->indexOfEnumerator(enumName), idx);
|
QCOMPARE(meta->indexOfEnumerator(enumName), idx);
|
||||||
|
|
||||||
QCOMPARE(meta->enumerator(idx).enclosingMetaObject(), meta);
|
const QMetaEnum metaEnum = meta->enumerator(idx);
|
||||||
QCOMPARE(meta->enumerator(idx).isValid(), true);
|
QCOMPARE(metaEnum.enclosingMetaObject(), meta);
|
||||||
QCOMPARE(meta->enumerator(idx).keyCount(), 4);
|
QCOMPARE(metaEnum.isValid(), true);
|
||||||
QCOMPARE(meta->enumerator(idx).name(), typeName.constData());
|
QCOMPARE(metaEnum.keyCount(), 4);
|
||||||
QCOMPARE(meta->enumerator(idx).enumName(), enumName.constData());
|
QCOMPARE(metaEnum.name(), typeName.constData());
|
||||||
bool isFlag = meta->enumerator(idx).isFlag();
|
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++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
QByteArray v = prefix + QByteArray::number(i);
|
QByteArray v = prefix + QByteArray::number(i);
|
||||||
const int value = isFlag ? (1 << i) : i;
|
const int value = isFlag ? (1 << i) : i;
|
||||||
QCOMPARE(meta->enumerator(idx).keyToValue(v), value);
|
QCOMPARE(metaEnum.keyToValue(v), value);
|
||||||
QCOMPARE(meta->enumerator(idx).valueToKey(value), v.constData());
|
QCOMPARE(metaEnum.valueToKey(value), v.constData());
|
||||||
}
|
}
|
||||||
QCOMPARE(meta->enumerator(idx).isScoped(), isScoped);
|
QCOMPARE(metaEnum.isScoped(), isScoped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_Moc::cxx11TrailingReturn()
|
void tst_Moc::cxx11TrailingReturn()
|
||||||
@ -3994,10 +4038,12 @@ void tst_Moc::optionsFileError()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name,
|
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(name, QByteArray{enumerator.name()});
|
||||||
QCOMPARE(keys.size(), enumerator.keyCount());
|
QCOMPARE(keys.size(), enumerator.keyCount());
|
||||||
|
QCOMPARE(underlyingType, enumerator.metaType().underlyingType());
|
||||||
for (int i = 0; i < enumerator.keyCount(); ++i) {
|
for (int i = 0; i < enumerator.keyCount(); ++i) {
|
||||||
QCOMPARE(keys[i].first, QByteArray{enumerator.key(i)});
|
QCOMPARE(keys[i].first, QByteArray{enumerator.key(i)});
|
||||||
QCOMPARE(keys[i].second, enumerator.value(i));
|
QCOMPARE(keys[i].second, enumerator.value(i));
|
||||||
@ -4014,27 +4060,33 @@ public:
|
|||||||
|
|
||||||
void tst_Moc::testQNamespace()
|
void tst_Moc::testQNamespace()
|
||||||
{
|
{
|
||||||
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 4);
|
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 5);
|
||||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(0), "TestEnum1",
|
checkEnum(TestQNamespace::staticMetaObject.enumerator(0), "TestEnum1",
|
||||||
{{"Key1", 11}, {"Key2", 12}});
|
{{"Key1", 11}, {"Key2", 12}});
|
||||||
checkEnum(TestQNamespace::staticMetaObject.enumerator(1), "TestEnum2",
|
checkEnum(TestQNamespace::staticMetaObject.enumerator(1), "TestEnum2",
|
||||||
{{"Key1", 17}, {"Key2", 18}});
|
{{"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}});
|
{{"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}});
|
{{"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",
|
checkEnum(TestQNamespace::TestGadget::staticMetaObject.enumerator(0), "TestGEnum1",
|
||||||
{{"Key1", 13}, {"Key2", 14}});
|
{{"Key1", 13}, {"Key2", 14}});
|
||||||
checkEnum(TestQNamespace::TestGadget::staticMetaObject.enumerator(1), "TestGEnum2",
|
checkEnum(TestQNamespace::TestGadget::staticMetaObject.enumerator(1), "TestGEnum2",
|
||||||
{{"Key1", 23}, {"Key2", 24}});
|
{{"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",
|
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(0), "TestGeEnum1",
|
||||||
{{"Key1", 20}, {"Key2", 21}});
|
{{"Key1", 20}, {"Key2", 21}});
|
||||||
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(1), "TestGeEnum2",
|
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(1), "TestGeEnum2",
|
||||||
{{"Key1", 23}, {"Key2", 24}});
|
{{"Key1", 23}, {"Key2", 24}});
|
||||||
|
checkEnum(TestQNamespace::TestGadgetExport::staticMetaObject.enumerator(2), "TestGeEnum3",
|
||||||
|
{{"Key1", 26}, {"Key2", 27}}, QMetaType::fromType<quint16>());
|
||||||
|
|
||||||
QMetaEnum meta = QMetaEnum::fromType<TestQNamespace::TestEnum1>();
|
QMetaEnum meta = QMetaEnum::fromType<TestQNamespace::TestEnum1>();
|
||||||
QVERIFY(meta.isValid());
|
QVERIFY(meta.isValid());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user