Skip to content

Commit

Permalink
moc: keep the enum/class/struct C++ type tag in properties
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
thiagomacieira committed Nov 21, 2024
1 parent 8fabcb6 commit ea3288c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 20 deletions.
55 changes: 37 additions & 18 deletions src/tools/moc/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ uint nameToBuiltinType(const QByteArray &name)
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.
*/
Expand Down Expand Up @@ -710,8 +724,8 @@ void Generator::addProperties()
{
for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
fprintf(out, " // property '%s'\n"
" QtMocHelpers::PropertyData<%s>(%d, ",
p.name.constData(), p.type.constData(), stridx(p.name));
" QtMocHelpers::PropertyData<%s%s>(%d, ",
p.name.constData(), cxxTypeTag(p.typeTag), p.type.constData(), stridx(p.name));
generateTypeInfo(p.type);
fputc(',', out);

Expand Down Expand Up @@ -888,9 +902,10 @@ QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper()
{
QMultiMap<QByteArray, int> automaticPropertyMetaTypes;
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))
automaticPropertyMetaTypes.insert(propertyType, i);
automaticPropertyMetaTypes.insert(cxxTypeTag(p.typeTag) + propertyType, i);
}
return automaticPropertyMetaTypes;
}
Expand Down Expand Up @@ -1157,14 +1172,17 @@ void Generator::generateStaticMetacall()
propindex, p.type.constData(), prefix.constData(), p.read.constData());
#endif
else if (p.read == "default")
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s().value(); break;\n",
propindex, p.type.constData(), prefix.constData(), p.bind.constData());
fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s().value(); break;\n",
propindex, cxxTypeTag(p.typeTag), p.type.constData(),
prefix.constData(), p.bind.constData());
else if (!p.read.isEmpty())
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
propindex, p.type.constData(), prefix.constData(), p.read.constData());
fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s(); break;\n",
propindex, cxxTypeTag(p.typeTag), p.type.constData(),
prefix.constData(), p.read.constData());
else
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
propindex, p.type.constData(), prefix.constData(), p.member.constData());
fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s; break;\n",
propindex, cxxTypeTag(p.typeTag), p.type.constData(),
prefix.constData(), p.member.constData());
}
fprintf(out, " default: break;\n");
fprintf(out, " }\n");
Expand All @@ -1187,21 +1205,22 @@ void Generator::generateStaticMetacall()
}
if (p.write == "default") {
fprintf(out, " case %d: {\n", propindex);
fprintf(out, " %s%s().setValue(*reinterpret_cast< %s*>(_v));\n",
prefix.constData(), p.bind.constData(), p.type.constData());
fprintf(out, " %s%s().setValue(*reinterpret_cast<%s%s*>(_v));\n",
prefix.constData(), p.bind.constData(), cxxTypeTag(p.typeTag), p.type.constData());
fprintf(out, " break;\n");
fprintf(out, " }\n");
} else if (!p.write.isEmpty()) {
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
propindex, prefix.constData(), p.write.constData(), p.type.constData());
fprintf(out, " case %d: %s%s(*reinterpret_cast<%s%s*>(_v)); break;\n",
propindex, prefix.constData(), p.write.constData(),
cxxTypeTag(p.typeTag), p.type.constData());
} else {
fprintf(out, " case %d:", propindex);
if (p.notify.isEmpty()) {
fprintf(out, " QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s*>(_v)); break;\n",
prefix.constData(), p.member.constData(), p.type.constData());
fprintf(out, " QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s%s*>(_v)); break;\n",
prefix.constData(), p.member.constData(), cxxTypeTag(p.typeTag), p.type.constData());
} else {
fprintf(out, "\n if (QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s*>(_v)))\n",
prefix.constData(), p.member.constData(), p.type.constData());
fprintf(out, "\n if (QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s%s*>(_v)))\n",
prefix.constData(), p.member.constData(), cxxTypeTag(p.typeTag), p.type.constData());
fprintf(out, " Q_EMIT _t->%s(", p.notify.constData());
if (p.notifyId > -1) {
const FunctionDef &f = cdef->signalList.at(p.notifyId);
Expand Down
11 changes: 9 additions & 2 deletions src/tools/moc/moc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,12 @@ Type Moc::parseType()
}

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(;;) {
skipCxxAttributes();
switch (next()) {
Expand Down Expand Up @@ -1326,9 +1331,11 @@ void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex, Moc::Proper
propDef.location = index;
propDef.relativeIndex = propertyIndex;

QByteArray type = parseType().name;
Type t = parseType();
QByteArray type = t.name;
if (type.isEmpty())
error();
propDef.typeTag = t.typeTag;
propDef.designable = propDef.scriptable = propDef.stored = "true";
propDef.user = "false";
/*
Expand Down
11 changes: 11 additions & 0 deletions src/tools/moc/moc.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ QT_BEGIN_NAMESPACE

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
{
enum ReferenceType { NoReference, Reference, RValueReference, Pointer };
Expand All @@ -33,6 +42,7 @@ struct Type
QByteArray rawName;
uint isVolatile : 1;
uint isScoped : 1;
TypeTags typeTag;
Token firstToken;
ReferenceType referenceType;
};
Expand Down Expand Up @@ -116,6 +126,7 @@ struct PropertyDef
enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
Specification gspec = ValueSpec;
int revision = 0;
TypeTags typeTag;
bool constant = false;
bool final = false;
bool required = false;
Expand Down

0 comments on commit ea3288c

Please sign in to comment.