summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-02-05 14:27:38 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-02-06 10:28:04 +0100
commit44b03e1c812233a392d4c7ac143a05dad339bfae (patch)
tree5e236f90dd41bda38738dbb1e30f08f77e274e35 /tools
parent3bc9dffda38a65ad559072a7e60edb380e4e576c (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.cpp36
-rw-r--r--tools/qscxmlc/moc.cpp83
-rw-r--r--tools/qscxmlc/moc.h11
-rw-r--r--tools/qscxmlc/moc_patches/generator.cpp.patch26
-rw-r--r--tools/qscxmlc/moc_patches/generator.h.patch4
-rw-r--r--tools/qscxmlc/moc_patches/moc.cpp.patch6
-rw-r--r--tools/qscxmlc/moc_patches/moc.h.patch21
-rw-r--r--tools/qscxmlc/moc_patches/outputrevision.h.patch4
-rw-r--r--tools/qscxmlc/scxmlcppdumper.cpp6
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();