diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-05 14:27:38 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-06 10:28:04 +0100 |
commit | 44b03e1c812233a392d4c7ac143a05dad339bfae (patch) | |
tree | 5e236f90dd41bda38738dbb1e30f08f77e274e35 /tools | |
parent | 3bc9dffda38a65ad559072a7e60edb380e4e576c (diff) |
Update moc
The actual moc hasn't changed since 6.7 was branched off. We can pick
the change back.
Pick-to: 6.7
Fixes: QTBUG-121344
Change-Id: Ied2406ccfdd8307e8f142ff68e45a27786089cc1
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qscxmlc/generator.cpp | 36 | ||||
-rw-r--r-- | tools/qscxmlc/moc.cpp | 83 | ||||
-rw-r--r-- | tools/qscxmlc/moc.h | 11 | ||||
-rw-r--r-- | tools/qscxmlc/moc_patches/generator.cpp.patch | 26 | ||||
-rw-r--r-- | tools/qscxmlc/moc_patches/generator.h.patch | 4 | ||||
-rw-r--r-- | tools/qscxmlc/moc_patches/moc.cpp.patch | 6 | ||||
-rw-r--r-- | tools/qscxmlc/moc_patches/moc.h.patch | 21 | ||||
-rw-r--r-- | tools/qscxmlc/moc_patches/outputrevision.h.patch | 4 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.cpp | 6 |
9 files changed, 116 insertions, 81 deletions
diff --git a/tools/qscxmlc/generator.cpp b/tools/qscxmlc/generator.cpp index 571c255..4586c1d 100644 --- a/tools/qscxmlc/generator.cpp +++ b/tools/qscxmlc/generator.cpp @@ -96,7 +96,7 @@ Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, requireCompleteTypes(requireCompleteTypes) { if (cdef->superclassList.size()) - purestSuperClass = cdef->superclassList.constFirst().first; + purestSuperClass = cdef->superclassList.constFirst().classname; } // -- QtScxml @@ -635,10 +635,9 @@ void Generator::generateCode() auto it = cdef->superclassList.cbegin() + 1; const auto end = cdef->superclassList.cend(); for (; it != end; ++it) { - const auto &[className, access] = *it; - if (access == FunctionDef::Private) + if (it->access == FunctionDef::Private) continue; - const char *cname = className.constData(); + const char *cname = it->classname.constData(); fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(this);\n", cname, cname); } @@ -682,12 +681,29 @@ void Generator::generateCode() // Generate function to make sure the non-class signals exist in the parent classes // if (!cdef->nonClassSignalList.isEmpty()) { - fprintf(out, "// If you get a compile error in this function it can be because either\n"); - fprintf(out, "// a) You are using a NOTIFY signal that does not exist. Fix it.\n"); - fprintf(out, "// b) You are using a NOTIFY signal that does exist (in a parent class) but has a non-empty parameter list. This is a moc limitation.\n"); - fprintf(out, "[[maybe_unused]] static void checkNotifySignalValidity_%s(%s *t) {\n", qualifiedClassNameIdentifier.constData(), cdef->qualified.constData()); - for (const QByteArray &nonClassSignal : std::as_const(cdef->nonClassSignalList)) - fprintf(out, " t->%s();\n", nonClassSignal.constData()); + fprintf(out, "namespace CheckNotifySignalValidity_%s {\n", qualifiedClassNameIdentifier.constData()); + for (const QByteArray &nonClassSignal : std::as_const(cdef->nonClassSignalList)) { + const auto propertyIt = std::find_if(cdef->propertyList.constBegin(), + cdef->propertyList.constEnd(), + [&nonClassSignal](const PropertyDef &p) { + return nonClassSignal == p.notify; + }); + // must find something, otherwise checkProperties wouldn't have inserted an entry into nonClassSignalList + Q_ASSERT(propertyIt != cdef->propertyList.constEnd()); + fprintf(out, "template<typename T> using has_nullary_%s = decltype(std::declval<T>().%s());\n", + nonClassSignal.constData(), + nonClassSignal.constData()); + const auto &propertyType = propertyIt->type; + fprintf(out, "template<typename T> using has_unary_%s = decltype(std::declval<T>().%s(std::declval<%s>()));\n", + nonClassSignal.constData(), + nonClassSignal.constData(), + propertyType.constData()); + fprintf(out, "static_assert(qxp::is_detected_v<has_nullary_%s, %s> || qxp::is_detected_v<has_unary_%s, %s>,\n" + " \"NOTIFY signal %s does not exist in class (or is private in its parent)\");\n", + nonClassSignal.constData(), cdef->qualified.constData(), + nonClassSignal.constData(), cdef->qualified.constData(), + nonClassSignal.constData()); + } fprintf(out, "}\n"); } } diff --git a/tools/qscxmlc/moc.cpp b/tools/qscxmlc/moc.cpp index bcccb5f..aeb3cad 100644 --- a/tools/qscxmlc/moc.cpp +++ b/tools/qscxmlc/moc.cpp @@ -27,6 +27,15 @@ static QByteArray normalizeType(const QByteArray &ba) return ba.size() ? normalizeTypeInternal(ba.constBegin(), ba.constEnd()) : ba; } +const QByteArray &Moc::toFullyQualified(const QByteArray &name) const noexcept +{ + if (auto it = knownQObjectClasses.find(name); it != knownQObjectClasses.end()) + return it.value(); + if (auto it = knownGadgets.find(name); it != knownGadgets.end()) + return it.value(); + return name; +} + bool Moc::parseClassHead(ClassDef *def) { // figure out whether this is a class declaration, or only a @@ -88,17 +97,17 @@ bool Moc::parseClassHead(ClassDef *def) else test(PUBLIC); test(VIRTUAL); - const QByteArray type = parseType().name; + const Type type = parseType(); // ignore the 'class Foo : BAR(Baz)' case if (test(LPAREN)) { until(RPAREN); } else { - def->superclassList += qMakePair(type, access); + def->superclassList.push_back({type.name, toFullyQualified(type.name), access}); } } while (test(COMMA)); if (!def->superclassList.isEmpty() - && knownGadgets.contains(def->superclassList.constFirst().first)) { + && knownGadgets.contains(def->superclassList.constFirst().classname)) { // Q_GADGET subclasses are treated as Q_GADGETs knownGadgets.insert(def->classname, def->qualified); knownGadgets.insert(def->qualified, def->qualified); @@ -424,35 +433,29 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) error(); } bool scopedFunctionName = false; - if (test(LPAREN)) { - def->name = def->type.name; - scopedFunctionName = def->type.isScoped; - def->type = Type("int"); - } else { - // we might have modifiers and attributes after a tag - // note that testFunctionAttribute is handled further below, - // and revisions and attributes must come first - while (testForFunctionModifiers(def)) {} - Type tempType = parseType();; - while (!tempType.name.isEmpty() && lookup() != LPAREN) { - if (testFunctionAttribute(def->type.firstToken, def)) - ; // fine - else if (def->type.firstToken == Q_SIGNALS_TOKEN) - error(); - else if (def->type.firstToken == Q_SLOTS_TOKEN) - error(); - else { - if (!def->tag.isEmpty()) - def->tag += ' '; - def->tag += def->type.name; - } - def->type = tempType; - tempType = parseType(); + // we might have modifiers and attributes after a tag + // note that testFunctionAttribute is handled further below, + // and revisions and attributes must come first + while (testForFunctionModifiers(def)) {} + Type tempType = parseType();; + while (!tempType.name.isEmpty() && lookup() != LPAREN) { + if (testFunctionAttribute(def->type.firstToken, def)) + ; // fine + else if (def->type.firstToken == Q_SIGNALS_TOKEN) + error(); + else if (def->type.firstToken == Q_SLOTS_TOKEN) + error(); + else { + if (!def->tag.isEmpty()) + def->tag += ' '; + def->tag += def->type.name; } - next(LPAREN, "Not a signal or slot declaration"); - def->name = tempType.name; - scopedFunctionName = tempType.isScoped; + def->type = tempType; + tempType = parseType(); } + next(LPAREN, "Not a signal or slot declaration"); + def->name = tempType.name; + scopedFunctionName = tempType.isScoped; if (!test(RPAREN)) { parseFunctionArguments(def); @@ -544,7 +547,8 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) def->isConstructor = !tilde; def->type = Type(); } else { - def->type = Type("int"); + // missing type name? => Skip + return false; } } else { // ### TODO: The condition before testForFunctionModifiers shoulnd't be necessary, @@ -712,8 +716,10 @@ void Moc::parse() switch (next()) { case NAMESPACE: if (test(IDENTIFIER)) { - while (test(SCOPE)) + while (test(SCOPE)) { + test(INLINE); // ignore inline namespaces next(IDENTIFIER); + } if (test(EQ)) { // namespace Foo = Bar::Baz; until(SEMIC); @@ -1171,6 +1177,7 @@ void Moc::generate(FILE *out, FILE *jsonOutput) fprintf(out, "\n#include <QtCore/qtmochelpers.h>\n"); fprintf(out, "\n#include <memory>\n\n"); // For std::addressof + fprintf(out, "\n#include <QtCore/qxptype_traits.h>\n"); // is_detected fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n" "#error \"The header file '%s' doesn't include <QObject>.\"\n", fn.constData()); @@ -1862,7 +1869,7 @@ bool Moc::until(Token target) { void Moc::checkSuperClasses(ClassDef *def) { Q_ASSERT(!def->superclassList.isEmpty()); - const QByteArray &firstSuperclass = def->superclassList.at(0).first; + const QByteArray &firstSuperclass = def->superclassList.at(0).classname; if (!knownQObjectClasses.contains(firstSuperclass)) { // enable once we /require/ include paths @@ -1888,7 +1895,7 @@ void Moc::checkSuperClasses(ClassDef *def) const auto end = def->superclassList.cend(); auto it = def->superclassList.cbegin() + 1; for (; it != end; ++it) { - const QByteArray &superClass = it->first; + const QByteArray &superClass = it->classname; if (knownQObjectClasses.contains(superClass)) { const QByteArray msg = "Class " @@ -2043,11 +2050,11 @@ QJsonObject ClassDef::toJson() const QJsonArray superClasses; for (const auto &super: std::as_const(superclassList)) { - const auto name = super.first; - const auto access = super.second; QJsonObject superCls; - superCls["name"_L1] = QString::fromUtf8(name); - FunctionDef::accessToJson(&superCls, access); + superCls["name"_L1] = QString::fromUtf8(super.classname); + if (super.classname != super.qualified) + superCls["fullyQualifiedName"_L1] = QString::fromUtf8(super.qualified); + FunctionDef::accessToJson(&superCls, super.access); superClasses.append(superCls); } diff --git a/tools/qscxmlc/moc.h b/tools/qscxmlc/moc.h index d054dea..19aefb9 100644 --- a/tools/qscxmlc/moc.h +++ b/tools/qscxmlc/moc.h @@ -165,8 +165,15 @@ struct BaseDef { qsizetype end = 0; }; +struct SuperClass { + QByteArray classname; + QByteArray qualified; + FunctionDef::Access access; +}; +Q_DECLARE_TYPEINFO(SuperClass, Q_RELOCATABLE_TYPE); + struct ClassDef : BaseDef { - QList<QPair<QByteArray, FunctionDef::Access>> superclassList; + QList<SuperClass> superclassList; struct Interface { @@ -245,6 +252,8 @@ public: return index > def->begin && index < def->end - 1; } + const QByteArray &toFullyQualified(const QByteArray &name) const noexcept; + void prependNamespaces(BaseDef &def, const QList<NamespaceDef> &namespaceList) const; Type parseType(); diff --git a/tools/qscxmlc/moc_patches/generator.cpp.patch b/tools/qscxmlc/moc_patches/generator.cpp.patch index 75cd3b1..26906d8 100644 --- a/tools/qscxmlc/moc_patches/generator.cpp.patch +++ b/tools/qscxmlc/moc_patches/generator.cpp.patch @@ -1,5 +1,5 @@ ---- .upstream/generator.cpp 2023-07-06 09:09:24.454402160 +0200 -+++ generator.cpp 2023-08-22 14:06:36.819992506 +0200 +--- .upstream/generator.cpp 2024-02-01 11:08:00.055494626 +0100 ++++ generator.cpp 2024-02-05 14:18:32.229391845 +0100 @@ -4,7 +4,9 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 @@ -57,7 +57,7 @@ - requireCompleteTypes(requireCompleteTypes) - { - if (cdef->superclassList.size()) -- purestSuperClass = cdef->superclassList.constFirst().first; +- purestSuperClass = cdef->superclassList.constFirst().classname; +// -- QtScxml +Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, + const QHash<QByteArray, QByteArray> &knownQObjectClasses, @@ -72,7 +72,7 @@ + requireCompleteTypes(requireCompleteTypes) +{ + if (cdef->superclassList.size()) -+ purestSuperClass = cdef->superclassList.constFirst().first; ++ purestSuperClass = cdef->superclassList.constFirst().classname; } +// -- QtScxml @@ -153,7 +153,7 @@ qualifiedClassNameIdentifier.constData()); // for all superclasses but the first one -@@ -632,7 +674,9 @@ +@@ -631,7 +673,9 @@ // // Generate plugin meta data // @@ -163,7 +163,7 @@ // // Generate function to make sure the non-class signals exist in the parent classes -@@ -1084,6 +1128,13 @@ +@@ -1100,6 +1144,13 @@ const FunctionDef &f = methodList.at(methodindex); Q_ASSERT(!f.normalizedType.isEmpty()); fprintf(out, " case %d: ", methodindex); @@ -177,7 +177,7 @@ if (f.normalizedType != "void") fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData()); fprintf(out, "_t->"); -@@ -1162,6 +1213,10 @@ +@@ -1178,6 +1229,10 @@ const FunctionDef &f = cdef->signalList.at(methodindex); if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic) continue; @@ -188,7 +188,7 @@ anythingUsed = true; fprintf(out, " {\n"); fprintf(out, " using _t = %s (%s::*)(",f.type.rawName.constData() , cdef->classname.constData()); -@@ -1184,7 +1239,7 @@ +@@ -1200,7 +1255,7 @@ else fprintf(out, ");\n"); fprintf(out, " if (_t _q_method = &%s::%s; *reinterpret_cast<_t *>(_a[1]) == _q_method) {\n", @@ -197,7 +197,7 @@ fprintf(out, " *result = %d;\n", methodindex); fprintf(out, " return;\n"); fprintf(out, " }\n }\n"); -@@ -1279,8 +1334,11 @@ +@@ -1295,8 +1350,11 @@ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s().value(); break;\n", propindex, p.type.constData(), prefix.constData(), p.bind.constData()); else if (!p.read.isEmpty()) @@ -211,7 +211,7 @@ else fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n", propindex, p.type.constData(), prefix.constData(), p.member.constData()); -@@ -1412,6 +1470,10 @@ +@@ -1428,6 +1486,10 @@ { if (def->wasCloned || def->isAbstract) return; @@ -222,7 +222,7 @@ fprintf(out, "\n// SIGNAL %d\n%s %s::%s(", index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData()); -@@ -1460,10 +1522,8 @@ +@@ -1476,10 +1538,8 @@ if (def->normalizedType == "void") { fprintf(out, "nullptr"); } else { @@ -235,7 +235,7 @@ } int i; for (i = 1; i < offset; ++i) -@@ -1478,6 +1538,36 @@ +@@ -1494,6 +1554,36 @@ fprintf(out, "}\n"); } @@ -272,7 +272,7 @@ static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v); static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o) { -@@ -1613,7 +1703,11 @@ +@@ -1629,7 +1719,11 @@ #define CBOR_ENCODER_WRITER_CONTROL 1 #define CBOR_ENCODER_WRITE_FUNCTION CborDevice::callback diff --git a/tools/qscxmlc/moc_patches/generator.h.patch b/tools/qscxmlc/moc_patches/generator.h.patch index d2a5235..4fc3325 100644 --- a/tools/qscxmlc/moc_patches/generator.h.patch +++ b/tools/qscxmlc/moc_patches/generator.h.patch @@ -1,5 +1,5 @@ ---- .upstream/generator.h 2023-06-22 08:29:43.218633538 +0200 -+++ generator.h 2023-08-22 14:02:21.930688587 +0200 +--- .upstream/generator.h 2023-06-22 20:40:43.078529554 +0200 ++++ generator.h 2024-02-05 14:06:04.258179059 +0100 @@ -6,23 +6,34 @@ #include "moc.h" diff --git a/tools/qscxmlc/moc_patches/moc.cpp.patch b/tools/qscxmlc/moc_patches/moc.cpp.patch index d4cf1ad..7b55c65 100644 --- a/tools/qscxmlc/moc_patches/moc.cpp.patch +++ b/tools/qscxmlc/moc_patches/moc.cpp.patch @@ -1,5 +1,5 @@ ---- .upstream/moc.cpp 2023-06-22 08:29:43.218633538 +0200 -+++ moc.cpp 2023-08-22 14:02:21.930688587 +0200 +--- .upstream/moc.cpp 2024-02-01 11:08:00.055494626 +0100 ++++ moc.cpp 2024-02-05 14:06:04.258179059 +0100 @@ -12,14 +12,15 @@ #include <QtCore/qdir.h> #include <QtCore/qjsondocument.h> @@ -19,7 +19,7 @@ // only moc needs this function static QByteArray normalizeType(const QByteArray &ba) { -@@ -1990,6 +1991,7 @@ +@@ -1997,6 +1998,7 @@ } } } diff --git a/tools/qscxmlc/moc_patches/moc.h.patch b/tools/qscxmlc/moc_patches/moc.h.patch index cc58e0f..dcdac6b 100644 --- a/tools/qscxmlc/moc_patches/moc.h.patch +++ b/tools/qscxmlc/moc_patches/moc.h.patch @@ -1,17 +1,16 @@ ---- .upstream/moc.h 2023-06-21 08:45:31.377639327 +0200 -+++ moc.h 2023-08-22 14:02:21.930688587 +0200 -@@ -4,15 +4,12 @@ +--- .upstream/moc.h 2024-02-05 14:10:55.937714571 +0100 ++++ moc.h 2024-02-05 14:12:52.133597464 +0100 +@@ -4,14 +4,12 @@ #ifndef MOC_H #define MOC_H -#include "parser.h" -#include <qstringlist.h> -#include <qmap.h> --#include <qpair.h> -#include <qjsondocument.h> -#include <qjsonarray.h> -#include <qjsonobject.h> --#include <qversionnumber.h> +-#include <qtyperevision.h> -#include <stdio.h> +// -- QtScxml +#include <QtCore/qmap.h> @@ -22,7 +21,7 @@ #include <private/qtools_p.h> -@@ -24,16 +21,18 @@ +@@ -23,16 +21,18 @@ { enum ReferenceType { NoReference, Reference, RValueReference, Pointer }; @@ -43,7 +42,7 @@ ReferenceType referenceType; }; Q_DECLARE_TYPEINFO(Type, Q_RELOCATABLE_TYPE); -@@ -83,8 +82,9 @@ +@@ -82,8 +82,9 @@ bool inlineCode = false; bool wasCloned = false; @@ -54,7 +53,7 @@ bool isCompat = false; bool isInvokable = false; bool isScriptable = false; -@@ -98,6 +98,11 @@ +@@ -97,6 +98,11 @@ QJsonObject toJson() const; static void accessToJson(QJsonObject *obj, Access acs); @@ -66,7 +65,7 @@ }; Q_DECLARE_TYPEINFO(FunctionDef, Q_RELOCATABLE_TYPE); -@@ -125,6 +130,10 @@ +@@ -124,6 +130,10 @@ qsizetype location = -1; // token index, used for error reporting QJsonObject toJson() const; @@ -77,7 +76,7 @@ }; Q_DECLARE_TYPEINFO(PropertyDef, Q_RELOCATABLE_TYPE); -@@ -198,6 +207,7 @@ +@@ -204,6 +214,7 @@ }; Q_DECLARE_TYPEINFO(NamespaceDef, Q_RELOCATABLE_TYPE); @@ -85,7 +84,7 @@ class Moc : public Parser { public: -@@ -285,6 +295,7 @@ +@@ -293,6 +304,7 @@ void checkListSizes(const ClassDef &def); }; diff --git a/tools/qscxmlc/moc_patches/outputrevision.h.patch b/tools/qscxmlc/moc_patches/outputrevision.h.patch index 6dba72e..be3c2eb 100644 --- a/tools/qscxmlc/moc_patches/outputrevision.h.patch +++ b/tools/qscxmlc/moc_patches/outputrevision.h.patch @@ -1,5 +1,5 @@ ---- .upstream/outputrevision.h 2022-07-14 10:20:51.543950028 +0200 -+++ outputrevision.h 2023-08-21 09:57:10.176050973 +0200 +--- .upstream/outputrevision.h 2022-05-23 08:46:14.490945334 +0200 ++++ outputrevision.h 2024-02-05 14:06:04.254179068 +0100 @@ -4,7 +4,13 @@ #ifndef OUTPUTREVISION_H #define OUTPUTREVISION_H diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp index 98f6772..765498c 100644 --- a/tools/qscxmlc/scxmlcppdumper.cpp +++ b/tools/qscxmlc/scxmlcppdumper.cpp @@ -729,7 +729,11 @@ QString CppDumper::generateMetaObject(const QString &className, ClassDef classDef; classDef.classname = className.toUtf8(); classDef.qualified = classDef.classname; - classDef.superclassList << qMakePair(QByteArray("QScxmlStateMachine"), FunctionDef::Public); + classDef.superclassList << SuperClass { + QByteArray("QScxmlStateMachine"), + QByteArray(QT_STRINGIFY(QT_PREPEND_NAMESPACE(QScxmlStateMachine))), + FunctionDef::Public + }; classDef.hasQObject = true; FunctionDef constructor; constructor.name = className.toUtf8(); |