summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSES/LicenseRef-SHA1-Public-Domain.txt3
-rw-r--r--dependencies.yaml4
-rw-r--r--src/3rdparty/sha1/REUSE.toml8
-rw-r--r--src/3rdparty/sha1/qt_attribution.json15
-rw-r--r--src/3rdparty/sha1/sha1.cpp225
-rw-r--r--src/scxml/qscxmlinvokableservice.cpp6
-rw-r--r--src/scxml/qscxmlstatemachine.cpp8
-rw-r--r--tools/qscxmlc/generator.cpp50
-rw-r--r--tools/qscxmlc/generator.h6
-rw-r--r--tools/qscxmlc/moc.cpp93
-rw-r--r--tools/qscxmlc/moc.h5
-rw-r--r--tools/qscxmlc/moc_patches/generator.cpp.patch69
-rw-r--r--tools/qscxmlc/moc_patches/generator.h.patch21
-rw-r--r--tools/qscxmlc/moc_patches/moc.cpp.patch14
-rw-r--r--tools/qscxmlc/moc_patches/moc.h.patch10
-rw-r--r--tools/qscxmlc/moc_patches/outputrevision.h.patch2
-rw-r--r--tools/qscxmlc/scxmlcppdumper.cpp30
17 files changed, 468 insertions, 101 deletions
diff --git a/LICENSES/LicenseRef-SHA1-Public-Domain.txt b/LICENSES/LicenseRef-SHA1-Public-Domain.txt
new file mode 100644
index 0000000..2ebbf9a
--- /dev/null
+++ b/LICENSES/LicenseRef-SHA1-Public-Domain.txt
@@ -0,0 +1,3 @@
+100% free public domain implementation of the SHA-1 algorithm
+by Dominik Reichl <dominik.reichl@t-online.de>
+Web: http://www.dominik-reichl.de/
diff --git a/dependencies.yaml b/dependencies.yaml
index ba73fbb..45a9542 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -1,7 +1,7 @@
dependencies:
../qtbase:
- ref: bd04c5d7a4b907b8c4a2d2dda4ba3f24f687fb7f
+ ref: 4fd88011fa7975ce64d5648698a234f85bac359c
required: true
../qtdeclarative:
- ref: 59da4b17158303fc671869547bcb91b675bf4702
+ ref: fc162d455eedbb68f22f302dee45f7faf4146dd0
required: false
diff --git a/src/3rdparty/sha1/REUSE.toml b/src/3rdparty/sha1/REUSE.toml
new file mode 100644
index 0000000..93b18a4
--- /dev/null
+++ b/src/3rdparty/sha1/REUSE.toml
@@ -0,0 +1,8 @@
+version = 1
+
+[[annotations]]
+path = ["**"]
+precedence = "closest"
+SPDX-FileCopyrightText = ["Copyright (C) Dominik Reichl <dominik.reichl@t-online.de>",
+ "Copyright (C) 2016 The Qt Company Ltd"]
+SPDX-License-Identifier = "LicenseRef-SHA1-Public-Domain"
diff --git a/src/3rdparty/sha1/qt_attribution.json b/src/3rdparty/sha1/qt_attribution.json
new file mode 100644
index 0000000..bbcced6
--- /dev/null
+++ b/src/3rdparty/sha1/qt_attribution.json
@@ -0,0 +1,15 @@
+{
+ "Id": "sha1",
+ "Name": "Secure Hash Algorithm SHA-1",
+ "QDocModule": "qtcore",
+ "QtUsage": "Used in Qt SCXML (Qt moc copy).",
+
+ "Description": "Implements the Secure Hash Algorithms SHA 1",
+ "PURL": "pkg:generic/csha1?download_url=https://www.dominik-reichl.de/projects/csha1/",
+ "Homepage": "http://www.dominik-reichl.de/projects/csha1/",
+ "License": "Public Domain",
+ "LicenseId": "LicenseRef-SHA1-Public-Domain",
+ "Copyright": ["Copyright (C) Dominik Reichl <dominik.reichl@t-online.de>",
+ "Copyright (C) 2016 The Qt Company Ltd"],
+ "Comment": "no relevant CPE found"
+}
diff --git a/src/3rdparty/sha1/sha1.cpp b/src/3rdparty/sha1/sha1.cpp
new file mode 100644
index 0000000..6dd25e3
--- /dev/null
+++ b/src/3rdparty/sha1/sha1.cpp
@@ -0,0 +1,225 @@
+// Based on the public domain implementation of the SHA-1 algorithm by Dominik Reichl
+//
+// Copyright (C) Dominik Reichl <dominik.reichl@t-online.de>
+// Copyright (C) 2016 The Qt Company Ltd.
+//
+// SPDX-License-Identifier: LicenseRef-SHA1-Public-Domain
+
+#include <QtCore/qendian.h>
+
+#ifdef Q_CC_MSVC
+# include <stdlib.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// Test Vectors (from FIPS PUB 180-1)
+//
+// SHA1("abc") =
+// A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+//
+// SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
+// 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+//
+// SHA1(A million repetitions of "a") =
+// 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+//
+
+
+// #define or #undef this, if you want the to wipe all
+// temporary variables after processing
+#define SHA1_WIPE_VARIABLES
+
+
+struct Sha1State
+{
+ quint32 h0;
+ quint32 h1;
+ quint32 h2;
+ quint32 h3;
+ quint32 h4;
+
+ quint64 messageSize;
+ unsigned char buffer[64];
+};
+
+
+typedef union
+{
+ quint8 bytes[64];
+ quint32 words[16];
+} Sha1Chunk;
+
+static inline quint32 rol32(quint32 value, unsigned int shift)
+{
+#ifdef Q_CC_MSVC
+ return _rotl(value, shift);
+#else
+ return ((value << shift) | (value >> (32 - shift)));
+#endif
+}
+
+static inline quint32 sha1Word(Sha1Chunk *chunk, const uint position)
+{
+ return (chunk->words[position & 0xf] = rol32( chunk->words[(position+13) & 0xf]
+ ^ chunk->words[(position+ 8) & 0xf]
+ ^ chunk->words[(position+ 2) & 0xf]
+ ^ chunk->words[(position) & 0xf], 1));
+}
+
+static inline void sha1Round0(Sha1Chunk *chunk, const uint position,
+ quint32 &v, quint32 &w, quint32 &x, quint32 &y, quint32 &z)
+{
+ z += ((( w & (x ^ y)) ^ y) + chunk->words[position] + 0x5A827999 + rol32(v, 5));
+ w = rol32(w, 30);
+}
+
+static inline void sha1Round1(Sha1Chunk *chunk, const uint position,
+ quint32 &v, quint32 &w, quint32 &x, quint32 &y, quint32 &z)
+{
+ z += ((( w & (x ^ y)) ^ y) + sha1Word(chunk,position) + 0x5A827999 + rol32(v, 5));
+ w = rol32(w, 30);
+}
+
+static inline void sha1Round2(Sha1Chunk *chunk, const uint position,
+ quint32 &v, quint32 &w, quint32 &x, quint32 &y, quint32 &z)
+{
+ z += (( w ^ x ^ y) + sha1Word(chunk, position) + 0x6ED9EBA1 + rol32(v, 5));
+ w = rol32(w, 30);
+}
+
+static inline void sha1Round3(Sha1Chunk *chunk, const uint position,
+ quint32 &v, quint32 &w, quint32 &x, quint32 &y, quint32 &z)
+{
+ z += (((( w | x) & y) | (w & x)) + sha1Word(chunk, position) + 0x8F1BBCDC + rol32(v, 5));
+ w = rol32(w, 30);
+}
+
+static inline void sha1Round4(Sha1Chunk *chunk, const uint position,
+ quint32 &v, quint32 &w, quint32 &x, quint32 &y, quint32 &z)
+{
+ z += ((w ^ x ^ y) + sha1Word(chunk, position) + 0xCA62C1D6 + rol32(v, 5));
+ w = rol32(w, 30);
+}
+
+static inline void sha1ProcessChunk(Sha1State *state, const unsigned char *buffer)
+{
+ // Copy state[] to working vars
+ quint32 a = state->h0;
+ quint32 b = state->h1;
+ quint32 c = state->h2;
+ quint32 d = state->h3;
+ quint32 e = state->h4;
+
+ quint8 chunkBuffer[64];
+ memcpy(chunkBuffer, buffer, 64);
+
+ Sha1Chunk *chunk = reinterpret_cast<Sha1Chunk*>(&chunkBuffer);
+
+ for (int i = 0; i < 16; ++i)
+ chunk->words[i] = qFromBigEndian(chunk->words[i]);
+
+ sha1Round0(chunk, 0, a,b,c,d,e); sha1Round0(chunk, 1, e,a,b,c,d); sha1Round0(chunk, 2, d,e,a,b,c); sha1Round0(chunk, 3, c,d,e,a,b);
+ sha1Round0(chunk, 4, b,c,d,e,a); sha1Round0(chunk, 5, a,b,c,d,e); sha1Round0(chunk, 6, e,a,b,c,d); sha1Round0(chunk, 7, d,e,a,b,c);
+ sha1Round0(chunk, 8, c,d,e,a,b); sha1Round0(chunk, 9, b,c,d,e,a); sha1Round0(chunk, 10, a,b,c,d,e); sha1Round0(chunk, 11, e,a,b,c,d);
+ sha1Round0(chunk, 12, d,e,a,b,c); sha1Round0(chunk, 13, c,d,e,a,b); sha1Round0(chunk, 14, b,c,d,e,a); sha1Round0(chunk, 15, a,b,c,d,e);
+ sha1Round1(chunk, 16, e,a,b,c,d); sha1Round1(chunk, 17, d,e,a,b,c); sha1Round1(chunk, 18, c,d,e,a,b); sha1Round1(chunk, 19, b,c,d,e,a);
+ sha1Round2(chunk, 20, a,b,c,d,e); sha1Round2(chunk, 21, e,a,b,c,d); sha1Round2(chunk, 22, d,e,a,b,c); sha1Round2(chunk, 23, c,d,e,a,b);
+ sha1Round2(chunk, 24, b,c,d,e,a); sha1Round2(chunk, 25, a,b,c,d,e); sha1Round2(chunk, 26, e,a,b,c,d); sha1Round2(chunk, 27, d,e,a,b,c);
+ sha1Round2(chunk, 28, c,d,e,a,b); sha1Round2(chunk, 29, b,c,d,e,a); sha1Round2(chunk, 30, a,b,c,d,e); sha1Round2(chunk, 31, e,a,b,c,d);
+ sha1Round2(chunk, 32, d,e,a,b,c); sha1Round2(chunk, 33, c,d,e,a,b); sha1Round2(chunk, 34, b,c,d,e,a); sha1Round2(chunk, 35, a,b,c,d,e);
+ sha1Round2(chunk, 36, e,a,b,c,d); sha1Round2(chunk, 37, d,e,a,b,c); sha1Round2(chunk, 38, c,d,e,a,b); sha1Round2(chunk, 39, b,c,d,e,a);
+ sha1Round3(chunk, 40, a,b,c,d,e); sha1Round3(chunk, 41, e,a,b,c,d); sha1Round3(chunk, 42, d,e,a,b,c); sha1Round3(chunk, 43, c,d,e,a,b);
+ sha1Round3(chunk, 44, b,c,d,e,a); sha1Round3(chunk, 45, a,b,c,d,e); sha1Round3(chunk, 46, e,a,b,c,d); sha1Round3(chunk, 47, d,e,a,b,c);
+ sha1Round3(chunk, 48, c,d,e,a,b); sha1Round3(chunk, 49, b,c,d,e,a); sha1Round3(chunk, 50, a,b,c,d,e); sha1Round3(chunk, 51, e,a,b,c,d);
+ sha1Round3(chunk, 52, d,e,a,b,c); sha1Round3(chunk, 53, c,d,e,a,b); sha1Round3(chunk, 54, b,c,d,e,a); sha1Round3(chunk, 55, a,b,c,d,e);
+ sha1Round3(chunk, 56, e,a,b,c,d); sha1Round3(chunk, 57, d,e,a,b,c); sha1Round3(chunk, 58, c,d,e,a,b); sha1Round3(chunk, 59, b,c,d,e,a);
+ sha1Round4(chunk, 60, a,b,c,d,e); sha1Round4(chunk, 61, e,a,b,c,d); sha1Round4(chunk, 62, d,e,a,b,c); sha1Round4(chunk, 63, c,d,e,a,b);
+ sha1Round4(chunk, 64, b,c,d,e,a); sha1Round4(chunk, 65, a,b,c,d,e); sha1Round4(chunk, 66, e,a,b,c,d); sha1Round4(chunk, 67, d,e,a,b,c);
+ sha1Round4(chunk, 68, c,d,e,a,b); sha1Round4(chunk, 69, b,c,d,e,a); sha1Round4(chunk, 70, a,b,c,d,e); sha1Round4(chunk, 71, e,a,b,c,d);
+ sha1Round4(chunk, 72, d,e,a,b,c); sha1Round4(chunk, 73, c,d,e,a,b); sha1Round4(chunk, 74, b,c,d,e,a); sha1Round4(chunk, 75, a,b,c,d,e);
+ sha1Round4(chunk, 76, e,a,b,c,d); sha1Round4(chunk, 77, d,e,a,b,c); sha1Round4(chunk, 78, c,d,e,a,b); sha1Round4(chunk, 79, b,c,d,e,a);
+
+ // Add the working vars back into state
+ state->h0 += a;
+ state->h1 += b;
+ state->h2 += c;
+ state->h3 += d;
+ state->h4 += e;
+
+ // Wipe variables
+#ifdef SHA1_WIPE_VARIABLES
+ a = b = c = d = e = 0;
+ memset(chunkBuffer, 0, 64);
+#endif
+}
+
+static inline void sha1InitState(Sha1State *state)
+{
+ state->h0 = 0x67452301;
+ state->h1 = 0xEFCDAB89;
+ state->h2 = 0x98BADCFE;
+ state->h3 = 0x10325476;
+ state->h4 = 0xC3D2E1F0;
+
+ state->messageSize = 0;
+}
+
+static inline void sha1Update(Sha1State *state, const unsigned char *data, qint64 len)
+{
+ quint32 rest = static_cast<quint32>(state->messageSize & Q_UINT64_C(63));
+
+ quint64 availableData = static_cast<quint64>(len) + static_cast<quint64>(rest);
+ state->messageSize += len;
+
+ if (availableData < Q_UINT64_C(64)) {
+ memcpy(&state->buffer[rest], &data[0], len);
+
+ } else {
+ qint64 i = static_cast<qint64>(64 - rest);
+ memcpy(&state->buffer[rest], &data[0], static_cast<qint32>(i));
+ sha1ProcessChunk(state, state->buffer);
+
+ qint64 lastI = len - ((len + rest) & Q_INT64_C(63));
+ for( ; i < lastI; i += 64)
+ sha1ProcessChunk(state, &data[i]);
+
+ memcpy(&state->buffer[0], &data[i], len - i);
+ }
+}
+
+static inline void sha1FinalizeState(Sha1State *state)
+{
+ quint64 messageSize = state->messageSize;
+ unsigned char sizeInBits[8];
+ qToBigEndian(messageSize << 3, sizeInBits);
+
+ sha1Update(state, (const unsigned char *)"\200", 1);
+
+ unsigned char zero[64];
+ memset(zero, 0, 64);
+ if (static_cast<int>(messageSize & 63) > 56 - 1) {
+ sha1Update(state, zero, 64 - 1 - static_cast<int>(messageSize & 63));
+ sha1Update(state, zero, 64 - 8);
+ } else {
+ sha1Update(state, zero, 64 - 1 - 8 - static_cast<int>(messageSize & 63));
+ }
+
+ sha1Update(state, sizeInBits, 8);
+#ifdef SHA1_WIPE_VARIABLES
+ memset(state->buffer, 0, 64);
+ memset(zero, 0, 64);
+ state->messageSize = 0;
+#endif
+}
+
+static inline void sha1ToHash(Sha1State *state, unsigned char* buffer)
+{
+ qToBigEndian(state->h0, buffer);
+ qToBigEndian(state->h1, buffer + 4);
+ qToBigEndian(state->h2, buffer + 8);
+ qToBigEndian(state->h3, buffer + 12);
+ qToBigEndian(state->h4, buffer + 16);
+}
+
+QT_END_NAMESPACE
diff --git a/src/scxml/qscxmlinvokableservice.cpp b/src/scxml/qscxmlinvokableservice.cpp
index 0665406..8845d51 100644
--- a/src/scxml/qscxmlinvokableservice.cpp
+++ b/src/scxml/qscxmlinvokableservice.cpp
@@ -287,6 +287,12 @@ QScxmlScxmlService::~QScxmlScxmlService()
}
/*!
+ \class QScxmlScxmlService
+ \inmodule QtScxml
+ \internal
+*/
+
+/*!
Creates a SCXML service wrapping \a stateMachine, invoked from
\a parentStateMachine, as a child of \a factory.
*/
diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp
index cb35778..ac8247d 100644
--- a/src/scxml/qscxmlstatemachine.cpp
+++ b/src/scxml/qscxmlstatemachine.cpp
@@ -487,11 +487,17 @@ void QScxmlStateMachinePrivate::submitDelayedEvent(QScxmlEvent *event)
}
/*!
+ \class QScxmlStateMachinePrivate
+ \inmodule QtScxml
+ \internal
+*/
+
+/*!
* Submits an error event to the external event queue of this state machine.
*
* The type of the error is specified by \a type. The value of type has to begin
* with the string \e error. For example \c {error.execution}. The message,
- * \a message, decribes the error and is passed to the event as the
+ * \a message, describes the error and is passed to the event as the
* \c errorMessage property. The \a sendId of the message causing the error is specified, if it has
* one.
*/
diff --git a/tools/qscxmlc/generator.cpp b/tools/qscxmlc/generator.cpp
index 50f1822..006dd81 100644
--- a/tools/qscxmlc/generator.cpp
+++ b/tools/qscxmlc/generator.cpp
@@ -104,20 +104,21 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
}
// -- QtScxml
-Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+Generator::Generator(const ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets,
- QIODevice &outfile,
- bool requireCompleteTypes)
- : out(outfile),
- cdef(classDef),
- metaTypes(metaTypes),
- knownQObjectClasses(knownQObjectClasses),
- knownGadgets(knownGadgets),
- requireCompleteTypes(requireCompleteTypes)
+ const QHash<QByteArray, QByteArray> &hashes,
+ QIODevice &outfile, bool requireCompleteTypes)
+ : out(outfile),
+ cdef(classDef),
+ metaTypes(metaTypes),
+ knownQObjectClasses(knownQObjectClasses),
+ knownGadgets(knownGadgets),
+ hashes(hashes),
+ requireCompleteTypes(requireCompleteTypes)
{
- if (cdef->superclassList.size())
- purestSuperClass = cdef->superclassList.constFirst().classname;
+ if (cdef->superclassList.size())
+ purestSuperClass = cdef->superclassList.constFirst().classname;
}
// -- QtScxml
@@ -255,28 +256,11 @@ void Generator::generateCode()
bool isQObject = (cdef->classname == "QObject");
bool isConstructible = !cdef->constructorList.isEmpty();
- // filter out undeclared enumerators and sets
- {
- QList<EnumDef> enumList;
- for (EnumDef def : std::as_const(cdef->enumList)) {
- if (cdef->enumDeclarations.contains(def.name)) {
- enumList += def;
- }
- def.enumName = def.name;
- QByteArray alias = cdef->flagAliases.value(def.name);
- if (cdef->enumDeclarations.contains(alias)) {
- def.name = alias;
- def.flags |= cdef->enumDeclarations[alias];
- enumList += def;
- }
- }
- cdef->enumList = enumList;
- }
-
//
// Register all strings used in data section
//
strreg(cdef->qualified);
+ strreg(hashes[cdef->qualified]);
registerClassInfoStrings();
registerFunctionStrings(cdef->signalList);
registerFunctionStrings(cdef->slotList);
@@ -337,6 +321,8 @@ void Generator::generateCode()
addEnums();
fprintf(out, " };\n");
+ fprintf(out, " uint qt_metaObjectHashIndex = %d;\n", stridx(hashes[cdef->qualified]));
+
const char *uintDataParams = "";
if (isConstructible || !cdef->classInfoList.isEmpty()) {
if (isConstructible) {
@@ -369,7 +355,7 @@ void Generator::generateCode()
if (!requireCompleteness)
tagType = "qt_meta_tag_" + qualifiedClassNameIdentifier + "_t";
fprintf(out, " return QtMocHelpers::metaObjectData<%s, %s>(%s, qt_stringData,\n"
- " qt_methods, qt_properties, qt_enums%s);\n"
+ " qt_methods, qt_properties, qt_enums, qt_metaObjectHashIndex%s);\n"
"}\n",
ownType, tagType.constData(), metaObjectFlags, uintDataParams);
}
@@ -803,6 +789,10 @@ void Generator::addProperties()
addFlag("Constant");
if (p.final)
addFlag("Final");
+ if (p.virtual_)
+ addFlag("Virtual");
+ if (p.override)
+ addFlag("Override");
if (p.user != "false")
addFlag("User");
if (p.required)
diff --git a/tools/qscxmlc/generator.h b/tools/qscxmlc/generator.h
index 63cceef..8b8c58e 100644
--- a/tools/qscxmlc/generator.h
+++ b/tools/qscxmlc/generator.h
@@ -17,13 +17,14 @@ QT_BEGIN_NAMESPACE
class Generator
{
QIODevice &out; // -- QtScxml
- ClassDef *cdef;
+ const ClassDef *cdef;
QList<uint> meta_data;
public:
- Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ Generator(const ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets,
+ const QHash<QByteArray, QByteArray> &hashes,
QIODevice &outfile, // -- QtScxml
bool requireCompleteTypes = false);
void generateCode();
@@ -67,6 +68,7 @@ private:
QList<QByteArray> metaTypes;
QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
+ QHash<QByteArray, QByteArray> hashes;
bool requireCompleteTypes;
};
diff --git a/tools/qscxmlc/moc.cpp b/tools/qscxmlc/moc.cpp
index a57c1b2..ce102c7 100644
--- a/tools/qscxmlc/moc.cpp
+++ b/tools/qscxmlc/moc.cpp
@@ -68,6 +68,8 @@ bool Moc::parseClassHead(ClassDef *def)
const QByteArrayView lex = lexemView();
if (lex != "final" && lex != "sealed" && lex != "Q_DECL_FINAL")
name = lexem();
+ else
+ def->isFinal = true;
}
def->qualified += name;
@@ -85,6 +87,8 @@ bool Moc::parseClassHead(ClassDef *def)
const QByteArrayView lex = lexemView();
if (lex != "final" && lex != "sealed" && lex != "Q_DECL_FINAL")
return false;
+ else
+ def->isFinal = true;
}
if (test(COLON)) {
@@ -553,6 +557,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
bool scopedFunctionName = false;
if (test(LPAREN)) {
def->name = def->type.name;
+ def->lineNumber = symbol().lineNum;
scopedFunctionName = def->type.isScoped;
if (def->name == cdef->classname) {
def->isDestructor = tilde;
@@ -586,6 +591,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
if (!test(LPAREN))
return false;
def->name = tempType.name;
+ def->lineNumber = symbol().lineNum;
scopedFunctionName = tempType.isScoped;
}
@@ -1185,6 +1191,24 @@ static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes)
return required;
}
+QByteArray classDefJsonObjectHash(const QJsonObject &object)
+{
+ const QByteArray json = QJsonDocument(object).toJson(QJsonValue::JsonFormat::Compact);
+ QByteArray hash(20, 0); // SHA1 produces 160 bits of data
+
+ {
+ Sha1State state;
+ sha1InitState(&state);
+ sha1Update(&state, reinterpret_cast<const uchar *>(json.constData()), json.size());
+ sha1FinalizeState(&state);
+ sha1ToHash(&state, reinterpret_cast<uchar *>(hash.data()));
+ }
+
+ static const char revisionPrefix[] = "0$";
+ const QByteArray hashB64 = hash.toBase64(QByteArray::OmitTrailingEquals);
+ return revisionPrefix + hashB64;
+}
+
void Moc::generate(FILE *out, FILE *jsonOutput)
{
QByteArrayView fn = strippedFileName();
@@ -1241,14 +1265,40 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
"#endif\n\n");
#endif
+ // filter out undeclared enumerators and sets
+ for (ClassDef &cdef : classList) {
+ QList<EnumDef> enumList;
+ for (EnumDef def : std::as_const(cdef.enumList)) {
+ if (cdef.enumDeclarations.contains(def.name)) {
+ enumList += def;
+ }
+ def.enumName = def.name;
+ QByteArray alias = cdef.flagAliases.value(def.name);
+ if (cdef.enumDeclarations.contains(alias)) {
+ def.name = alias;
+ def.flags |= cdef.enumDeclarations[alias];
+ enumList += def;
+ }
+ }
+ cdef.enumList = enumList;
+ }
+
fprintf(out, "QT_WARNING_PUSH\n");
fprintf(out, "QT_WARNING_DISABLE_DEPRECATED\n");
fprintf(out, "QT_WARNING_DISABLE_GCC(\"-Wuseless-cast\")\n");
+ QHash<QByteArray, QJsonObject> classDefJsonObjects;
+ QHash<QByteArray, QByteArray> metaObjectHashes;
+ for (const ClassDef &def : std::as_const(classList)) {
+ const QJsonObject jsonObject = def.toJson();
+ classDefJsonObjects.insert(def.qualified, jsonObject);
+ metaObjectHashes.insert(def.qualified, classDefJsonObjectHash(jsonObject));
+ }
+
fputs("", out);
- for (ClassDef &def : classList) {
- Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets, out,
- requireCompleteTypes);
+ for (const ClassDef &def : std::as_const(classList)) {
+ Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets,
+ metaObjectHashes, out, requireCompleteTypes);
generator.generateCode();
// generator.generateCode() should have already registered all strings
@@ -1267,13 +1317,20 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
mocData["inputFile"_L1] = QLatin1StringView(fn.constData());
QJsonArray classesJsonFormatted;
+ QJsonObject hashesJsonObject;
- for (const ClassDef &cdef: std::as_const(classList))
- classesJsonFormatted.append(cdef.toJson());
+ for (const ClassDef &cdef : std::as_const(classList)) {
+ classesJsonFormatted.append(classDefJsonObjects[cdef.qualified]);
+ hashesJsonObject.insert(QString::fromLatin1(cdef.qualified),
+ QString::fromLatin1(metaObjectHashes[cdef.qualified]));
+ }
if (!classesJsonFormatted.isEmpty())
mocData["classes"_L1] = classesJsonFormatted;
+ if (!hashesJsonObject.isEmpty())
+ mocData["hashes"_L1] = hashesJsonObject;
+
QJsonDocument jsonDoc(mocData);
fputs(jsonDoc.toJson().constData(), jsonOutput);
}
@@ -1428,6 +1485,9 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
next(IDENTIFIER);
propDef.name = lexem();
continue;
+ } else if (l[0] == 'O' && l == "OVERRIDE") {
+ propDef.override = true;
+ continue;
} else if (l[0] == 'R' && l == "REQUIRED") {
propDef.required = true;
continue;
@@ -1435,6 +1495,9 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
prev();
propDef.revision = parseRevision().toEncodedVersion<int>();
continue;
+ } else if (l[0] == 'V' && l == "VIRTUAL") {
+ propDef.virtual_ = true;
+ continue;
}
QByteArray v, v2;
@@ -1539,6 +1602,24 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
propDef.write = "";
warning(msg.constData());
}
+ if (propDef.override && propDef.virtual_) {
+ const QByteArray msg = "Issue with property declaration " + propDef.name
+ + ": VIRTUAL is redundant when overriding a property. The OVERRIDE "
+ "must only be used when actually overriding an existing property; using it on a "
+ "new property is an error.";
+ error(msg.constData());
+ }
+ if (propDef.override && propDef.final) {
+ const QByteArray msg = "Issue with property declaration " + propDef.name
+ + ": OVERRIDE is redundant when property is marked FINAL";
+ error(msg.constData());
+ }
+ if (propDef.virtual_ && propDef.final) {
+ const QByteArray msg = "Issue with property declaration " + propDef.name
+ + ": The VIRTUAL cannot be combined with FINAL, as these attributes are mutually "
+ "exclusive";
+ error(msg.constData());
+ }
}
void Moc::parseProperty(ClassDef *def, Moc::PropertyMode mode)
@@ -2054,6 +2135,8 @@ QJsonObject ClassDef::toJson() const
cls["className"_L1] = QString::fromUtf8(classname.constData());
cls["qualifiedClassName"_L1] = QString::fromUtf8(qualified.constData());
cls["lineNumber"_L1] = lineNumber;
+ if (isFinal)
+ cls["final"_L1] = true;
QJsonArray classInfos;
for (const auto &info: std::as_const(classInfoList)) {
diff --git a/tools/qscxmlc/moc.h b/tools/qscxmlc/moc.h
index fbcf150..f8008b3 100644
--- a/tools/qscxmlc/moc.h
+++ b/tools/qscxmlc/moc.h
@@ -136,6 +136,8 @@ struct PropertyDef
TypeTags typeTag;
bool constant = false;
bool final = false;
+ bool virtual_ = false;
+ bool override = false;
bool required = false;
int relativeIndex = -1; // property index in current metaobject
int lineNumber = 0;
@@ -217,6 +219,7 @@ struct ClassDef : BaseDef {
bool hasQGadget = false;
bool hasQNamespace = false;
bool requireCompleteMethodTypes = false;
+ bool isFinal = false;
QJsonObject toJson() const;
};
@@ -305,7 +308,7 @@ public:
QByteArray lexemUntil(Token);
bool until(Token);
- // test for Q_INVOCABLE, Q_SCRIPTABLE, etc. and set the flags
+ // test for Q_INVOKABLE, Q_SCRIPTABLE, etc. and set the flags
// in FunctionDef accordingly
bool testFunctionAttribute(FunctionDef *def);
bool testFunctionAttribute(Token tok, FunctionDef *def);
diff --git a/tools/qscxmlc/moc_patches/generator.cpp.patch b/tools/qscxmlc/moc_patches/generator.cpp.patch
index 21b8fd0..3ecf6e8 100644
--- a/tools/qscxmlc/moc_patches/generator.cpp.patch
+++ b/tools/qscxmlc/moc_patches/generator.cpp.patch
@@ -1,5 +1,5 @@
---- .upstream/generator.cpp 2025-06-23 08:04:34.541288406 +0200
-+++ generator.cpp 2025-08-05 10:52:45.130291770 +0200
+--- .upstream/generator.cpp 2025-12-08 08:44:49.600222497 +0100
++++ generator.cpp 2025-12-08 11:36:34.441647201 +0100
@@ -4,7 +4,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
@@ -40,45 +40,40 @@
static int nameToBuiltinType(const QByteArray &name)
{
if (name.isEmpty())
-@@ -78,21 +103,23 @@
+@@ -78,23 +103,24 @@
return nullptr;
}
-- Generator::Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
+- Generator::Generator(Moc *moc, const ClassDef *classDef, const QList<QByteArray> &metaTypes,
- const QHash<QByteArray, QByteArray> &knownQObjectClasses,
-- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile,
-- bool requireCompleteTypes)
+- const QHash<QByteArray, QByteArray> &knownGadgets,
+- const QHash<QByteArray, QByteArray> &hashes,
+- FILE *outfile, bool requireCompleteTypes)
- : parser(moc),
- out(outfile),
-- cdef(classDef),
-- metaTypes(metaTypes),
-- knownQObjectClasses(knownQObjectClasses),
-- knownGadgets(knownGadgets),
-- requireCompleteTypes(requireCompleteTypes)
-- {
-- if (cdef->superclassList.size())
-- purestSuperClass = cdef->superclassList.constFirst().classname;
+// -- QtScxml
-+Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
++Generator::Generator(const ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ const QHash<QByteArray, QByteArray> &knownQObjectClasses,
+ const QHash<QByteArray, QByteArray> &knownGadgets,
-+ QIODevice &outfile,
-+ bool requireCompleteTypes)
-+ : out(outfile),
-+ cdef(classDef),
-+ metaTypes(metaTypes),
-+ knownQObjectClasses(knownQObjectClasses),
-+ knownGadgets(knownGadgets),
-+ requireCompleteTypes(requireCompleteTypes)
++ const QHash<QByteArray, QByteArray> &hashes,
++ QIODevice &outfile, bool requireCompleteTypes)
++ : out(outfile),
+ cdef(classDef),
+ metaTypes(metaTypes),
+ knownQObjectClasses(knownQObjectClasses),
+ knownGadgets(knownGadgets),
+ hashes(hashes),
+ requireCompleteTypes(requireCompleteTypes)
+- {
+{
-+ if (cdef->superclassList.size())
-+ purestSuperClass = cdef->superclassList.constFirst().classname;
+ if (cdef->superclassList.size())
+ purestSuperClass = cdef->superclassList.constFirst().classname;
}
+// -- QtScxml
static inline qsizetype lengthOfEscapeSequence(const QByteArray &s, qsizetype i)
{
-@@ -119,7 +146,7 @@
+@@ -121,7 +147,7 @@
// Prints \a s to \a out, breaking it into lines of at most ColumnWidth. The
// opening and closing quotes are NOT included (it's up to the caller).
@@ -87,7 +82,7 @@
{
static constexpr int ColumnWidth = 68;
const qsizetype len = s.size();
-@@ -263,8 +290,10 @@
+@@ -248,8 +274,10 @@
bool hasStaticMetaCall =
(cdef->hasQObject || !cdef->methodList.isEmpty()
|| !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
@@ -98,7 +93,7 @@
const QByteArray qualifiedClassNameIdentifier = generateQualifiedClassNameIdentifier(cdef->qualified);
-@@ -525,8 +554,10 @@
+@@ -512,8 +540,10 @@
}
fprintf(out, "}\n");
@@ -109,7 +104,7 @@
//
// Generate internal qt_metacall() function
-@@ -542,7 +573,9 @@
+@@ -529,7 +559,9 @@
//
// Generate plugin meta data
//
@@ -119,7 +114,7 @@
//
// Generate function to make sure the non-class signals exist in the parent classes
-@@ -1011,6 +1044,13 @@
+@@ -1002,6 +1034,13 @@
const FunctionDef &f = methodList.at(methodindex);
Q_ASSERT(!f.normalizedType.isEmpty());
fprintf(out, " case %d: ", methodindex);
@@ -133,7 +128,7 @@
if (f.normalizedType != "void")
fprintf(out, "{ %s _r = ", disambiguatedTypeName(noRef(f.normalizedType)).constData());
fprintf(out, "_t->");
-@@ -1087,6 +1127,10 @@
+@@ -1078,6 +1117,10 @@
const FunctionDef &f = cdef->signalList.at(methodindex);
if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
continue;
@@ -144,7 +139,7 @@
fprintf(out, " if (QtMocHelpers::indexOfMethod<%s (%s::*)(",
f.type.rawName.constData() , cdef->classname.constData());
-@@ -1105,7 +1149,7 @@
+@@ -1096,7 +1139,7 @@
}
fprintf(out, ")%s>(_a, &%s::%s, %d))\n",
f.isConst ? " const" : "",
@@ -153,7 +148,7 @@
fprintf(out, " return;\n");
}
fprintf(out, " }\n");
-@@ -1182,9 +1226,12 @@
+@@ -1173,9 +1216,12 @@
propindex, cxxTypeTag(p.typeTag), disambiguatedTypeName(p.type, p.typeTag).constData(),
prefix.constData(), p.bind.constData());
else if (!p.read.isEmpty())
@@ -168,7 +163,7 @@
else
fprintf(out, " case %d: *reinterpret_cast<%s%s*>(_v) = %s%s; break;\n",
propindex, cxxTypeTag(p.typeTag), disambiguatedTypeName(p.type, p.typeTag).constData(),
-@@ -1303,6 +1350,10 @@
+@@ -1294,6 +1340,10 @@
{
if (def->wasCloned || def->isAbstract)
return;
@@ -179,7 +174,7 @@
fprintf(out, "\n// SIGNAL %d\n%s %s::%s(",
index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData());
-@@ -1364,6 +1415,36 @@
+@@ -1355,6 +1405,36 @@
fprintf(out, "}\n");
}
@@ -216,7 +211,7 @@
static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v);
static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o)
{
-@@ -1491,6 +1572,8 @@
+@@ -1482,6 +1562,8 @@
fputs("\n", out);
}
@@ -225,7 +220,7 @@
QByteArray Generator::disambiguatedTypeName(const QByteArray &name)
{
-@@ -1524,4 +1607,6 @@
+@@ -1515,4 +1597,6 @@
QT_END_NAMESPACE
diff --git a/tools/qscxmlc/moc_patches/generator.h.patch b/tools/qscxmlc/moc_patches/generator.h.patch
index cc0cab6..7e45c84 100644
--- a/tools/qscxmlc/moc_patches/generator.h.patch
+++ b/tools/qscxmlc/moc_patches/generator.h.patch
@@ -1,6 +1,6 @@
---- .upstream/generator.h 2025-06-20 07:16:49.211901974 +0200
-+++ generator.h 2025-08-05 10:37:10.298870121 +0200
-@@ -6,23 +6,34 @@
+--- .upstream/generator.h 2025-12-08 08:44:49.600222497 +0100
++++ generator.h 2025-12-08 11:38:46.170083870 +0100
+@@ -6,24 +6,35 @@
#include "moc.h"
@@ -17,17 +17,18 @@
- Moc *parser = nullptr;
- FILE *out;
+ QIODevice &out; // -- QtScxml
- ClassDef *cdef;
+ const ClassDef *cdef;
QList<uint> meta_data;
public:
-- Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
-+ Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+- Generator(Moc *moc, const ClassDef *classDef, const QList<QByteArray> &metaTypes,
++ Generator(const ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
-- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr,
-+ const QHash<QByteArray, QByteArray> &knownGadgets,
+ const QHash<QByteArray, QByteArray> &knownGadgets,
+ const QHash<QByteArray, QByteArray> &hashes,
+- FILE *outfile = nullptr, bool requireCompleteTypes = false);
+ QIODevice &outfile, // -- QtScxml
- bool requireCompleteTypes = false);
++ bool requireCompleteTypes = false);
void generateCode();
qsizetype registeredStringsCount() { return strings.size(); }
@@ -39,7 +40,7 @@
private:
bool registerableMetaType(const QByteArray &propertyType);
void registerClassInfoStrings();
-@@ -39,7 +50,9 @@
+@@ -40,7 +51,9 @@
void generateMetacall();
void generateStaticMetacall();
void generateSignal(const FunctionDef *def, int index);
diff --git a/tools/qscxmlc/moc_patches/moc.cpp.patch b/tools/qscxmlc/moc_patches/moc.cpp.patch
index f048095..c32b7ed 100644
--- a/tools/qscxmlc/moc_patches/moc.cpp.patch
+++ b/tools/qscxmlc/moc_patches/moc.cpp.patch
@@ -1,6 +1,6 @@
---- .upstream/moc.cpp 2025-08-05 10:30:37.641278729 +0200
-+++ moc.cpp 2025-08-05 10:35:50.718576253 +0200
-@@ -12,15 +12,15 @@
+--- .upstream/moc.cpp 2025-12-08 08:44:49.600222497 +0100
++++ moc.cpp 2025-12-08 11:47:45.363161643 +0100
+@@ -12,19 +12,15 @@
#include <QtCore/qdir.h>
#include <QtCore/qjsondocument.h>
@@ -8,6 +8,10 @@
-#include <private/qmetaobject_p.h>
-#include <private/qmetaobject_moc_p.h>
-#include <private/qduplicatetracker_p.h>
+-
+-// This is a bootstrapped tool, so we can't rely on QCryptographicHash for the
+-// faster SHA1 implementations from OpenSSL.
+-#include "../../3rdparty/sha1/sha1.cpp"
+// -- QtScxml
+#include <QtCore/qjsonobject.h>
+// -- QtScxml
@@ -20,7 +24,7 @@
// only moc needs this function
static QByteArray normalizeType(const QByteArray &ba)
{
-@@ -2046,6 +2046,7 @@
+@@ -2131,6 +2127,7 @@
}
}
}
@@ -28,7 +32,7 @@
QJsonObject ClassDef::toJson() const
{
-@@ -2242,8 +2243,8 @@
+@@ -2329,8 +2326,8 @@
def["alias"_L1] = QString::fromUtf8(enumName);
if (!type.isEmpty())
def["type"_L1] = QString::fromUtf8(type);
diff --git a/tools/qscxmlc/moc_patches/moc.h.patch b/tools/qscxmlc/moc_patches/moc.h.patch
index 39d433d..af29acf 100644
--- a/tools/qscxmlc/moc_patches/moc.h.patch
+++ b/tools/qscxmlc/moc_patches/moc.h.patch
@@ -1,5 +1,5 @@
---- .upstream/moc.h 2025-07-04 08:47:51.556486285 +0200
-+++ moc.h 2025-08-05 10:35:50.722576269 +0200
+--- .upstream/moc.h 2025-12-08 08:44:49.600222497 +0100
++++ moc.h 2025-12-08 11:22:49.550907139 +0100
@@ -4,15 +4,13 @@
#ifndef MOC_H
#define MOC_H
@@ -68,7 +68,7 @@
};
Q_DECLARE_TYPEINFO(FunctionDef, Q_RELOCATABLE_TYPE);
-@@ -137,6 +143,10 @@
+@@ -139,6 +145,10 @@
qsizetype location = -1; // token index, used for error reporting
QJsonObject toJson() const;
@@ -79,7 +79,7 @@
};
Q_DECLARE_TYPEINFO(PropertyDef, Q_RELOCATABLE_TYPE);
-@@ -219,6 +229,7 @@
+@@ -222,6 +232,7 @@
};
Q_DECLARE_TYPEINFO(NamespaceDef, Q_RELOCATABLE_TYPE);
@@ -87,7 +87,7 @@
class Moc : public Parser
{
public:
-@@ -309,6 +320,7 @@
+@@ -312,6 +323,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 8e1f746..8f652f6 100644
--- a/tools/qscxmlc/moc_patches/outputrevision.h.patch
+++ b/tools/qscxmlc/moc_patches/outputrevision.h.patch
@@ -1,5 +1,5 @@
--- .upstream/outputrevision.h 2024-11-15 07:24:09.762842614 +0100
-+++ outputrevision.h 2025-08-05 10:35:50.714576239 +0200
++++ outputrevision.h 2025-12-08 11:22:49.542907112 +0100
@@ -4,7 +4,13 @@
#ifndef OUTPUTREVISION_H
#define OUTPUTREVISION_H
diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp
index be6ce7e..4f406c8 100644
--- a/tools/qscxmlc/scxmlcppdumper.cpp
+++ b/tools/qscxmlc/scxmlcppdumper.cpp
@@ -3,12 +3,14 @@
#include "scxmlcppdumper.h"
#include "generator.h"
+#include "../../src/3rdparty/sha1/sha1.cpp"
#include <QtScxml/private/qscxmlexecutablecontent_p.h>
-#include <QtCore/qfileinfo.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qjsonobject.h>
#include <QtCore/qresource.h>
#include <algorithm>
@@ -723,6 +725,24 @@ QString CppDumper::generateSignalDecls(const GeneratedTableData::MetaDataInfo &i
return decls;
}
+QByteArray classDefJsonObjectHash(const QJsonObject &object)
+{
+ const QByteArray json = QJsonDocument(object).toJson(QJsonValue::JsonFormat::Compact);
+ QByteArray hash(20, 0); // SHA1 produces 160 bits of data
+
+ {
+ Sha1State state;
+ sha1InitState(&state);
+ sha1Update(&state, reinterpret_cast<const uchar *>(json.constData()), json.size());
+ sha1FinalizeState(&state);
+ sha1ToHash(&state, reinterpret_cast<uchar *>(hash.data()));
+ }
+
+ static const char revisionPrefix[] = "0$";
+ const QByteArray hashB64 = hash.toBase64(QByteArray::OmitTrailingEquals);
+ return revisionPrefix + hashB64;
+}
+
QString CppDumper::generateMetaObject(const QString &className,
const GeneratedTableData::MetaDataInfo &info)
{
@@ -793,10 +813,16 @@ QString CppDumper::generateMetaObject(const QString &className,
QHash<QByteArray, QByteArray> knownQObjectClasses;
knownQObjectClasses.insert(QByteArray("QScxmlStateMachine"), QByteArray());
+ QHash<QByteArray, QJsonObject> classDefJsonObjects;
+ QHash<QByteArray, QByteArray> metaObjectHashes;
+ const QJsonObject jsonObject = classDef.toJson();
+ classDefJsonObjects.insert(classDef.qualified, jsonObject);
+ metaObjectHashes.insert(classDef.qualified, classDefJsonObjectHash(jsonObject));
+
QBuffer buf;
buf.open(QIODevice::WriteOnly);
Generator generator(&classDef, QList<QByteArray>(), knownQObjectClasses,
- QHash<QByteArray, QByteArray>(), buf);
+ QHash<QByteArray, QByteArray>(), metaObjectHashes, buf);
generator.generateCode();
if (m_translationUnit->stateMethods) {
generator.generateAccessorDefs();