moc: keep the enum/class/struct C++ type tag in properties

ActiveQt dumpcpp could use this so
        Q_PROPERTY(class Accounts *Accounts READ Accounts)

can compile. moc will now generate:
    QtMocHelpers::UintData qt_properties {
        // property 'Accounts'
        QtMocHelpers::PropertyData<class Accounts*>(1, 0x80000000 | 2, QMC::DefaultPropertyFlags | QMC::EnumOrFlag),
    };

    if (_c == QMetaObject::RegisterPropertyMetaType) {
        switch (_id) {
        default: *reinterpret_cast<int*>(_a[0]) = -1; break;
        case 0:
            *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< class Accounts* >(); break;
        }
    }
    if (_c == QMetaObject::ReadProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: *reinterpret_cast<class Accounts**>(_v) = _t->Accounts(); break;
        default: break;
        }
    }

Change-Id: Ibb85c3a067054d017b05fffdbd500f302f655bd9
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira 2024-10-07 21:27:42 -07:00
parent 8fabcb642f
commit ea3288c9b6
3 changed files with 57 additions and 20 deletions

View File

@ -35,6 +35,20 @@ uint nameToBuiltinType(const QByteArray &name)
return tp < uint(QMetaType::User) ? tp : uint(QMetaType::UnknownType); return tp < uint(QMetaType::User) ? tp : uint(QMetaType::UnknownType);
} }
constexpr const char *cxxTypeTag(TypeTags t)
{
if (t & TypeTag::HasEnum) {
if (t & TypeTag::HasClass)
return "enum class ";
if (t & TypeTag::HasStruct)
return "enum struct ";
return "enum ";
}
if (t & TypeTag::HasClass) return "class ";
if (t & TypeTag::HasStruct) return "struct ";
return "";
}
/* /*
Returns \c true if the type is a built-in type. Returns \c true if the type is a built-in type.
*/ */
@ -710,8 +724,8 @@ void Generator::addProperties()
{ {
for (const PropertyDef &p : std::as_const(cdef->propertyList)) { for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
fprintf(out, " // property '%s'\n" fprintf(out, " // property '%s'\n"
" QtMocHelpers::PropertyData<%s>(%d, ", " QtMocHelpers::PropertyData<%s%s>(%d, ",
p.name.constData(), p.type.constData(), stridx(p.name)); p.name.constData(), cxxTypeTag(p.typeTag), p.type.constData(), stridx(p.name));
generateTypeInfo(p.type); generateTypeInfo(p.type);
fputc(',', out); fputc(',', out);
@ -888,9 +902,10 @@ QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper()
{ {
QMultiMap<QByteArray, int> automaticPropertyMetaTypes; QMultiMap<QByteArray, int> automaticPropertyMetaTypes;
for (int i = 0; i < int(cdef->propertyList.size()); ++i) { for (int i = 0; i < int(cdef->propertyList.size()); ++i) {
const QByteArray propertyType = cdef->propertyList.at(i).type; const PropertyDef &p = cdef->propertyList.at(i);
const QByteArray propertyType = p.type;
if (registerableMetaType(propertyType) && !isBuiltinType(propertyType)) if (registerableMetaType(propertyType) && !isBuiltinType(propertyType))
automaticPropertyMetaTypes.insert(propertyType, i); automaticPropertyMetaTypes.insert(cxxTypeTag(p.typeTag) + propertyType, i);
} }
return automaticPropertyMetaTypes; return automaticPropertyMetaTypes;
} }
@ -1157,14 +1172,17 @@ void Generator::generateStaticMetacall()
propindex, p.type.constData(), prefix.constData(), p.read.constData()); propindex, p.type.constData(), prefix.constData(), p.read.constData());
#endif #endif
else if (p.read == "default") else if (p.read == "default")
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s().value(); break;\n", fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s().value(); break;\n",
propindex, p.type.constData(), prefix.constData(), p.bind.constData()); propindex, cxxTypeTag(p.typeTag), p.type.constData(),
prefix.constData(), p.bind.constData());
else if (!p.read.isEmpty()) else if (!p.read.isEmpty())
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n", fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s(); break;\n",
propindex, p.type.constData(), prefix.constData(), p.read.constData()); propindex, cxxTypeTag(p.typeTag), p.type.constData(),
prefix.constData(), p.read.constData());
else else
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n", fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s; break;\n",
propindex, p.type.constData(), prefix.constData(), p.member.constData()); propindex, cxxTypeTag(p.typeTag), p.type.constData(),
prefix.constData(), p.member.constData());
} }
fprintf(out, " default: break;\n"); fprintf(out, " default: break;\n");
fprintf(out, " }\n"); fprintf(out, " }\n");
@ -1187,21 +1205,22 @@ void Generator::generateStaticMetacall()
} }
if (p.write == "default") { if (p.write == "default") {
fprintf(out, " case %d: {\n", propindex); fprintf(out, " case %d: {\n", propindex);
fprintf(out, " %s%s().setValue(*reinterpret_cast< %s*>(_v));\n", fprintf(out, " %s%s().setValue(*reinterpret_cast<%s%s*>(_v));\n",
prefix.constData(), p.bind.constData(), p.type.constData()); prefix.constData(), p.bind.constData(), cxxTypeTag(p.typeTag), p.type.constData());
fprintf(out, " break;\n"); fprintf(out, " break;\n");
fprintf(out, " }\n"); fprintf(out, " }\n");
} else if (!p.write.isEmpty()) { } else if (!p.write.isEmpty()) {
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n", fprintf(out, " case %d: %s%s(*reinterpret_cast<%s%s*>(_v)); break;\n",
propindex, prefix.constData(), p.write.constData(), p.type.constData()); propindex, prefix.constData(), p.write.constData(),
cxxTypeTag(p.typeTag), p.type.constData());
} else { } else {
fprintf(out, " case %d:", propindex); fprintf(out, " case %d:", propindex);
if (p.notify.isEmpty()) { if (p.notify.isEmpty()) {
fprintf(out, " QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s*>(_v)); break;\n", fprintf(out, " QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s%s*>(_v)); break;\n",
prefix.constData(), p.member.constData(), p.type.constData()); prefix.constData(), p.member.constData(), cxxTypeTag(p.typeTag), p.type.constData());
} else { } else {
fprintf(out, "\n if (QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s*>(_v)))\n", fprintf(out, "\n if (QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s%s*>(_v)))\n",
prefix.constData(), p.member.constData(), p.type.constData()); prefix.constData(), p.member.constData(), cxxTypeTag(p.typeTag), p.type.constData());
fprintf(out, " Q_EMIT _t->%s(", p.notify.constData()); fprintf(out, " Q_EMIT _t->%s(", p.notify.constData());
if (p.notifyId > -1) { if (p.notifyId > -1) {
const FunctionDef &f = cdef->signalList.at(p.notifyId); const FunctionDef &f = cdef->signalList.at(p.notifyId);

View File

@ -162,7 +162,12 @@ Type Moc::parseType()
} }
skipCxxAttributes(); skipCxxAttributes();
test(ENUM) || test(CLASS) || test(STRUCT); if (test(ENUM))
type.typeTag = TypeTag::HasEnum;
if (test(CLASS))
type.typeTag |= TypeTag::HasClass;
if (test(STRUCT))
type.typeTag |= TypeTag::HasStruct;
for(;;) { for(;;) {
skipCxxAttributes(); skipCxxAttributes();
switch (next()) { switch (next()) {
@ -1326,9 +1331,11 @@ void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex, Moc::Proper
propDef.location = index; propDef.location = index;
propDef.relativeIndex = propertyIndex; propDef.relativeIndex = propertyIndex;
QByteArray type = parseType().name; Type t = parseType();
QByteArray type = t.name;
if (type.isEmpty()) if (type.isEmpty())
error(); error();
propDef.typeTag = t.typeTag;
propDef.designable = propDef.scriptable = propDef.stored = "true"; propDef.designable = propDef.scriptable = propDef.stored = "true";
propDef.user = "false"; propDef.user = "false";
/* /*

View File

@ -20,6 +20,15 @@ QT_BEGIN_NAMESPACE
struct QMetaObject; struct QMetaObject;
enum class TypeTag : uchar {
None,
HasStruct = 0x01,
HasClass = 0x02,
HasEnum = 0x04,
};
Q_DECLARE_FLAGS(TypeTags, TypeTag)
Q_DECLARE_OPERATORS_FOR_FLAGS(TypeTags)
struct Type struct Type
{ {
enum ReferenceType { NoReference, Reference, RValueReference, Pointer }; enum ReferenceType { NoReference, Reference, RValueReference, Pointer };
@ -33,6 +42,7 @@ struct Type
QByteArray rawName; QByteArray rawName;
uint isVolatile : 1; uint isVolatile : 1;
uint isScoped : 1; uint isScoped : 1;
TypeTags typeTag;
Token firstToken; Token firstToken;
ReferenceType referenceType; ReferenceType referenceType;
}; };
@ -116,6 +126,7 @@ struct PropertyDef
enum Specification { ValueSpec, ReferenceSpec, PointerSpec }; enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
Specification gspec = ValueSpec; Specification gspec = ValueSpec;
int revision = 0; int revision = 0;
TypeTags typeTag;
bool constant = false; bool constant = false;
bool final = false; bool final = false;
bool required = false; bool required = false;