summaryrefslogtreecommitdiffstats
path: root/src/tools/moc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/moc')
-rw-r--r--src/tools/moc/CMakeLists.txt14
-rw-r--r--src/tools/moc/cbordevice.h2
-rw-r--r--src/tools/moc/collectjson.cpp2
-rw-r--r--src/tools/moc/generator.cpp461
-rw-r--r--src/tools/moc/generator.h7
-rw-r--r--src/tools/moc/keywords.cpp394
-rw-r--r--src/tools/moc/main.cpp30
-rw-r--r--src/tools/moc/moc.cpp392
-rw-r--r--src/tools/moc/moc.h48
-rw-r--r--src/tools/moc/parser.cpp76
-rw-r--r--src/tools/moc/parser.h11
-rw-r--r--src/tools/moc/preprocessor.cpp103
-rw-r--r--src/tools/moc/preprocessor.h9
-rw-r--r--src/tools/moc/symbols.h107
-rw-r--r--src/tools/moc/token.h2
-rwxr-xr-xsrc/tools/moc/util/generate.sh4
-rw-r--r--src/tools/moc/util/generate_keywords.cpp2
-rw-r--r--src/tools/moc/util/licenseheader.cpp.in (renamed from src/tools/moc/util/licenseheader.txt)0
-rw-r--r--src/tools/moc/utils.h42
19 files changed, 942 insertions, 764 deletions
diff --git a/src/tools/moc/CMakeLists.txt b/src/tools/moc/CMakeLists.txt
index 7593ef528c..b98b7ab4e9 100644
--- a/src/tools/moc/CMakeLists.txt
+++ b/src/tools/moc/CMakeLists.txt
@@ -1,7 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-# Generated from moc.pro.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## moc Tool:
@@ -9,10 +7,11 @@
qt_get_tool_target_name(target_name moc)
qt_internal_add_tool(${target_name}
+ TRY_RUN
CORE_LIBRARY Bootstrap
TARGET_DESCRIPTION "Qt Meta Object Compiler"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
cbordevice.h
collectjson.cpp collectjson.h
@@ -22,7 +21,6 @@ qt_internal_add_tool(${target_name}
outputrevision.h
parser.cpp parser.h
preprocessor.cpp preprocessor.h
- # qdatetime_p.h special case remove
symbols.h
token.cpp token.h
utils.h
@@ -31,6 +29,8 @@ qt_internal_add_tool(${target_name}
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_FROM_BYTEARRAY
QT_NO_FOREACH
+ QT_NO_QPAIR
+ QT_USE_NODISCARD_FILE_OPEN
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
../../3rdparty/tinycbor/src
@@ -38,10 +38,6 @@ qt_internal_add_tool(${target_name}
)
qt_internal_return_unless_building_tools()
-#### Keys ignored in scope 1:.:.:moc.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt Meta Object Compiler"
-# _OPTION = "host_build"
-
## Scopes:
#####################################################################
diff --git a/src/tools/moc/cbordevice.h b/src/tools/moc/cbordevice.h
index f221968911..7668e4c0be 100644
--- a/src/tools/moc/cbordevice.h
+++ b/src/tools/moc/cbordevice.h
@@ -4,6 +4,8 @@
#ifndef CBORDEVICE_H
#define CBORDEVICE_H
+#include <QtCore/qtypes.h>
+
#include <memory>
#include <stdio.h>
diff --git a/src/tools/moc/collectjson.cpp b/src/tools/moc/collectjson.cpp
index c0a4b64d7e..d542e2abc4 100644
--- a/src/tools/moc/collectjson.cpp
+++ b/src/tools/moc/collectjson.cpp
@@ -60,7 +60,7 @@ int collectJson(const QStringList &jsonFiles, const QString &outputFile, bool sk
QStringList jsonFilesSorted = jsonFiles;
jsonFilesSorted.sort();
- for (const QString &jsonFile : qAsConst(jsonFilesSorted)) {
+ for (const QString &jsonFile : std::as_const(jsonFilesSorted)) {
QFile f(jsonFile);
if (!f.open(QIODevice::ReadOnly)) {
fprintf(stderr, "Error opening %s for reading\n", qPrintable(jsonFile));
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index e9e5f167b7..02e9ef178a 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -23,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
uint nameToBuiltinType(const QByteArray &name)
{
if (name.isEmpty())
@@ -55,11 +57,12 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
return nullptr;
}
- Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ Generator::Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile,
bool requireCompleteTypes)
- : out(outfile),
+ : parser(moc),
+ out(outfile),
cdef(classDef),
metaTypes(metaTypes),
knownQObjectClasses(knownQObjectClasses),
@@ -67,62 +70,49 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
requireCompleteTypes(requireCompleteTypes)
{
if (cdef->superclassList.size())
- purestSuperClass = cdef->superclassList.constFirst().first;
+ purestSuperClass = cdef->superclassList.constFirst().classname;
}
-static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
+static inline qsizetype lengthOfEscapeSequence(const QByteArray &s, qsizetype i)
{
- if (s.at(i) != '\\' || i >= s.length() - 1)
+ if (s.at(i) != '\\' || i >= s.size() - 1)
return 1;
- const int startPos = i;
+ const qsizetype startPos = i;
++i;
char ch = s.at(i);
if (ch == 'x') {
++i;
- while (i < s.length() && is_hex_char(s.at(i)))
+ while (i < s.size() && isHexDigit(s.at(i)))
++i;
- } else if (is_octal_char(ch)) {
+ } else if (isOctalDigit(ch)) {
while (i < startPos + 4
- && i < s.length()
- && is_octal_char(s.at(i))) {
+ && i < s.size()
+ && isOctalDigit(s.at(i))) {
++i;
}
} else { // single character escape sequence
- i = qMin(i + 1, s.length());
+ i = qMin(i + 1, s.size());
}
return i - startPos;
}
-static inline uint lengthOfEscapedString(const QByteArray &str)
-{
- int extra = 0;
- for (int j = 0; j < str.length(); ++j) {
- if (str.at(j) == '\\') {
- int cnt = lengthOfEscapeSequence(str, j) - 1;
- extra += cnt;
- j += cnt;
- }
- }
- return str.length() - extra;
-}
-
// 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).
static void printStringWithIndentation(FILE *out, const QByteArray &s)
{
static constexpr int ColumnWidth = 72;
- int len = s.length();
- int idx = 0;
+ const qsizetype len = s.size();
+ qsizetype idx = 0;
do {
- int spanLen = qMin(ColumnWidth - 2, len - idx);
+ qsizetype spanLen = qMin(ColumnWidth - 2, len - idx);
// don't cut escape sequences at the end of a line
- int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
+ const qsizetype backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
if (backSlashPos >= idx) {
- int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
+ const qsizetype escapeLen = lengthOfEscapeSequence(s, backSlashPos);
spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, len - idx);
}
- fprintf(out, "\n \"%.*s\"", spanLen, s.constData() + idx);
+ fprintf(out, "\n \"%.*s\"", int(spanLen), s.constData() + idx);
idx += spanLen;
} while (idx < len);
}
@@ -135,7 +125,7 @@ void Generator::strreg(const QByteArray &s)
int Generator::stridx(const QByteArray &s)
{
- int i = strings.indexOf(s);
+ int i = int(strings.indexOf(s));
Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings");
return i;
}
@@ -146,8 +136,8 @@ int Generator::stridx(const QByteArray &s)
static int aggregateParameterCount(const QList<FunctionDef> &list)
{
int sum = 0;
- for (int i = 0; i < list.count(); ++i)
- sum += list.at(i).arguments.count() + 1; // +1 for return type
+ for (const FunctionDef &def : list)
+ sum += int(def.arguments.size()) + 1; // +1 for return type
return sum;
}
@@ -184,14 +174,14 @@ bool Generator::registerableMetaType(const QByteArray &propertyType)
#undef STREAM_1ARG_TEMPLATE
;
for (const QByteArray &oneArgTemplateType : oneArgTemplates) {
- QByteArray ba = oneArgTemplateType + "<";
+ const QByteArray ba = oneArgTemplateType + "<";
if (propertyType.startsWith(ba) && propertyType.endsWith(">")) {
- const int argumentSize = propertyType.size() - oneArgTemplateType.size() - 1
+ const qsizetype argumentSize = propertyType.size() - ba.size()
// The closing '>'
- 1
// templates inside templates have an extra whitespace char to strip.
- (propertyType.at(propertyType.size() - 2) == ' ' ? 1 : 0 );
- const QByteArray templateArg = propertyType.mid(oneArgTemplateType.size() + 1, argumentSize);
+ const QByteArray templateArg = propertyType.sliced(ba.size(), argumentSize);
return isBuiltinType(templateArg) || registerableMetaType(templateArg);
}
}
@@ -204,12 +194,28 @@ static bool qualifiedNameEquals(const QByteArray &qualifiedName, const QByteArra
{
if (qualifiedName == name)
return true;
- int index = qualifiedName.indexOf("::");
+ const qsizetype index = qualifiedName.indexOf("::");
if (index == -1)
return false;
return qualifiedNameEquals(qualifiedName.mid(index+2), name);
}
+static QByteArray generateQualifiedClassNameIdentifier(const QByteArray &identifier)
+{
+ QByteArray qualifiedClassNameIdentifier = identifier;
+
+ // Remove ':'s in the name, but be sure not to create any illegal
+ // identifiers in the process. (Don't replace with '_', because
+ // that will create problems with things like NS_::_class.)
+ qualifiedClassNameIdentifier.replace("::", "SCOPE");
+
+ // Also, avoid any leading/trailing underscores (we'll concatenate
+ // the generated name with other prefixes/suffixes, and these latter
+ // may already include an underscore, leading to two underscores)
+ qualifiedClassNameIdentifier = "CLASS" + qualifiedClassNameIdentifier + "ENDCLASS";
+ return qualifiedClassNameIdentifier;
+}
+
void Generator::generateCode()
{
bool isQObject = (cdef->classname == "QObject");
@@ -218,8 +224,7 @@ void Generator::generateCode()
// filter out undeclared enumerators and sets
{
QList<EnumDef> enumList;
- for (int i = 0; i < cdef->enumList.count(); ++i) {
- EnumDef def = cdef->enumList.at(i);
+ for (EnumDef def : std::as_const(cdef->enumList)) {
if (cdef->enumDeclarations.contains(def.name)) {
enumList += def;
}
@@ -250,8 +255,7 @@ void Generator::generateCode()
(cdef->hasQObject || !cdef->methodList.isEmpty()
|| !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
- QByteArray qualifiedClassNameIdentifier = cdef->qualified;
- qualifiedClassNameIdentifier.replace(':', '_');
+ const QByteArray qualifiedClassNameIdentifier = generateQualifiedClassNameIdentifier(cdef->qualified);
// ensure the qt_meta_stringdata_XXXX_t type is local
fprintf(out, "namespace {\n");
@@ -262,7 +266,7 @@ void Generator::generateCode()
fprintf(out, "\n#ifdef QT_MOC_HAS_STRINGDATA\n"
"struct qt_meta_stringdata_%s_t {};\n"
- "static constexpr auto qt_meta_stringdata_%s = QtMocHelpers::stringData(",
+ "constexpr auto qt_meta_stringdata_%s = QtMocHelpers::stringData(",
qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
{
char comma = 0;
@@ -274,61 +278,9 @@ void Generator::generateCode()
}
}
fprintf(out, "\n);\n"
- "#else // !QT_MOC_HAS_STRING_DATA\n");
-
-#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
+ "#else // !QT_MOC_HAS_STRINGDATA\n");
fprintf(out, "#error \"qtmochelpers.h not found or too old.\"\n");
-#else
-//
-// Build stringdata struct
-//
-
- fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
- fprintf(out, " uint offsetsAndSizes[%d];\n", int(strings.size() * 2));
- for (int i = 0; i < strings.size(); ++i) {
- int thisLength = lengthOfEscapedString(strings.at(i)) + 1;
- fprintf(out, " char stringdata%d[%d];\n", i, thisLength);
- }
- fprintf(out, "};\n");
-
- // Macro that simplifies the string data listing. The offset is calculated
- // from the top of the stringdata object (i.e., past the uints).
- fprintf(out, "#define QT_MOC_LITERAL(ofs, len) \\\n"
- " uint(sizeof(qt_meta_stringdata_%s_t::offsetsAndSizes) + ofs), len \n",
- qualifiedClassNameIdentifier.constData());
-
- fprintf(out, "Q_CONSTINIT static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n",
- qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
- fprintf(out, " {");
- {
- int idx = 0;
- for (int i = 0; i < strings.size(); ++i) {
- const QByteArray &str = strings.at(i);
- const QByteArray comment = str.length() > 32 ? str.left(29) + "..." : str;
- const char *comma = (i != strings.size() - 1 ? "," : " ");
- int len = lengthOfEscapedString(str);
- fprintf(out, "\n QT_MOC_LITERAL(%d, %d)%s // \"%s\"", idx, len, comma,
- comment.constData());
-
- idx += len + 1;
- }
- fprintf(out, "\n }");
- }
-
-//
-// Build stringdata arrays
-//
- for (const QByteArray &s : qAsConst(strings)) {
- fputc(',', out);
- printStringWithIndentation(out, s);
- }
-
-// Terminate stringdata struct
- fprintf(out, "\n};\n");
- fprintf(out, "#undef QT_MOC_LITERAL\n");
-#endif // Qt 6.9
-
- fprintf(out, "#endif // !QT_MOC_HAS_STRING_DATA\n");
+ fprintf(out, "#endif // !QT_MOC_HAS_STRINGDATA\n");
fprintf(out, "} // unnamed namespace\n\n");
//
@@ -340,11 +292,17 @@ void Generator::generateCode()
fprintf(out, "\n // content:\n");
fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision));
fprintf(out, " %4d, // classname\n", stridx(cdef->qualified));
- fprintf(out, " %4d, %4d, // classinfo\n", int(cdef->classInfoList.count()), int(cdef->classInfoList.count() ? index : 0));
- index += cdef->classInfoList.count() * 2;
+ fprintf(out, " %4d, %4d, // classinfo\n", int(cdef->classInfoList.size()), int(cdef->classInfoList.size() ? index : 0));
+ index += cdef->classInfoList.size() * 2;
+
+ qsizetype methodCount = 0;
+ if (qAddOverflow(cdef->signalList.size(), cdef->slotList.size(), &methodCount)
+ || qAddOverflow(cdef->methodList.size(), methodCount, &methodCount)) {
+ parser->error("internal limit exceeded: the total number of member functions"
+ " (including signals and slots) is too big.");
+ }
- int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
- fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
+ fprintf(out, " %4" PRIdQSIZETYPE ", %4d, // methods\n", methodCount, methodCount ? index : 0);
index += methodCount * QMetaObjectPrivate::IntsPerMethod;
if (cdef->revisionedMethods)
index += methodCount;
@@ -355,16 +313,17 @@ void Generator::generateCode()
+ aggregateParameterCount(cdef->constructorList);
index += totalParameterCount * 2 // types and parameter names
- methodCount // return "parameters" don't have names
- - cdef->constructorList.count(); // "this" parameters don't have names
+ - int(cdef->constructorList.size()); // "this" parameters don't have names
- fprintf(out, " %4d, %4d, // properties\n", int(cdef->propertyList.count()), int(cdef->propertyList.count() ? index : 0));
- index += cdef->propertyList.count() * QMetaObjectPrivate::IntsPerProperty;
- fprintf(out, " %4d, %4d, // enums/sets\n", int(cdef->enumList.count()), cdef->enumList.count() ? index : 0);
+ fprintf(out, " %4d, %4d, // properties\n", int(cdef->propertyList.size()), int(cdef->propertyList.size() ? index : 0));
+ index += cdef->propertyList.size() * QMetaObjectPrivate::IntsPerProperty;
+ fprintf(out, " %4d, %4d, // enums/sets\n", int(cdef->enumList.size()), cdef->enumList.size() ? index : 0);
int enumsIndex = index;
- for (int i = 0; i < cdef->enumList.count(); ++i)
- index += 5 + (cdef->enumList.at(i).values.count() * 2);
- fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? int(cdef->constructorList.count()) : 0,
+ for (const EnumDef &def : std::as_const(cdef->enumList))
+ index += QMetaObjectPrivate::IntsPerEnum + (def.values.size() * 2);
+
+ fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? int(cdef->constructorList.size()) : 0,
isConstructible ? index : 0);
int flags = 0;
@@ -374,7 +333,7 @@ void Generator::generateCode()
flags |= PropertyAccessInStaticMetaCall;
}
fprintf(out, " %4d, // flags\n", flags);
- fprintf(out, " %4d, // signalCount\n", int(cdef->signalList.count()));
+ fprintf(out, " %4d, // signalCount\n", int(cdef->signalList.size()));
//
@@ -382,8 +341,14 @@ void Generator::generateCode()
//
generateClassInfos();
- // all property metatypes, + 1 for the type of the current class itself
- int initialMetaTypeOffset = cdef->propertyList.count() + 1;
+ qsizetype propEnumCount = 0;
+ // all property metatypes + all enum metatypes + 1 for the type of the current class itself
+ if (qAddOverflow(cdef->propertyList.size(), cdef->enumList.size(), &propEnumCount)
+ || qAddOverflow(propEnumCount, qsizetype(1), &propEnumCount)
+ || propEnumCount >= std::numeric_limits<int>::max()) {
+ parser->error("internal limit exceeded: number of property and enum metatypes is too big.");
+ }
+ int initialMetaTypeOffset = int(propEnumCount);
//
// Build signals array first, otherwise the signal indices would be wrong
@@ -446,15 +411,14 @@ void Generator::generateCode()
QMultiHash<QByteArray, QByteArray> knownExtraMetaObject(knownGadgets);
knownExtraMetaObject.unite(knownQObjectClasses);
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
if (isBuiltinType(p.type))
continue;
if (p.type.contains('*') || p.type.contains('<') || p.type.contains('>'))
continue;
- int s = p.type.lastIndexOf("::");
+ const qsizetype s = p.type.lastIndexOf("::");
if (s <= 0)
continue;
@@ -465,7 +429,7 @@ void Generator::generateCode()
QByteArray thisScope = cdef->qualified;
do {
- int s = thisScope.lastIndexOf("::");
+ const qsizetype s = thisScope.lastIndexOf("::");
thisScope = thisScope.left(s);
QByteArray currentScope = thisScope.isEmpty() ? unqualifiedScope : thisScope + "::" + unqualifiedScope;
scopeIt = knownExtraMetaObject.constFind(currentScope);
@@ -491,7 +455,7 @@ void Generator::generateCode()
for (auto it = cdef->enumDeclarations.keyBegin(),
end = cdef->enumDeclarations.keyEnd(); it != end; ++it) {
const QByteArray &enumKey = *it;
- int s = enumKey.lastIndexOf("::");
+ const qsizetype s = enumKey.lastIndexOf("::");
if (s > 0) {
QByteArray scope = enumKey.left(s);
if (scope != "Qt" && !qualifiedNameEquals(cdef->qualified, scope) && !extraList.contains(scope))
@@ -506,9 +470,9 @@ void Generator::generateCode()
if (!extraList.isEmpty()) {
fprintf(out, "Q_CONSTINIT static const QMetaObject::SuperData qt_meta_extradata_%s[] = {\n",
qualifiedClassNameIdentifier.constData());
- for (int i = 0; i < extraList.count(); ++i) {
- fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", extraList.at(i).constData());
- }
+ for (const QByteArray &ba : std::as_const(extraList))
+ fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", ba.constData());
+
fprintf(out, " nullptr\n};\n\n");
}
@@ -554,13 +518,19 @@ void Generator::generateCode()
fprintf(out, " qt_metaTypeArray<");
}
// metatypes for properties
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
fprintf(out, "%s\n // property '%s'\n %s",
comma, p.name.constData(), stringForType(p.type, true).constData());
comma = ",";
}
+ // metatypes for enums
+ for (const EnumDef &e : std::as_const(cdef->enumList)) {
+ fprintf(out, "%s\n // enum '%s'\n %s",
+ comma, e.name.constData(), stringForType(e.qualifiedType(cdef), true).constData());
+ comma = ",";
+ }
+
// type name for the Q_OJBECT/GADGET itself, void for namespaces
auto ownType = !cdef->hasQNamespace ? cdef->classname.data() : "void";
fprintf(out, "%s\n // Q_OBJECT / Q_GADGET\n %s",
@@ -569,10 +539,9 @@ void Generator::generateCode()
// metatypes for all exposed methods
// because we definitely printed something above, this section doesn't need comma control
- for (const QList<FunctionDef> &methodContainer :
- { cdef->signalList, cdef->slotList, cdef->methodList }) {
- for (int i = 0; i< methodContainer.count(); ++i) {
- const FunctionDef& fdef = methodContainer.at(i);
+ const auto allMethods = {&cdef->signalList, &cdef->slotList, &cdef->methodList};
+ for (const QList<FunctionDef> *methodContainer : allMethods) {
+ for (const FunctionDef &fdef : *methodContainer) {
fprintf(out, ",\n // method '%s'\n %s",
fdef.name.constData(), stringForType(fdef.type.name, false).constData());
for (const auto &argument: fdef.arguments)
@@ -581,8 +550,7 @@ void Generator::generateCode()
}
// but constructors have no return types, so this needs comma control again
- for (int i = 0; i< cdef->constructorList.count(); ++i) {
- const FunctionDef& fdef = cdef->constructorList.at(i);
+ for (const FunctionDef &fdef : std::as_const(cdef->constructorList)) {
if (fdef.arguments.isEmpty())
continue;
@@ -619,18 +587,24 @@ void Generator::generateCode()
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata0))\n"
" return static_cast<void*>(this);\n",
qualifiedClassNameIdentifier.constData());
- for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
- if (cdef->superclassList.at(i).second == FunctionDef::Private)
- continue;
- const char *cname = cdef->superclassList.at(i).first.constData();
- fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(this);\n",
- cname, cname);
+
+ // for all superclasses but the first one
+ if (cdef->superclassList.size() > 1) {
+ auto it = cdef->superclassList.cbegin() + 1;
+ const auto end = cdef->superclassList.cend();
+ for (; it != end; ++it) {
+ if (it->access == FunctionDef::Private)
+ continue;
+ const char *cname = it->classname.constData();
+ fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(this);\n",
+ cname, cname);
+ }
}
- for (int i = 0; i < cdef->interfaceList.size(); ++i) {
- const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i);
- for (int j = 0; j < iface.size(); ++j) {
+
+ for (const QList<ClassDef::Interface> &iface : std::as_const(cdef->interfaceList)) {
+ for (qsizetype j = 0; j < iface.size(); ++j) {
fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData());
- for (int k = j; k >= 0; --k)
+ for (qsizetype k = j; k >= 0; --k)
fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData());
fprintf(out, "this%s;\n", QByteArray(j + 1, ')').constData());
}
@@ -651,8 +625,8 @@ void Generator::generateCode()
//
// Generate internal signal functions
//
- for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
- generateSignal(&cdef->signalList[signalindex], signalindex);
+ for (int signalindex = 0; signalindex < int(cdef->signalList.size()); ++signalindex)
+ generateSignal(&cdef->signalList.at(signalindex), signalindex);
//
// Generate plugin meta data
@@ -663,12 +637,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 : qAsConst(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");
}
}
@@ -676,8 +667,7 @@ void Generator::generateCode()
void Generator::registerClassInfoStrings()
{
- for (int i = 0; i < cdef->classInfoList.size(); ++i) {
- const ClassInfoDef &c = cdef->classInfoList.at(i);
+ for (const ClassInfoDef &c : std::as_const(cdef->classInfoList)) {
strreg(c.name);
strreg(c.value);
}
@@ -690,25 +680,19 @@ void Generator::generateClassInfos()
fprintf(out, "\n // classinfo: key, value\n");
- for (int i = 0; i < cdef->classInfoList.size(); ++i) {
- const ClassInfoDef &c = cdef->classInfoList.at(i);
+ for (const ClassInfoDef &c : std::as_const(cdef->classInfoList))
fprintf(out, " %4d, %4d,\n", stridx(c.name), stridx(c.value));
- }
}
void Generator::registerFunctionStrings(const QList<FunctionDef> &list)
{
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
-
+ for (const FunctionDef &f : list) {
strreg(f.name);
if (!isBuiltinType(f.normalizedType))
strreg(f.normalizedType);
strreg(f.tag);
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
+ for (const ArgumentDef &a : f.arguments) {
if (!isBuiltinType(a.normalizedType))
strreg(a.normalizedType);
strreg(a.name);
@@ -729,9 +713,7 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
return;
fprintf(out, "\n // %ss: name, argc, parameters, tag, flags, initial metatype offsets\n", functype);
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
-
+ for (const FunctionDef &f : list) {
QByteArray comment;
uint flags = type;
if (f.access == FunctionDef::Private) {
@@ -766,7 +748,7 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
comment.append(" | MethodIsConst ");
}
- int argc = f.arguments.count();
+ const int argc = int(f.arguments.size());
fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x, %4d /* %s */,\n",
stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, initialMetatypeOffset, comment.constData());
@@ -778,12 +760,10 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
void Generator::generateFunctionRevisions(const QList<FunctionDef> &list, const char *functype)
{
- if (list.count())
+ if (list.size())
fprintf(out, "\n // %ss: revision\n", functype);
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
+ for (const FunctionDef &f : list)
fprintf(out, " %4d,\n", f.revision);
- }
}
void Generator::generateFunctionParameters(const QList<FunctionDef> &list, const char *functype)
@@ -791,25 +771,22 @@ void Generator::generateFunctionParameters(const QList<FunctionDef> &list, const
if (list.isEmpty())
return;
fprintf(out, "\n // %ss: parameters\n", functype);
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
+ for (const FunctionDef &f : list) {
fprintf(out, " ");
// Types
- int argsCount = f.arguments.count();
- for (int j = -1; j < argsCount; ++j) {
- if (j > -1)
- fputc(' ', out);
- const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
- generateTypeInfo(typeName, /*allowEmptyName=*/f.isConstructor);
+ const bool allowEmptyName = f.isConstructor;
+ generateTypeInfo(f.normalizedType, allowEmptyName);
+ fputc(',', out);
+ for (const ArgumentDef &arg : f.arguments) {
+ fputc(' ', out);
+ generateTypeInfo(arg.normalizedType, allowEmptyName);
fputc(',', out);
}
// Parameter names
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &arg = f.arguments.at(j);
+ for (const ArgumentDef &arg : f.arguments)
fprintf(out, " %4d,", stridx(arg.name));
- }
fprintf(out, "\n");
}
@@ -842,8 +819,7 @@ void Generator::generateTypeInfo(const QByteArray &typeName, bool allowEmptyName
void Generator::registerPropertyStrings()
{
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
strreg(p.name);
if (!isBuiltinType(p.type))
strreg(p.type);
@@ -856,10 +832,9 @@ void Generator::generateProperties()
// Create meta data
//
- if (cdef->propertyList.count())
+ if (cdef->propertyList.size())
fprintf(out, "\n // properties: name, type, flags\n");
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
uint flags = Invalid;
if (!isBuiltinType(p.type))
flags |= EnumOrFlag;
@@ -903,7 +878,7 @@ void Generator::generateProperties()
int notifyId = p.notifyId;
if (p.notifyId < -1) {
// signal is in parent class
- const int indexInStrings = strings.indexOf(p.notify);
+ const int indexInStrings = int(strings.indexOf(p.notify));
notifyId = indexInStrings | IsUnresolvedSignal;
}
fprintf(out, ", 0x%.8x, uint(%d), %d,\n", flags, notifyId, p.revision);
@@ -912,13 +887,12 @@ void Generator::generateProperties()
void Generator::registerEnumStrings()
{
- for (int i = 0; i < cdef->enumList.count(); ++i) {
- const EnumDef &e = cdef->enumList.at(i);
+ for (const EnumDef &e : std::as_const(cdef->enumList)) {
strreg(e.name);
if (!e.enumName.isNull())
strreg(e.enumName);
- for (int j = 0; j < e.values.count(); ++j)
- strreg(e.values.at(j));
+ for (const QByteArray &val : e.values)
+ strreg(val);
}
}
@@ -928,9 +902,9 @@ void Generator::generateEnums(int index)
return;
fprintf(out, "\n // enums: name, alias, flags, count, data\n");
- index += 5 * cdef->enumList.count();
+ index += QMetaObjectPrivate::IntsPerEnum * cdef->enumList.size();
int i;
- for (i = 0; i < cdef->enumList.count(); ++i) {
+ for (i = 0; i < cdef->enumList.size(); ++i) {
const EnumDef &e = cdef->enumList.at(i);
int flags = 0;
if (cdef->enumDeclarations.value(e.name))
@@ -941,16 +915,14 @@ void Generator::generateEnums(int index)
stridx(e.name),
e.enumName.isNull() ? stridx(e.name) : stridx(e.enumName),
flags,
- int(e.values.count()),
+ int(e.values.size()),
index);
- index += e.values.count() * 2;
+ index += e.values.size() * 2;
}
fprintf(out, "\n // enum data: key, value\n");
- for (i = 0; i < cdef->enumList.count(); ++i) {
- const EnumDef &e = cdef->enumList.at(i);
- for (int j = 0; j < e.values.count(); ++j) {
- const QByteArray &val = e.values.at(j);
+ for (const EnumDef &e : std::as_const(cdef->enumList)) {
+ for (const QByteArray &val : e.values) {
QByteArray code = cdef->qualified.constData();
if (e.isEnumClass)
code += "::" + (e.enumName.isNull() ? e.name : e.enumName);
@@ -1015,7 +987,7 @@ void Generator::generateMetacall()
" || _c == QMetaObject::ResetProperty || _c == QMetaObject::BindableProperty\n"
" || _c == QMetaObject::RegisterPropertyMetaType) {\n"
" qt_static_metacall(this, _c, _id, _a);\n"
- " _id -= %d;\n }", int(cdef->propertyList.count()));
+ " _id -= %d;\n }", int(cdef->propertyList.size()));
}
if (methodList.size() || cdef->propertyList.size())
fprintf(out, "\n ");
@@ -1027,7 +999,7 @@ void Generator::generateMetacall()
QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper()
{
QMultiMap<QByteArray, int> automaticPropertyMetaTypes;
- for (int i = 0; i < cdef->propertyList.size(); ++i) {
+ for (int i = 0; i < int(cdef->propertyList.size()); ++i) {
const QByteArray propertyType = cdef->propertyList.at(i).type;
if (registerableMetaType(propertyType) && !isBuiltinType(propertyType))
automaticPropertyMetaTypes.insert(propertyType, i);
@@ -1041,7 +1013,7 @@ Generator::methodsWithAutomaticTypesHelper(const QList<FunctionDef> &methodList)
QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypes;
for (int i = 0; i < methodList.size(); ++i) {
const FunctionDef &f = methodList.at(i);
- for (int j = 0; j < f.arguments.count(); ++j) {
+ for (int j = 0; j < f.arguments.size(); ++j) {
const QByteArray argType = f.arguments.at(j).normalizedType;
if (registerableMetaType(argType) && !isBuiltinType(argType))
methodsWithAutomaticTypes[i].insert(argType, j);
@@ -1058,33 +1030,46 @@ void Generator::generateStaticMetacall()
bool needElse = false;
bool isUsed_a = false;
+ const auto generateCtorArguments = [&](int ctorindex) {
+ const FunctionDef &f = cdef->constructorList.at(ctorindex);
+ Q_ASSERT(!f.isPrivateSignal); // That would be a strange ctor indeed
+ int offset = 1;
+
+ const auto begin = f.arguments.cbegin();
+ const auto end = f.arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
+ fprintf(out, ",");
+ fprintf(out, "(*reinterpret_cast<%s>(_a[%d]))",
+ a.typeNameForCast.constData(), offset++);
+ }
+ };
+
if (!cdef->constructorList.isEmpty()) {
fprintf(out, " if (_c == QMetaObject::CreateInstance) {\n");
fprintf(out, " switch (_id) {\n");
- for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) {
+ const int ctorend = int(cdef->constructorList.size());
+ for (int ctorindex = 0; ctorindex < ctorend; ++ctorindex) {
fprintf(out, " case %d: { %s *_r = new %s(", ctorindex,
cdef->classname.constData(), cdef->classname.constData());
- const FunctionDef &f = cdef->constructorList.at(ctorindex);
- int offset = 1;
-
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
- if (j)
- fprintf(out, ",");
- fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++);
- }
- if (f.isPrivateSignal) {
- if (argsCount > 0)
- fprintf(out, ", ");
- fprintf(out, "%s", QByteArray("QPrivateSignal()").constData());
- }
+ generateCtorArguments(ctorindex);
fprintf(out, ");\n");
fprintf(out, " if (_a[0]) *reinterpret_cast<%s**>(_a[0]) = _r; } break;\n",
(cdef->hasQGadget || cdef->hasQNamespace) ? "void" : "QObject");
}
fprintf(out, " default: break;\n");
fprintf(out, " }\n");
+ fprintf(out, " } else if (_c == QMetaObject::ConstructInPlace) {\n");
+ fprintf(out, " switch (_id) {\n");
+ for (int ctorindex = 0; ctorindex < ctorend; ++ctorindex) {
+ fprintf(out, " case %d: { new (_a[0]) %s(",
+ ctorindex, cdef->classname.constData());
+ generateCtorArguments(ctorindex);
+ fprintf(out, "); } break;\n");
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
fprintf(out, " }");
needElse = true;
isUsed_a = true;
@@ -1126,16 +1111,17 @@ void Generator::generateStaticMetacall()
if (f.isRawSlot) {
fprintf(out, "QMethodRawArguments{ _a }");
} else {
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
- if (j)
+ const auto begin = f.arguments.cbegin();
+ const auto end = f.arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
fprintf(out, ",");
fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++);
isUsed_a = true;
}
if (f.isPrivateSignal) {
- if (argsCount > 0)
+ if (!f.arguments.isEmpty())
fprintf(out, ", ");
fprintf(out, "%s", "QPrivateSignal()");
}
@@ -1188,7 +1174,7 @@ void Generator::generateStaticMetacall()
fprintf(out, " else if (_c == QMetaObject::IndexOfMethod) {\n");
fprintf(out, " int *result = reinterpret_cast<int *>(_a[0]);\n");
bool anythingUsed = false;
- for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) {
+ for (int methodindex = 0; methodindex < int(cdef->signalList.size()); ++methodindex) {
const FunctionDef &f = cdef->signalList.at(methodindex);
if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
continue;
@@ -1196,15 +1182,16 @@ void Generator::generateStaticMetacall()
fprintf(out, " {\n");
fprintf(out, " using _t = %s (%s::*)(",f.type.rawName.constData() , cdef->classname.constData());
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
- if (j)
+ const auto begin = f.arguments.cbegin();
+ const auto end = f.arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
fprintf(out, ", ");
fprintf(out, "%s", QByteArray(a.type.name + ' ' + a.rightType).constData());
}
if (f.isPrivateSignal) {
- if (argsCount > 0)
+ if (!f.arguments.isEmpty())
fprintf(out, ", ");
fprintf(out, "%s", "QPrivateSignal");
}
@@ -1255,8 +1242,7 @@ void Generator::generateStaticMetacall()
bool needSet = false;
bool needReset = false;
bool hasBindableProperties = false;
- for (int i = 0; i < cdef->propertyList.size(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
needGet |= !p.read.isEmpty() || !p.member.isEmpty();
if (!p.read.isEmpty() || !p.member.isEmpty())
needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
@@ -1267,7 +1253,7 @@ void Generator::generateStaticMetacall()
hasBindableProperties |= !p.bind.isEmpty();
}
if (needElse)
- fprintf(out, "else ");
+ fprintf(out, " else ");
fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
auto setupMemberAccess = [this]() {
@@ -1287,7 +1273,7 @@ void Generator::generateStaticMetacall()
if (needTempVarForGet)
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.read.isEmpty() && p.member.isEmpty())
continue;
@@ -1328,7 +1314,7 @@ void Generator::generateStaticMetacall()
setupMemberAccess();
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.constant)
continue;
@@ -1381,7 +1367,7 @@ void Generator::generateStaticMetacall()
if (needReset) {
setupMemberAccess();
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.reset.isEmpty())
continue;
@@ -1402,7 +1388,7 @@ void Generator::generateStaticMetacall()
if (hasBindableProperties) {
setupMemberAccess();
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.bind.isEmpty())
continue;
@@ -1438,7 +1424,7 @@ void Generator::generateStaticMetacall()
fprintf(out, "}\n");
}
-void Generator::generateSignal(FunctionDef *def,int index)
+void Generator::generateSignal(const FunctionDef *def, int index)
{
if (def->wasCloned || def->isAbstract)
return;
@@ -1462,9 +1448,11 @@ void Generator::generateSignal(FunctionDef *def,int index)
}
int offset = 1;
- for (int j = 0; j < def->arguments.count(); ++j) {
- const ArgumentDef &a = def->arguments.at(j);
- if (j)
+ const auto begin = def->arguments.cbegin();
+ const auto end = def->arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
fputs(", ", out);
if (a.type.name.size())
fputs(a.type.name.constData(), out);
@@ -1495,7 +1483,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
}
int i;
for (i = 1; i < offset; ++i)
- if (i <= def->arguments.count() && def->arguments.at(i - 1).type.isVolatile)
+ if (i <= def->arguments.size() && def->arguments.at(i - 1).type.isVolatile)
fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(std::addressof(_t%d)))", i);
else
fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t%d)))", i);
@@ -1554,8 +1542,7 @@ static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v)
return cbor_encode_double(parent, d);
}
}
- Q_UNREACHABLE();
- return CborUnknownError;
+ Q_UNREACHABLE_RETURN(CborUnknownError);
}
void Generator::generatePluginMetaData()
@@ -1607,7 +1594,7 @@ void Generator::generatePluginMetaData()
};
// 'Use' all namespaces.
- int pos = cdef->qualified.indexOf("::");
+ qsizetype pos = cdef->qualified.indexOf("::");
for ( ; pos != -1 ; pos = cdef->qualified.indexOf("::", pos + 2) )
fprintf(out, "using namespace %s;\n", cdef->qualified.left(pos).constData());
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index fa651f04a0..2d4d69ca05 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -10,16 +10,19 @@ QT_BEGIN_NAMESPACE
class Generator
{
+ Moc *parser = nullptr;
FILE *out;
ClassDef *cdef;
QList<uint> meta_data;
public:
- Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr,
bool requireCompleteTypes = false);
void generateCode();
+ qsizetype registeredStringsCount() { return strings.size(); };
+
private:
bool registerableMetaType(const QByteArray &propertyType);
void registerClassInfoStrings();
@@ -37,7 +40,7 @@ private:
void generateProperties();
void generateMetacall();
void generateStaticMetacall();
- void generateSignal(FunctionDef *def, int index);
+ void generateSignal(const FunctionDef *def, int index);
void generatePluginMetaData();
QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
QMap<int, QMultiMap<QByteArray, int>>
diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp
index 9d82da7a26..6a1f58490f 100644
--- a/src/tools/moc/keywords.cpp
+++ b/src/tools/moc/keywords.cpp
@@ -5,12 +5,12 @@
// DO NOT EDIT.
static const short keyword_trans[][128] = {
- {0,0,0,0,0,0,0,0,0,586,583,0,0,0,0,0,
+ {0,0,0,0,0,0,0,0,0,618,615,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 586,252,584,587,8,38,239,585,25,26,236,234,30,235,27,237,
+ 618,252,616,619,8,38,239,617,25,26,236,234,30,235,27,237,
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,21,8,8,8,8,8,8,8,8,8,31,589,32,238,8,
+ 8,21,8,8,8,8,8,8,8,8,8,31,621,32,238,8,
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -91,7 +91,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,290,222,0,0,504,0,0,0,
+ 0,0,0,0,0,0,0,0,290,222,0,0,524,0,0,0,
0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -130,7 +130,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,528,0,0,0,0,0,0,0,0,0,0,357,
+ 0,0,0,0,401,0,0,0,0,0,0,0,0,0,0,357,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -152,7 +152,7 @@ static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
- 592,592,592,592,592,592,592,592,592,592,0,0,0,0,0,0,
+ 624,624,624,624,624,624,624,624,624,624,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -311,7 +311,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,591,0,0,0,0,590,
+ 0,0,0,0,0,0,0,0,0,0,623,0,0,0,0,622,
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -347,21 +347,21 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,501,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
+ 0,521,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,482,431,415,423,380,0,491,0,0,0,572,364,358,
- 393,0,564,479,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,502,451,435,443,380,0,511,0,0,0,604,364,358,
+ 393,0,596,499,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,401,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,421,0,0,0,
0,0,394,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -369,7 +369,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,518,0,0,0,0,0,395,
+ 0,0,0,0,0,0,0,0,0,538,0,0,0,0,0,395,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -377,48 +377,64 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,403,0,0,0,0,0,0,0,0,0,0,0,548,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,419,0,0,0,0,0,0,0,0,0,0,0,420,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,582,0,0,0,0,0,415,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,427,0,0,0,0,0,0,0,0,0,0,0,428,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,461,439,0,0,444,0,0,0,453,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,439,0,0,0,0,0,0,0,0,0,0,0,440,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,547,0,480,0,0,0,508,0,0,514,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,447,0,0,0,0,0,0,0,0,0,0,0,448,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,481,459,0,0,464,0,0,0,473,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,493,0,540,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,565,0,500,0,0,0,528,0,0,534,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 556,0,0,524,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,513,0,558,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 574,0,0,544,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
@@ -832,193 +848,225 @@ static const struct
{CHARACTER, 0, 84, 399, CHARACTER},
{CHARACTER, 0, 89, 400, CHARACTER},
{Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 85, 402, CHARACTER},
- {CHARACTER, 0, 71, 403, CHARACTER},
- {CHARACTER, 0, 73, 404, CHARACTER},
- {CHARACTER, 0, 78, 405, CHARACTER},
- {CHARACTER, 0, 95, 406, CHARACTER},
- {CHARACTER, 0, 77, 407, CHARACTER},
- {CHARACTER, 0, 69, 408, CHARACTER},
- {CHARACTER, 0, 84, 409, CHARACTER},
- {CHARACTER, 0, 65, 410, CHARACTER},
- {CHARACTER, 0, 68, 411, CHARACTER},
- {CHARACTER, 0, 65, 412, CHARACTER},
- {CHARACTER, 0, 84, 413, CHARACTER},
- {CHARACTER, 0, 65, 414, CHARACTER},
+ {CHARACTER, 0, 95, 402, CHARACTER},
+ {CHARACTER, 46, 0, 0, CHARACTER},
+ {CHARACTER, 0, 78, 404, CHARACTER},
+ {CHARACTER, 0, 79, 405, CHARACTER},
+ {CHARACTER, 0, 78, 406, CHARACTER},
+ {CHARACTER, 0, 89, 407, CHARACTER},
+ {CHARACTER, 0, 77, 408, CHARACTER},
+ {CHARACTER, 0, 79, 409, CHARACTER},
+ {CHARACTER, 0, 85, 410, CHARACTER},
+ {CHARACTER, 0, 83, 411, CHARACTER},
+ {CHARACTER, 0, 95, 412, CHARACTER},
+ {CHARACTER, 0, 80, 413, CHARACTER},
+ {CHARACTER, 0, 82, 414, CHARACTER},
+ {CHARACTER, 47, 0, 0, CHARACTER},
+ {CHARACTER, 0, 80, 416, CHARACTER},
+ {CHARACTER, 0, 69, 417, CHARACTER},
+ {CHARACTER, 0, 82, 418, CHARACTER},
+ {CHARACTER, 0, 84, 419, CHARACTER},
+ {CHARACTER, 0, 89, 420, CHARACTER},
+ {QT_ANONYMOUS_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 85, 422, CHARACTER},
+ {CHARACTER, 0, 71, 423, CHARACTER},
+ {CHARACTER, 0, 73, 424, CHARACTER},
+ {CHARACTER, 0, 78, 425, CHARACTER},
+ {CHARACTER, 0, 95, 426, CHARACTER},
+ {CHARACTER, 0, 77, 427, CHARACTER},
+ {CHARACTER, 0, 69, 428, CHARACTER},
+ {CHARACTER, 0, 84, 429, CHARACTER},
+ {CHARACTER, 0, 65, 430, CHARACTER},
+ {CHARACTER, 0, 68, 431, CHARACTER},
+ {CHARACTER, 0, 65, 432, CHARACTER},
+ {CHARACTER, 0, 84, 433, CHARACTER},
+ {CHARACTER, 0, 65, 434, CHARACTER},
{Q_PLUGIN_METADATA_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 416, CHARACTER},
- {CHARACTER, 0, 85, 417, CHARACTER},
- {CHARACTER, 0, 77, 418, CHARACTER},
- {Q_ENUM_TOKEN, 46, 0, 0, CHARACTER},
+ {CHARACTER, 0, 78, 436, CHARACTER},
+ {CHARACTER, 0, 85, 437, CHARACTER},
+ {CHARACTER, 0, 77, 438, CHARACTER},
+ {Q_ENUM_TOKEN, 48, 0, 0, CHARACTER},
{Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 421, CHARACTER},
- {CHARACTER, 0, 83, 422, CHARACTER},
+ {CHARACTER, 0, 78, 441, CHARACTER},
+ {CHARACTER, 0, 83, 442, CHARACTER},
{Q_ENUM_NS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 424, CHARACTER},
- {CHARACTER, 0, 65, 425, CHARACTER},
- {CHARACTER, 0, 71, 426, CHARACTER},
- {Q_FLAG_TOKEN, 47, 0, 0, CHARACTER},
+ {CHARACTER, 0, 76, 444, CHARACTER},
+ {CHARACTER, 0, 65, 445, CHARACTER},
+ {CHARACTER, 0, 71, 446, CHARACTER},
+ {Q_FLAG_TOKEN, 49, 0, 0, CHARACTER},
{Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 429, CHARACTER},
- {CHARACTER, 0, 83, 430, CHARACTER},
+ {CHARACTER, 0, 78, 449, CHARACTER},
+ {CHARACTER, 0, 83, 450, CHARACTER},
{Q_FLAG_NS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 432, CHARACTER},
- {CHARACTER, 0, 67, 433, CHARACTER},
- {CHARACTER, 0, 76, 434, CHARACTER},
- {CHARACTER, 0, 65, 435, CHARACTER},
- {CHARACTER, 0, 82, 436, CHARACTER},
- {CHARACTER, 0, 69, 437, CHARACTER},
- {CHARACTER, 0, 95, 438, CHARACTER},
- {CHARACTER, 48, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 440, CHARACTER},
- {CHARACTER, 0, 65, 441, CHARACTER},
- {CHARACTER, 0, 71, 442, CHARACTER},
- {CHARACTER, 0, 83, 443, CHARACTER},
- {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 445, CHARACTER},
- {CHARACTER, 0, 84, 446, CHARACTER},
- {CHARACTER, 0, 69, 447, CHARACTER},
- {CHARACTER, 0, 82, 448, CHARACTER},
- {CHARACTER, 0, 70, 449, CHARACTER},
- {CHARACTER, 0, 65, 450, CHARACTER},
- {CHARACTER, 0, 67, 451, CHARACTER},
{CHARACTER, 0, 69, 452, CHARACTER},
- {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 454, CHARACTER},
- {CHARACTER, 0, 84, 455, CHARACTER},
- {CHARACTER, 0, 65, 456, CHARACTER},
- {CHARACTER, 0, 84, 457, CHARACTER},
- {CHARACTER, 0, 89, 458, CHARACTER},
- {CHARACTER, 0, 80, 459, CHARACTER},
- {CHARACTER, 0, 69, 460, CHARACTER},
- {Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 88, 462, CHARACTER},
- {CHARACTER, 0, 84, 463, CHARACTER},
- {CHARACTER, 0, 69, 464, CHARACTER},
+ {CHARACTER, 0, 67, 453, CHARACTER},
+ {CHARACTER, 0, 76, 454, CHARACTER},
+ {CHARACTER, 0, 65, 455, CHARACTER},
+ {CHARACTER, 0, 82, 456, CHARACTER},
+ {CHARACTER, 0, 69, 457, CHARACTER},
+ {CHARACTER, 0, 95, 458, CHARACTER},
+ {CHARACTER, 50, 0, 0, CHARACTER},
+ {CHARACTER, 0, 76, 460, CHARACTER},
+ {CHARACTER, 0, 65, 461, CHARACTER},
+ {CHARACTER, 0, 71, 462, CHARACTER},
+ {CHARACTER, 0, 83, 463, CHARACTER},
+ {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 465, CHARACTER},
- {CHARACTER, 0, 83, 466, CHARACTER},
- {CHARACTER, 0, 73, 467, CHARACTER},
- {CHARACTER, 0, 79, 468, CHARACTER},
- {CHARACTER, 0, 78, 469, CHARACTER},
- {CHARACTER, 0, 95, 470, CHARACTER},
- {CHARACTER, 0, 73, 471, CHARACTER},
- {CHARACTER, 0, 78, 472, CHARACTER},
- {CHARACTER, 0, 84, 473, CHARACTER},
+ {CHARACTER, 0, 84, 466, CHARACTER},
+ {CHARACTER, 0, 69, 467, CHARACTER},
+ {CHARACTER, 0, 82, 468, CHARACTER},
+ {CHARACTER, 0, 70, 469, CHARACTER},
+ {CHARACTER, 0, 65, 470, CHARACTER},
+ {CHARACTER, 0, 67, 471, CHARACTER},
+ {CHARACTER, 0, 69, 472, CHARACTER},
+ {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 474, CHARACTER},
- {CHARACTER, 0, 82, 475, CHARACTER},
- {CHARACTER, 0, 70, 476, CHARACTER},
- {CHARACTER, 0, 65, 477, CHARACTER},
- {CHARACTER, 0, 67, 478, CHARACTER},
- {CHARACTER, 0, 69, 452, CHARACTER},
- {CHARACTER, 49, 0, 0, CHARACTER},
- {CHARACTER, 0, 84, 481, CHARACTER},
- {CHARACTER, 0, 83, 427, CHARACTER},
- {CHARACTER, 0, 76, 483, CHARACTER},
- {CHARACTER, 0, 65, 484, CHARACTER},
- {CHARACTER, 0, 83, 485, CHARACTER},
+ {CHARACTER, 0, 84, 475, CHARACTER},
+ {CHARACTER, 0, 65, 476, CHARACTER},
+ {CHARACTER, 0, 84, 477, CHARACTER},
+ {CHARACTER, 0, 89, 478, CHARACTER},
+ {CHARACTER, 0, 80, 479, CHARACTER},
+ {CHARACTER, 0, 69, 480, CHARACTER},
+ {Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 88, 482, CHARACTER},
+ {CHARACTER, 0, 84, 483, CHARACTER},
+ {CHARACTER, 0, 69, 484, CHARACTER},
+ {CHARACTER, 0, 78, 485, CHARACTER},
{CHARACTER, 0, 83, 486, CHARACTER},
{CHARACTER, 0, 73, 487, CHARACTER},
- {CHARACTER, 0, 78, 488, CHARACTER},
- {CHARACTER, 0, 70, 489, CHARACTER},
- {CHARACTER, 0, 79, 490, CHARACTER},
- {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 79, 488, CHARACTER},
+ {CHARACTER, 0, 78, 489, CHARACTER},
+ {CHARACTER, 0, 95, 490, CHARACTER},
+ {CHARACTER, 0, 73, 491, CHARACTER},
{CHARACTER, 0, 78, 492, CHARACTER},
- {CHARACTER, 50, 0, 0, CHARACTER},
+ {CHARACTER, 0, 84, 493, CHARACTER},
{CHARACTER, 0, 69, 494, CHARACTER},
{CHARACTER, 0, 82, 495, CHARACTER},
{CHARACTER, 0, 70, 496, CHARACTER},
{CHARACTER, 0, 65, 497, CHARACTER},
{CHARACTER, 0, 67, 498, CHARACTER},
- {CHARACTER, 0, 69, 499, CHARACTER},
- {CHARACTER, 0, 83, 500, CHARACTER},
+ {CHARACTER, 0, 69, 472, CHARACTER},
+ {CHARACTER, 51, 0, 0, CHARACTER},
+ {CHARACTER, 0, 84, 501, CHARACTER},
+ {CHARACTER, 0, 83, 447, CHARACTER},
+ {CHARACTER, 0, 76, 503, CHARACTER},
+ {CHARACTER, 0, 65, 504, CHARACTER},
+ {CHARACTER, 0, 83, 505, CHARACTER},
+ {CHARACTER, 0, 83, 506, CHARACTER},
+ {CHARACTER, 0, 73, 507, CHARACTER},
+ {CHARACTER, 0, 78, 508, CHARACTER},
+ {CHARACTER, 0, 70, 509, CHARACTER},
+ {CHARACTER, 0, 79, 510, CHARACTER},
+ {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 78, 512, CHARACTER},
+ {CHARACTER, 52, 0, 0, CHARACTER},
+ {CHARACTER, 0, 69, 514, CHARACTER},
+ {CHARACTER, 0, 82, 515, CHARACTER},
+ {CHARACTER, 0, 70, 516, CHARACTER},
+ {CHARACTER, 0, 65, 517, CHARACTER},
+ {CHARACTER, 0, 67, 518, CHARACTER},
+ {CHARACTER, 0, 69, 519, CHARACTER},
+ {CHARACTER, 0, 83, 520, CHARACTER},
{Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 108, 502, CHARACTER},
- {CHARACTER, 0, 115, 503, CHARACTER},
+ {CHARACTER, 0, 108, 522, CHARACTER},
+ {CHARACTER, 0, 115, 523, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 111, 505, CHARACTER},
- {CHARACTER, 0, 116, 506, CHARACTER},
- {CHARACTER, 0, 115, 507, CHARACTER},
+ {CHARACTER, 0, 111, 525, CHARACTER},
+ {CHARACTER, 0, 116, 526, CHARACTER},
+ {CHARACTER, 0, 115, 527, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 71, 509, CHARACTER},
- {CHARACTER, 0, 78, 510, CHARACTER},
- {CHARACTER, 0, 65, 511, CHARACTER},
- {CHARACTER, 0, 76, 512, CHARACTER},
- {Q_SIGNAL_TOKEN, 0, 83, 513, CHARACTER},
+ {CHARACTER, 0, 71, 529, CHARACTER},
+ {CHARACTER, 0, 78, 530, CHARACTER},
+ {CHARACTER, 0, 65, 531, CHARACTER},
+ {CHARACTER, 0, 76, 532, CHARACTER},
+ {Q_SIGNAL_TOKEN, 0, 83, 533, CHARACTER},
{Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 515, CHARACTER},
- {CHARACTER, 0, 84, 516, CHARACTER},
- {Q_SLOT_TOKEN, 0, 83, 517, CHARACTER},
+ {CHARACTER, 0, 79, 535, CHARACTER},
+ {CHARACTER, 0, 84, 536, CHARACTER},
+ {Q_SLOT_TOKEN, 0, 83, 537, CHARACTER},
{Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 86, 519, CHARACTER},
- {CHARACTER, 0, 65, 520, CHARACTER},
- {CHARACTER, 0, 84, 521, CHARACTER},
- {CHARACTER, 0, 69, 522, CHARACTER},
- {CHARACTER, 0, 95, 523, CHARACTER},
- {CHARACTER, 51, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 525, CHARACTER},
- {CHARACTER, 0, 79, 526, CHARACTER},
- {CHARACTER, 0, 84, 527, CHARACTER},
+ {CHARACTER, 0, 86, 539, CHARACTER},
+ {CHARACTER, 0, 65, 540, CHARACTER},
+ {CHARACTER, 0, 84, 541, CHARACTER},
+ {CHARACTER, 0, 69, 542, CHARACTER},
+ {CHARACTER, 0, 95, 543, CHARACTER},
+ {CHARACTER, 53, 0, 0, CHARACTER},
+ {CHARACTER, 0, 76, 545, CHARACTER},
+ {CHARACTER, 0, 79, 546, CHARACTER},
+ {CHARACTER, 0, 84, 547, CHARACTER},
{Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 95, 529, CHARACTER},
- {CHARACTER, 0, 77, 530, CHARACTER},
- {CHARACTER, 0, 79, 531, CHARACTER},
- {CHARACTER, 0, 67, 532, CHARACTER},
- {CHARACTER, 0, 95, 533, CHARACTER},
- {CHARACTER, 0, 67, 534, CHARACTER},
- {CHARACTER, 0, 79, 535, CHARACTER},
- {CHARACTER, 0, 77, 536, CHARACTER},
- {CHARACTER, 0, 80, 537, CHARACTER},
- {CHARACTER, 0, 65, 538, CHARACTER},
- {CHARACTER, 0, 84, 539, CHARACTER},
+ {CHARACTER, 0, 79, 549, CHARACTER},
+ {CHARACTER, 0, 67, 550, CHARACTER},
+ {CHARACTER, 0, 95, 551, CHARACTER},
+ {CHARACTER, 0, 67, 552, CHARACTER},
+ {CHARACTER, 0, 79, 553, CHARACTER},
+ {CHARACTER, 0, 77, 554, CHARACTER},
+ {CHARACTER, 0, 80, 555, CHARACTER},
+ {CHARACTER, 0, 65, 556, CHARACTER},
+ {CHARACTER, 0, 84, 557, CHARACTER},
{Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 541, CHARACTER},
- {CHARACTER, 0, 75, 542, CHARACTER},
- {CHARACTER, 0, 65, 543, CHARACTER},
- {CHARACTER, 0, 66, 544, CHARACTER},
- {CHARACTER, 0, 76, 545, CHARACTER},
- {CHARACTER, 0, 69, 546, CHARACTER},
+ {CHARACTER, 0, 79, 559, CHARACTER},
+ {CHARACTER, 0, 75, 560, CHARACTER},
+ {CHARACTER, 0, 65, 561, CHARACTER},
+ {CHARACTER, 0, 66, 562, CHARACTER},
+ {CHARACTER, 0, 76, 563, CHARACTER},
+ {CHARACTER, 0, 69, 564, CHARACTER},
{Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 82, 548, CHARACTER},
- {CHARACTER, 0, 73, 549, CHARACTER},
- {CHARACTER, 0, 80, 550, CHARACTER},
- {CHARACTER, 0, 84, 551, CHARACTER},
- {CHARACTER, 0, 65, 552, CHARACTER},
- {CHARACTER, 0, 66, 553, CHARACTER},
- {CHARACTER, 0, 76, 554, CHARACTER},
- {CHARACTER, 0, 69, 555, CHARACTER},
+ {CHARACTER, 0, 82, 566, CHARACTER},
+ {CHARACTER, 0, 73, 567, CHARACTER},
+ {CHARACTER, 0, 80, 568, CHARACTER},
+ {CHARACTER, 0, 84, 569, CHARACTER},
+ {CHARACTER, 0, 65, 570, CHARACTER},
+ {CHARACTER, 0, 66, 571, CHARACTER},
+ {CHARACTER, 0, 76, 572, CHARACTER},
+ {CHARACTER, 0, 69, 573, CHARACTER},
{Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 82, 557, CHARACTER},
- {CHARACTER, 0, 79, 558, CHARACTER},
- {CHARACTER, 0, 80, 559, CHARACTER},
- {CHARACTER, 0, 69, 560, CHARACTER},
- {CHARACTER, 0, 82, 561, CHARACTER},
- {CHARACTER, 0, 84, 562, CHARACTER},
- {CHARACTER, 0, 89, 563, CHARACTER},
+ {CHARACTER, 0, 82, 575, CHARACTER},
+ {CHARACTER, 0, 79, 576, CHARACTER},
+ {CHARACTER, 0, 80, 577, CHARACTER},
+ {CHARACTER, 0, 69, 578, CHARACTER},
+ {CHARACTER, 0, 82, 579, CHARACTER},
+ {CHARACTER, 0, 84, 580, CHARACTER},
+ {CHARACTER, 0, 89, 581, CHARACTER},
{Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 565, CHARACTER},
- {CHARACTER, 0, 86, 566, CHARACTER},
- {CHARACTER, 0, 73, 567, CHARACTER},
- {CHARACTER, 0, 83, 568, CHARACTER},
- {CHARACTER, 0, 73, 569, CHARACTER},
- {CHARACTER, 0, 79, 570, CHARACTER},
- {CHARACTER, 0, 78, 571, CHARACTER},
+ {CHARACTER, 0, 86, 583, CHARACTER},
+ {CHARACTER, 0, 65, 584, CHARACTER},
+ {CHARACTER, 0, 84, 585, CHARACTER},
+ {CHARACTER, 0, 69, 586, CHARACTER},
+ {CHARACTER, 0, 95, 587, CHARACTER},
+ {CHARACTER, 0, 80, 588, CHARACTER},
+ {CHARACTER, 0, 82, 589, CHARACTER},
+ {CHARACTER, 0, 79, 590, CHARACTER},
+ {CHARACTER, 0, 80, 591, CHARACTER},
+ {CHARACTER, 0, 69, 592, CHARACTER},
+ {CHARACTER, 0, 82, 593, CHARACTER},
+ {CHARACTER, 0, 84, 594, CHARACTER},
+ {CHARACTER, 0, 89, 595, CHARACTER},
+ {QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 69, 597, CHARACTER},
+ {CHARACTER, 0, 86, 598, CHARACTER},
+ {CHARACTER, 0, 73, 599, CHARACTER},
+ {CHARACTER, 0, 83, 600, CHARACTER},
+ {CHARACTER, 0, 73, 601, CHARACTER},
+ {CHARACTER, 0, 79, 602, CHARACTER},
+ {CHARACTER, 0, 78, 603, CHARACTER},
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 573, CHARACTER},
- {CHARACTER, 0, 67, 574, CHARACTER},
- {CHARACTER, 0, 95, 575, CHARACTER},
- {CHARACTER, 0, 73, 576, CHARACTER},
- {CHARACTER, 0, 78, 577, CHARACTER},
- {CHARACTER, 0, 67, 578, CHARACTER},
- {CHARACTER, 0, 76, 579, CHARACTER},
- {CHARACTER, 0, 85, 580, CHARACTER},
- {CHARACTER, 0, 68, 581, CHARACTER},
- {CHARACTER, 0, 69, 582, CHARACTER},
+ {CHARACTER, 0, 79, 605, CHARACTER},
+ {CHARACTER, 0, 67, 606, CHARACTER},
+ {CHARACTER, 0, 95, 607, CHARACTER},
+ {CHARACTER, 0, 73, 608, CHARACTER},
+ {CHARACTER, 0, 78, 609, CHARACTER},
+ {CHARACTER, 0, 67, 610, CHARACTER},
+ {CHARACTER, 0, 76, 611, CHARACTER},
+ {CHARACTER, 0, 85, 612, CHARACTER},
+ {CHARACTER, 0, 68, 613, CHARACTER},
+ {CHARACTER, 0, 69, 614, CHARACTER},
{Q_MOC_INCLUDE_TOKEN, 0, 0, 0, CHARACTER},
{NEWLINE, 0, 0, 0, NOTOKEN},
{QUOTE, 0, 0, 0, NOTOKEN},
{SINGLEQUOTE, 0, 0, 0, NOTOKEN},
{WHITESPACE, 0, 0, 0, NOTOKEN},
- {HASH, 0, 35, 588, HASH},
+ {HASH, 0, 35, 620, HASH},
{PP_HASHHASH, 0, 0, 0, NOTOKEN},
{BACKSLASH, 0, 0, 0, NOTOKEN},
{CPP_COMMENT, 0, 0, 0, NOTOKEN},
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index 71b9757ebc..bb51352519 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -330,7 +330,7 @@ int runMoc(int argc, char **argv)
if (parser.isSet(collectOption))
return collectJson(files, output, hasOptionFiles);
- if (files.count() > 1) {
+ if (files.size() > 1) {
error(qPrintable("Too many input files specified: '"_L1 + files.join("' '"_L1) + u'\''));
parser.showHelp(1);
} else if (!files.isEmpty()) {
@@ -399,7 +399,7 @@ int runMoc(int argc, char **argv)
for (const QString &arg : defines) {
QByteArray name = arg.toLocal8Bit();
QByteArray value("1");
- int eq = name.indexOf('=');
+ const qsizetype eq = name.indexOf('=');
if (eq >= 0) {
value = name.mid(eq + 1);
name = name.left(eq);
@@ -449,11 +449,14 @@ int runMoc(int argc, char **argv)
if (filename.isEmpty()) {
filename = QStringLiteral("standard input");
- in.open(stdin, QIODevice::ReadOnly);
+ if (!in.open(stdin, QIODevice::ReadOnly)) {
+ fprintf(stderr, "moc: cannot open standard input: %s\n", qPrintable(in.errorString()));
+ return 1;
+ }
} else {
in.setFileName(filename);
if (!in.open(QIODevice::ReadOnly)) {
- fprintf(stderr, "moc: %s: No such file\n", qPrintable(filename));
+ fprintf(stderr, "moc: cannot open %s: %s\n", qPrintable(filename), qPrintable(in.errorString()));
return 1;
}
moc.filename = filename.toLocal8Bit();
@@ -536,7 +539,10 @@ int runMoc(int argc, char **argv)
if (!out)
#endif
{
- fprintf(stderr, "moc: Cannot create %s\n", QFile::encodeName(output).constData());
+ const auto fopen_errno = errno;
+ fprintf(stderr, "moc: Cannot create %s. Error: %s\n",
+ QFile::encodeName(output).constData(),
+ strerror(fopen_errno));
return 1;
}
@@ -549,9 +555,12 @@ int runMoc(int argc, char **argv)
f = fopen(QFile::encodeName(jsonOutputFileName).constData(), "w");
if (!f)
#endif
- fprintf(stderr, "moc: Cannot create JSON output file %s. %s\n",
+ {
+ const auto fopen_errno = errno;
+ fprintf(stderr, "moc: Cannot create JSON output file %s. Error: %s\n",
QFile::encodeName(jsonOutputFileName).constData(),
- strerror(errno));
+ strerror(fopen_errno));
+ }
jsonOutput.reset(f);
}
} else { // use stdout
@@ -596,9 +605,12 @@ int runMoc(int argc, char **argv)
depFileHandleRaw = fopen(QFile::encodeName(depOutputFileName).constData(), "w");
if (!depFileHandleRaw)
#endif
- fprintf(stderr, "moc: Cannot create dep output file '%s'. %s\n",
+ {
+ const auto fopen_errno = errno;
+ fprintf(stderr, "moc: Cannot create dep output file '%s'. Error: %s\n",
QFile::encodeName(depOutputFileName).constData(),
- strerror(errno));
+ strerror(fopen_errno));
+ }
depFileHandle.reset(depFileHandleRaw);
if (!depFileHandle.isNull()) {
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 979c986a41..3cbe331f14 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -26,6 +26,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
@@ -87,17 +96,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);
@@ -243,7 +252,7 @@ bool Moc::parseEnum(EnumDef *def)
}
if (test(COLON)) { // C++11 strongly typed enum
// enum Foo : unsigned long { ... };
- parseType(); //ignore the result
+ def->type = normalizeType(parseType().name);
}
if (!test(LBRACE))
return false;
@@ -318,6 +327,9 @@ void Moc::parseFunctionArguments(FunctionDef *def)
def->arguments.removeLast();
def->isRawSlot = true;
}
+
+ if (Q_UNLIKELY(def->arguments.size() >= std::numeric_limits<int>::max()))
+ error("number of function arguments exceeds std::numeric_limits<int>::max()");
}
bool Moc::testFunctionAttribute(FunctionDef *def)
@@ -368,7 +380,7 @@ QTypeRevision Moc::parseRevision()
revisionString.remove(0, 1);
revisionString.chop(1);
const QList<QByteArray> majorMinor = revisionString.split(',');
- switch (majorMinor.length()) {
+ switch (majorMinor.size()) {
case 1: {
bool ok = false;
const int revision = revisionString.toInt(&ok);
@@ -409,8 +421,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
def->isVirtual = false;
def->isStatic = false;
//skip modifiers and attributes
- while (test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) ||
- (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual
+ while (testForFunctionModifiers(def)
|| skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {}
bool templateFunction = (lookup() == TEMPLATE);
def->type = parseType();
@@ -421,31 +432,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 {
- 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);
@@ -509,14 +518,20 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
return true;
}
+bool Moc::testForFunctionModifiers(FunctionDef *def)
+{
+ return test(EXPLICIT) || test(INLINE) ||
+ (test(STATIC) && (def->isStatic = true)) ||
+ (test(VIRTUAL) && (def->isVirtual = true));
+}
+
// like parseFunction, but never aborts with an error
bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
{
def->isVirtual = false;
def->isStatic = false;
//skip modifiers and attributes
- while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) ||
- (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual
+ while (testForFunctionModifiers(def)
|| skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {}
bool tilde = test(TILDE);
def->type = parseType();
@@ -531,10 +546,15 @@ 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 {
- Type tempType = parseType();;
+ // ### TODO: The condition before testForFunctionModifiers shoulnd't be necessary,
+ // but otherwise we end up with misparses
+ if (def->isSlot || def->isSignal || def->isInvokable)
+ while (testForFunctionModifiers(def)) {}
+ Type tempType = parseType();
while (!tempType.name.isEmpty() && lookup() != LPAREN) {
if (testFunctionAttribute(def->type.firstToken, def))
; // fine
@@ -593,6 +613,52 @@ inline void handleDefaultArguments(QList<FunctionDef> *functionList, FunctionDef
}
}
+void Moc::prependNamespaces(BaseDef &def, const QList<NamespaceDef> &namespaceList) const
+{
+ auto it = namespaceList.crbegin();
+ const auto rend = namespaceList.crend();
+ for (; it != rend; ++it) {
+ if (inNamespace(&*it))
+ def.qualified.prepend(it->classname + "::");
+ }
+}
+
+void Moc::checkListSizes(const ClassDef &def)
+{
+ if (Q_UNLIKELY(def.nonClassSignalList.size() > std::numeric_limits<int>::max()))
+ error("number of signals defined in parent class(es) exceeds "
+ "std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.propertyList.size() > std::numeric_limits<int>::max()))
+ error("number of bindable properties exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.classInfoList.size() > std::numeric_limits<int>::max()))
+ error("number of times Q_CLASSINFO macro is used exceeds "
+ "std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.enumList.size() > std::numeric_limits<int>::max()))
+ error("number of enumerations exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.superclassList.size() > std::numeric_limits<int>::max()))
+ error("number of super classes exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.constructorList.size() > std::numeric_limits<int>::max()))
+ error("number of constructor parameters exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.signalList.size() > std::numeric_limits<int>::max()))
+ error("number of signals exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.slotList.size() > std::numeric_limits<int>::max()))
+ error("number of declared slots exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.methodList.size() > std::numeric_limits<int>::max()))
+ error("number of methods exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.publicList.size() > std::numeric_limits<int>::max()))
+ error("number of public functions declared in this class exceeds "
+ "std::numeric_limits<int>::max().");
+}
+
void Moc::parse()
{
QList<NamespaceDef> namespaceList;
@@ -601,11 +667,17 @@ void Moc::parse()
Token t = next();
switch (t) {
case NAMESPACE: {
- int rewind = index;
+ qsizetype rewind = index;
if (test(IDENTIFIER)) {
QByteArray nsName = lexem();
QByteArrayList nested;
while (test(SCOPE)) {
+ /* treat (C++20's) namespace A::inline B {} as A::B
+ this is mostly to not break compilation when encountering such
+ a construct in a header; the interaction of Qt's meta-macros with
+ inline namespaces is still rather poor.
+ */
+ test(INLINE);
next(IDENTIFIER);
nested.append(nsName);
nsName = lexem();
@@ -627,11 +699,8 @@ void Moc::parse()
def.end = index;
index = def.begin + 1;
- for (int i = namespaceList.size() - 1; i >= 0; --i) {
- if (inNamespace(&namespaceList.at(i))) {
- def.qualified.prepend(namespaceList.at(i).classname + "::");
- }
- }
+ prependNamespaces(def, namespaceList);
+
for (const QByteArray &ns : nested) {
NamespaceDef parentNs;
parentNs.classname = ns;
@@ -646,8 +715,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);
@@ -777,9 +848,7 @@ void Moc::parse()
if (!def.hasQObject && !def.hasQGadget)
continue;
- for (int i = namespaceList.size() - 1; i >= 0; --i)
- if (inNamespace(&namespaceList.at(i)))
- def.qualified.prepend(namespaceList.at(i).classname + "::");
+ prependNamespaces(def, namespaceList);
QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets;
classHash.insert(def.classname, def.qualified);
@@ -792,10 +861,9 @@ void Moc::parse()
continue;
ClassDef def;
if (parseClassHead(&def)) {
+ prependNamespaces(def, namespaceList);
+
FunctionDef::Access access = FunctionDef::Private;
- for (int i = namespaceList.size() - 1; i >= 0; --i)
- if (inNamespace(&namespaceList.at(i)))
- def.qualified.prepend(namespaceList.at(i).classname + "::");
while (inClass(&def) && hasNext()) {
switch ((t = next())) {
case PRIVATE:
@@ -856,7 +924,10 @@ void Moc::parse()
error("Template classes not supported by Q_GADGET");
break;
case Q_PROPERTY_TOKEN:
- parseProperty(&def);
+ parseProperty(&def, Named);
+ break;
+ case QT_ANONYMOUS_PROPERTY_TOKEN:
+ parseProperty(&def, Anonymous);
break;
case Q_PLUGIN_METADATA_TOKEN:
parsePluginData(&def);
@@ -891,7 +962,10 @@ void Moc::parse()
parseSlotInPrivate(&def, access);
break;
case Q_PRIVATE_PROPERTY_TOKEN:
- parsePrivateProperty(&def);
+ parsePrivateProperty(&def, Named);
+ break;
+ case QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN:
+ parsePrivateProperty(&def, Anonymous);
break;
case ENUM: {
EnumDef enumDef;
@@ -904,7 +978,7 @@ void Moc::parse()
default:
FunctionDef funcDef;
funcDef.access = access;
- int rewind = index--;
+ qsizetype rewind = index--;
if (parseMaybeFunction(&def, &funcDef)) {
if (funcDef.isConstructor) {
if ((access == FunctionDef::Public) && funcDef.isInvokable) {
@@ -953,16 +1027,20 @@ void Moc::parse()
if (!def.pluginData.iid.isEmpty())
def.pluginData.metaArgs = metaArgs;
- checkSuperClasses(&def);
+ if (def.hasQObject && !def.superclassList.isEmpty())
+ checkSuperClasses(&def);
+
checkProperties(&def);
+ checkListSizes(def);
+
classList += def;
QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets;
classHash.insert(def.classname, def.qualified);
classHash.insert(def.qualified, def.qualified);
}
}
- for (const auto &n : qAsConst(namespaceList)) {
+ for (const auto &n : std::as_const(namespaceList)) {
if (!n.hasQNamespace)
continue;
ClassDef def;
@@ -975,8 +1053,10 @@ void Moc::parse()
if (it != classList.end()) {
it->classInfoList += def.classInfoList;
+ Q_ASSERT(it->classInfoList.size() <= std::numeric_limits<int>::max());
it->enumDeclarations.insert(def.enumDeclarations);
it->enumList += def.enumList;
+ Q_ASSERT(it->enumList.size() <= std::numeric_limits<int>::max());
it->flagAliases.insert(def.flagAliases);
} else {
knownGadgets.insert(def.classname, def.qualified);
@@ -1054,25 +1134,27 @@ static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes)
void Moc::generate(FILE *out, FILE *jsonOutput)
{
- QByteArray fn = filename;
- int i = filename.length()-1;
- while (i > 0 && filename.at(i - 1) != '/' && filename.at(i - 1) != '\\')
- --i; // skip path
- if (i >= 0)
- fn = filename.mid(i);
+ QByteArrayView fn = QByteArrayView(filename);
+
+ auto isSlash = [](char ch) { return ch == '/' || ch == '\\'; };
+ auto rit = std::find_if(fn.crbegin(), fn.crend(), isSlash);
+ if (rit != fn.crend())
+ fn = fn.last(rit - fn.crbegin());
+
fprintf(out, "/****************************************************************************\n"
"** Meta object code from reading C++ file '%s'\n**\n" , fn.constData());
fprintf(out, "** Created by: The Qt Meta Object Compiler version %d (Qt %s)\n**\n" , mocOutputRevision, QT_VERSION_STR);
fprintf(out, "** WARNING! All changes made in this file will be lost!\n"
"*****************************************************************************/\n\n");
- fprintf(out, "#include <memory>\n"); // For std::addressof
+ // include header(s) of user class definitions at _first_ to allow
+ // for preprocessor definitions possibly affecting standard headers.
+ // see https://codereview.qt-project.org/c/qt/qtbase/+/445937
if (!noInclude) {
if (includePath.size() && !includePath.endsWith('/'))
includePath += '/';
- for (int i = 0; i < includeFiles.size(); ++i) {
- QByteArray inc = includeFiles.at(i);
- if (inc.at(0) != '<' && inc.at(0) != '"') {
+ for (QByteArray inc : std::as_const(includeFiles)) {
+ if (!inc.isEmpty() && inc.at(0) != '<' && inc.at(0) != '"') {
if (includePath.size() && includePath != "./")
inc.prepend(includePath);
inc = '\"' + inc + '\"';
@@ -1091,16 +1173,10 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
for (const QByteArray &qtContainer : qtContainers)
fprintf(out, "#include <QtCore/%s>\n", qtContainer.constData());
- fprintf(out, "\n%s#include <QtCore/qtmochelpers.h>\n%s\n",
-#if QT_VERSION <= QT_VERSION_CHECK(6, 9, 0)
- "#if __has_include(<QtCore/qtmochelpers.h>)\n",
- "#else\n"
- "QT_BEGIN_MOC_NAMESPACE\n"
- "#endif\n"
-#else
- "", ""
-#endif
- );
+ 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());
@@ -1122,9 +1198,16 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
fprintf(out, "QT_WARNING_DISABLE_GCC(\"-Wuseless-cast\")\n");
fputs("", out);
- for (i = 0; i < classList.size(); ++i) {
- Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out, requireCompleteTypes);
+ for (ClassDef &def : classList) {
+ Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets, out,
+ requireCompleteTypes);
generator.generateCode();
+
+ // generator.generateCode() should have already registered all strings
+ if (Q_UNLIKELY(generator.registeredStringsCount() >= std::numeric_limits<int>::max())) {
+ error("internal limit exceeded: number of parsed strings is too big.");
+ exit(EXIT_FAILURE);
+ }
}
fputs("", out);
@@ -1137,7 +1220,7 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
QJsonArray classesJsonFormatted;
- for (const ClassDef &cdef: qAsConst(classList))
+ for (const ClassDef &cdef: std::as_const(classList))
classesJsonFormatted.append(cdef.toJson());
if (!classesJsonFormatted.isEmpty())
@@ -1234,7 +1317,7 @@ void Moc::parseSignals(ClassDef *def)
}
}
-void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex)
+void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex, Moc::PropertyMode mode)
{
propDef.location = index;
propDef.relativeIndex = propertyIndex;
@@ -1264,8 +1347,10 @@ void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex)
propDef.type = type;
- next();
- propDef.name = lexem();
+ if (mode == Moc::Named) {
+ next();
+ propDef.name = lexem();
+ }
parsePropertyAttributes(propDef);
}
@@ -1282,7 +1367,8 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
};
while (test(IDENTIFIER)) {
- const QByteArray l = lexem();
+ const Symbol &lsym = symbol();
+ const QByteArray l = lsym.lexem();
if (l[0] == 'C' && l == "CONSTANT") {
propDef.constant = true;
continue;
@@ -1305,15 +1391,15 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
QByteArray v, v2;
if (test(LPAREN)) {
v = lexemUntil(RPAREN);
- v = v.mid(1, v.length() - 2); // removes the '(' and ')'
+ v = v.mid(1, v.size() - 2); // removes the '(' and ')'
} else if (test(INTEGER_LITERAL)) {
v = lexem();
if (l != "REVISION")
- error(1);
+ error(lsym);
} else if (test(DEFAULT)) {
v = lexem();
if (l != "READ" && l != "WRITE")
- error(1);
+ error(lsym);
} else {
next(IDENTIFIER);
v = lexem();
@@ -1327,7 +1413,7 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
if (l == "MEMBER")
propDef.member = v;
else
- error(2);
+ error(lsym);
break;
case 'R':
if (l == "READ")
@@ -1338,10 +1424,10 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
bool ok = false;
const int minor = v.toInt(&ok);
if (!ok || !QTypeRevision::isValidSegment(minor))
- error(1);
+ error(lsym);
propDef.revision = QTypeRevision::fromMinorVersion(minor).toEncodedVersion<int>();
} else
- error(2);
+ error(lsym);
break;
case 'S':
if (l == "SCRIPTABLE") {
@@ -1351,27 +1437,27 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
propDef.stored = v + v2;
checkIsFunction(propDef.stored, "STORED");
} else
- error(2);
+ error(lsym);
break;
- case 'W': if (l != "WRITE") error(2);
+ case 'W': if (l != "WRITE") error(lsym);
propDef.write = v;
break;
- case 'B': if (l != "BINDABLE") error(2);
+ case 'B': if (l != "BINDABLE") error(lsym);
propDef.bind = v;
break;
- case 'D': if (l != "DESIGNABLE") error(2);
+ case 'D': if (l != "DESIGNABLE") error(lsym);
propDef.designable = v + v2;
checkIsFunction(propDef.designable, "DESIGNABLE");
break;
- case 'N': if (l != "NOTIFY") error(2);
+ case 'N': if (l != "NOTIFY") error(lsym);
propDef.notify = v;
break;
- case 'U': if (l != "USER") error(2);
+ case 'U': if (l != "USER") error(lsym);
propDef.user = v + v2;
checkIsFunction(propDef.user, "USER");
break;
default:
- error(2);
+ error(lsym);
}
}
if (propDef.constant && !propDef.write.isNull()) {
@@ -1406,11 +1492,11 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
}
}
-void Moc::parseProperty(ClassDef *def)
+void Moc::parseProperty(ClassDef *def, Moc::PropertyMode mode)
{
next(LPAREN);
PropertyDef propDef;
- createPropertyDef(propDef, int(def->propertyList.size()));
+ createPropertyDef(propDef, int(def->propertyList.size()), mode);
next(RPAREN);
def->propertyList += propDef;
@@ -1431,9 +1517,11 @@ void Moc::parsePluginData(ClassDef *def)
} else if (l == "FILE") {
next(STRING_LITERAL);
QByteArray metaDataFile = unquotedLexem();
- QFileInfo fi(QFileInfo(QString::fromLocal8Bit(currentFilenames.top().constData())).dir(), QString::fromLocal8Bit(metaDataFile.constData()));
- for (int j = 0; j < includes.size() && !fi.exists(); ++j) {
- const IncludePath &p = includes.at(j);
+ QFileInfo fi(QFileInfo(QString::fromLocal8Bit(currentFilenames.top())).dir(),
+ QString::fromLocal8Bit(metaDataFile));
+ for (const IncludePath &p : std::as_const(includes)) {
+ if (fi.exists())
+ break;
if (p.isFrameworkPath)
continue;
@@ -1496,7 +1584,7 @@ QByteArray Moc::parsePropertyAccessor()
return accessor;
}
-void Moc::parsePrivateProperty(ClassDef *def)
+void Moc::parsePrivateProperty(ClassDef *def, Moc::PropertyMode mode)
{
next(LPAREN);
PropertyDef propDef;
@@ -1504,7 +1592,7 @@ void Moc::parsePrivateProperty(ClassDef *def)
next(COMMA);
- createPropertyDef(propDef, int(def->propertyList.size()));
+ createPropertyDef(propDef, int(def->propertyList.size()), mode);
def->propertyList += propDef;
}
@@ -1602,7 +1690,7 @@ void Moc::parseInterfaces(ClassDef *def)
}
}
// resolve from classnames to interface ids
- for (int i = 0; i < iface.count(); ++i) {
+ for (qsizetype i = 0; i < iface.size(); ++i) {
const QByteArray iid = interface2IdMap.value(iface.at(i).className);
if (iid.isEmpty())
error("Undefined interface");
@@ -1679,7 +1767,7 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
QByteArray Moc::lexemUntil(Token target)
{
- int from = index;
+ qsizetype from = index;
until(target);
QByteArray s;
while (from <= index) {
@@ -1715,7 +1803,7 @@ bool Moc::until(Token target) {
//when searching commas within the default argument, we should take care of template depth (anglecount)
// unfortunately, we do not have enough semantic information to know if '<' is the operator< or
// the beginning of a template type. so we just use heuristics.
- int possible = -1;
+ qsizetype possible = -1;
while (index < symbols.size()) {
Token t = symbols.at(index++).token;
@@ -1779,7 +1867,8 @@ bool Moc::until(Token target) {
void Moc::checkSuperClasses(ClassDef *def)
{
- const QByteArray firstSuperclass = def->superclassList.value(0).first;
+ Q_ASSERT(!def->superclassList.isEmpty());
+ const QByteArray &firstSuperclass = def->superclassList.at(0).classname;
if (!knownQObjectClasses.contains(firstSuperclass)) {
// enable once we /require/ include paths
@@ -1794,8 +1883,18 @@ void Moc::checkSuperClasses(ClassDef *def)
#endif
return;
}
- for (int i = 1; i < def->superclassList.count(); ++i) {
- const QByteArray superClass = def->superclassList.at(i).first;
+
+ auto isRegisteredInterface = [&def](QByteArrayView super) {
+ auto matchesSuperClass = [&super](const auto &ifaces) {
+ return !ifaces.isEmpty() && ifaces.first().className == super;
+ };
+ return std::any_of(def->interfaceList.cbegin(), def->interfaceList.cend(), matchesSuperClass);
+ };
+
+ const auto end = def->superclassList.cend();
+ auto it = def->superclassList.cbegin() + 1;
+ for (; it != end; ++it) {
+ const QByteArray &superClass = it->classname;
if (knownQObjectClasses.contains(superClass)) {
const QByteArray msg
= "Class "
@@ -1809,14 +1908,7 @@ void Moc::checkSuperClasses(ClassDef *def)
}
if (interface2IdMap.contains(superClass)) {
- bool registeredInterface = false;
- for (int i = 0; i < def->interfaceList.count(); ++i)
- if (def->interfaceList.at(i).constFirst().className == superClass) {
- registeredInterface = true;
- break;
- }
-
- if (!registeredInterface) {
+ if (!isRegisteredInterface(superClass)) {
const QByteArray msg
= "Class "
+ def->classname
@@ -1837,31 +1929,27 @@ void Moc::checkProperties(ClassDef *cdef)
// specify get function, for compatibility we accept functions
// returning pointers, or const char * for QByteArray.
//
- QDuplicateTracker<QByteArray> definedProperties(cdef->propertyList.count());
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- PropertyDef &p = cdef->propertyList[i];
+ QDuplicateTracker<QByteArray> definedProperties(cdef->propertyList.size());
+ auto hasNoAttributes = [&](const PropertyDef &p) {
if (definedProperties.hasSeen(p.name)) {
QByteArray msg = "The property '" + p.name + "' is defined multiple times in class " + cdef->classname + ".";
warning(msg.constData());
}
if (p.read.isEmpty() && p.member.isEmpty() && p.bind.isEmpty()) {
- const int rewind = index;
- if (p.location >= 0)
- index = p.location;
QByteArray msg = "Property declaration " + p.name + " has neither an associated QProperty<> member"
", nor a READ accessor function nor an associated MEMBER variable. The property will be invalid.";
- warning(msg.constData());
- index = rewind;
- if (p.write.isEmpty()) {
- cdef->propertyList.removeAt(i);
- --i;
- }
- continue;
+ const auto &sym = p.location >= 0 ? symbolAt(p.location) : Symbol();
+ warning(sym, msg.constData());
+ if (p.write.isEmpty())
+ return true;
}
+ return false;
+ };
+ cdef->propertyList.removeIf(hasNoAttributes);
- for (int j = 0; j < cdef->publicList.count(); ++j) {
- const FunctionDef &f = cdef->publicList.at(j);
+ for (PropertyDef &p : cdef->propertyList) {
+ for (const FunctionDef &f : std::as_const(cdef->publicList)) {
if (f.name != p.read)
continue;
if (!f.isConst) // get functions must be const
@@ -1887,7 +1975,7 @@ void Moc::checkProperties(ClassDef *cdef)
}
if (!p.notify.isEmpty()) {
int notifyId = -1;
- for (int j = 0; j < cdef->signalList.count(); ++j) {
+ for (int j = 0; j < int(cdef->signalList.size()); ++j) {
const FunctionDef &f = cdef->signalList.at(j);
if (f.name != p.notify) {
continue;
@@ -1898,12 +1986,12 @@ void Moc::checkProperties(ClassDef *cdef)
}
p.notifyId = notifyId;
if (notifyId == -1) {
- int index = cdef->nonClassSignalList.indexOf(p.notify);
+ const int index = int(cdef->nonClassSignalList.indexOf(p.notify));
if (index == -1) {
cdef->nonClassSignalList << p.notify;
- p.notifyId = -1 - cdef->nonClassSignalList.count();
+ p.notifyId = int(-1 - cdef->nonClassSignalList.size());
} else {
- p.notifyId = -2 - index;
+ p.notifyId = int(-2 - index);
}
}
}
@@ -1917,7 +2005,7 @@ QJsonObject ClassDef::toJson() const
cls["qualifiedClassName"_L1] = QString::fromUtf8(qualified.constData());
QJsonArray classInfos;
- for (const auto &info: qAsConst(classInfoList)) {
+ for (const auto &info: std::as_const(classInfoList)) {
QJsonObject infoJson;
infoJson["name"_L1] = QString::fromUtf8(info.name);
infoJson["value"_L1] = QString::fromUtf8(info.value);
@@ -1944,7 +2032,7 @@ QJsonObject ClassDef::toJson() const
QJsonArray props;
- for (const PropertyDef &propDef: qAsConst(propertyList))
+ for (const PropertyDef &propDef: std::as_const(propertyList))
props.append(propDef.toJson());
if (!props.isEmpty())
@@ -1959,12 +2047,12 @@ QJsonObject ClassDef::toJson() const
QJsonArray superClasses;
- for (const auto &super: qAsConst(superclassList)) {
- const auto name = super.first;
- const auto access = super.second;
+ for (const auto &super: std::as_const(superclassList)) {
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);
}
@@ -1972,7 +2060,7 @@ QJsonObject ClassDef::toJson() const
cls["superClasses"_L1] = superClasses;
QJsonArray enums;
- for (const EnumDef &enumDef: qAsConst(enumList))
+ for (const EnumDef &enumDef: std::as_const(enumList))
enums.append(enumDef.toJson(*this));
if (!enums.isEmpty())
cls["enums"_L1] = enums;
@@ -2014,6 +2102,9 @@ QJsonObject FunctionDef::toJson() const
if (revision > 0)
fdef["revision"_L1] = revision;
+ if (wasCloned)
+ fdef["isCloned"_L1] = true;
+
return fdef;
}
@@ -2086,6 +2177,8 @@ QJsonObject EnumDef::toJson(const ClassDef &cdef) const
def["name"_L1] = QString::fromUtf8(name);
if (!enumName.isEmpty())
def["alias"_L1] = QString::fromUtf8(enumName);
+ if (!type.isEmpty())
+ def["type"_L1] = QString::fromUtf8(type);
def["isFlag"_L1] = cdef.enumDeclarations.value(name);
def["isClass"_L1] = isEnumClass;
@@ -2098,4 +2191,23 @@ QJsonObject EnumDef::toJson(const ClassDef &cdef) const
return def;
}
+QByteArray EnumDef::qualifiedType(const ClassDef *cdef) const
+{
+ if (name == cdef->classname) {
+ // The name of the enclosing namespace is the same as the enum class name
+ if (cdef->qualified.contains("::")) {
+ // QTBUG-112996, fully qualify by using cdef->qualified to disambiguate enum
+ // class name and enclosing namespace, e.g.:
+ // namespace A { namespace B { Q_NAMESPACE; enum class B { }; Q_ENUM_NS(B) } }
+ return cdef->qualified % "::" % name;
+ } else {
+ // Just "B"; otherwise the compiler complains about the type "B::B" inside
+ // "B::staticMetaObject" in the generated code; e.g.:
+ // namespace B { Q_NAMESPACE; enum class B { }; Q_ENUM_NS(B) }
+ return name;
+ }
+ }
+ return cdef->classname % "::" % name;
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index c27b2c633f..c1759fb0a3 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -7,13 +7,13 @@
#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>
-#include <ctype.h>
+
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
@@ -42,10 +42,12 @@ struct EnumDef
{
QByteArray name;
QByteArray enumName;
+ QByteArray type;
QList<QByteArray> values;
bool isEnumClass; // c++11 enum class
EnumDef() : isEnumClass(false) {}
QJsonObject toJson(const ClassDef &cdef) const;
+ QByteArray qualifiedType(const ClassDef *cdef) const;
};
Q_DECLARE_TYPEINFO(EnumDef, Q_RELOCATABLE_TYPE);
@@ -101,8 +103,10 @@ Q_DECLARE_TYPEINFO(FunctionDef, Q_RELOCATABLE_TYPE);
struct PropertyDef
{
bool stdCppSet() const {
+ if (name.isEmpty())
+ return false;
QByteArray s("set");
- s += toupper(name[0]);
+ s += QtMiscUtils::toAsciiUpper(name[0]);
s += name.mid(1);
return (s == write);
}
@@ -117,7 +121,7 @@ struct PropertyDef
bool required = false;
int relativeIndex = -1; // property index in current metaobject
- int location = -1; // token index, used for error reporting
+ qsizetype location = -1; // token index, used for error reporting
QJsonObject toJson() const;
};
@@ -147,12 +151,19 @@ struct BaseDef {
QMap<QByteArray, bool> enumDeclarations;
QList<EnumDef> enumList;
QMap<QByteArray, QByteArray> flagAliases;
- int begin = 0;
- int end = 0;
+ qsizetype begin = 0;
+ 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
{
@@ -196,6 +207,8 @@ Q_DECLARE_TYPEINFO(NamespaceDef, Q_RELOCATABLE_TYPE);
class Moc : public Parser
{
public:
+ enum PropertyMode { Named, Anonymous };
+
Moc()
: noInclude(false), mustIncludeQPluginH(false), requireCompleteTypes(false)
{}
@@ -228,6 +241,10 @@ 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();
bool parseEnum(EnumDef *def);
@@ -237,9 +254,11 @@ public:
void parseSlots(ClassDef *def, FunctionDef::Access access);
void parseSignals(ClassDef *def);
- void parseProperty(ClassDef *def);
+ void parseProperty(ClassDef *def, PropertyMode mode);
void parsePluginData(ClassDef *def);
- void createPropertyDef(PropertyDef &def, int propertyIndex);
+
+ void createPropertyDef(PropertyDef &def, int propertyIndex, PropertyMode mode);
+
void parsePropertyAttributes(PropertyDef &propDef);
void parseEnumOrFlag(BaseDef *def, bool isFlag);
void parseFlag(BaseDef *def);
@@ -252,7 +271,7 @@ public:
void parseMocInclude();
void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
QByteArray parsePropertyAccessor();
- void parsePrivateProperty(ClassDef *def);
+ void parsePrivateProperty(ClassDef *def, PropertyMode mode);
void parseFunctionArguments(FunctionDef *def);
@@ -270,14 +289,17 @@ public:
void checkSuperClasses(ClassDef *def);
void checkProperties(ClassDef* cdef);
+ bool testForFunctionModifiers(FunctionDef *def);
+
+ void checkListSizes(const ClassDef &def);
};
inline QByteArray noRef(const QByteArray &type)
{
if (type.endsWith('&')) {
if (type.endsWith("&&"))
- return type.left(type.length()-2);
- return type.left(type.length()-1);
+ return type.left(type.size()-2);
+ return type.left(type.size()-1);
}
return type;
}
diff --git a/src/tools/moc/parser.cpp b/src/tools/moc/parser.cpp
index 6fa0e645d3..1cfb8ce486 100644
--- a/src/tools/moc/parser.cpp
+++ b/src/tools/moc/parser.cpp
@@ -8,42 +8,80 @@
QT_BEGIN_NAMESPACE
-#ifdef USE_LEXEM_STORE
-Symbol::LexemStore Symbol::lexemStore;
-#endif
-
static const char *error_msg = nullptr;
+/*! \internal
+ Base implementation for printing diagnostic messages.
+
+ For example:
+ "/path/to/file:line:column: error: %s\n"
+ '%s' is replaced by \a msg. (Currently "column" is always 1).
+
+ If sym.lineNum is -1, the line and column parts aren't printed:
+ "/path/to/file: error: %s\n"
+
+ \a formatStringSuffix specifies the type of the message e.g.:
+ "error: %s\n"
+ "warning: %s\n"
+ "note: %s\n"
+ "Parse error at %s\n" (from defaultErrorMsg())
+*/
+void Parser::printMsg(QByteArrayView formatStringSuffix, QByteArrayView msg, const Symbol &sym)
+{
+ if (sym.lineNum != -1) {
#ifdef Q_CC_MSVC
-#define ErrorFormatString "%s(%d:%d): "
+ QByteArray formatString = "%s(%d:%d): " + formatStringSuffix;
#else
-#define ErrorFormatString "%s:%d:%d: "
+ QByteArray formatString = "%s:%d:%d: " + formatStringSuffix;
#endif
+ fprintf(stderr, formatString.constData(),
+ currentFilenames.top().constData(), sym.lineNum, 1, msg.data());
+ } else {
+ QByteArray formatString = "%s: " + formatStringSuffix;
+ fprintf(stderr, formatString.constData(),
+ currentFilenames.top().constData(), msg.data());
+ }
+}
+
+void Parser::defaultErrorMsg(const Symbol &sym)
+{
+ if (sym.lineNum != -1)
+ printMsg("error: Parse error at \"%s\"\n", sym.lexem().data(), sym);
+ else
+ printMsg("error: could not parse file\n", "", sym);
+}
-void Parser::error(int rollback) {
- index -= rollback;
- error();
+void Parser::error(const Symbol &sym)
+{
+ defaultErrorMsg(sym);
+ exit(EXIT_FAILURE);
}
-void Parser::error(const char *msg) {
+
+void Parser::error(const char *msg)
+{
if (msg || error_msg)
- fprintf(stderr, ErrorFormatString "error: %s\n",
- currentFilenames.top().constData(), symbol().lineNum, 1, msg?msg:error_msg);
+ printMsg("error: %s\n",
+ msg ? msg : error_msg,
+ index > 0 ? symbol() : Symbol{});
else
- fprintf(stderr, ErrorFormatString "error: Parse error at \"%s\"\n",
- currentFilenames.top().constData(), symbol().lineNum, 1, symbol().lexem().data());
+ defaultErrorMsg(symbol());
+
exit(EXIT_FAILURE);
}
+void Parser::warning(const Symbol &sym, QByteArrayView msg)
+{
+ if (displayWarnings)
+ printMsg("warning: %s\n", msg, sym);
+}
+
void Parser::warning(const char *msg) {
- if (displayWarnings && msg)
- fprintf(stderr, ErrorFormatString "warning: %s\n",
- currentFilenames.top().constData(), qMax(0, index > 0 ? symbol().lineNum : 0), 1, msg);
+ warning(index > 0 ? symbol() : Symbol{}, msg);
}
void Parser::note(const char *msg) {
if (displayNotes && msg)
- fprintf(stderr, ErrorFormatString "note: %s\n",
- currentFilenames.top().constData(), qMax(0, index > 0 ? symbol().lineNum : 0), 1, msg);
+ printMsg("note: %s\n", msg, index > 0 ? symbol() : Symbol{});
}
QT_END_NAMESPACE
diff --git a/src/tools/moc/parser.h b/src/tools/moc/parser.h
index 5f754d9b19..6fe982a1ce 100644
--- a/src/tools/moc/parser.h
+++ b/src/tools/moc/parser.h
@@ -5,6 +5,7 @@
#define PARSER_H
#include "symbols.h"
+#include <QtCore/qbytearrayview.h>
#include <stack>
@@ -15,7 +16,7 @@ class Parser
public:
Parser():index(0), displayWarnings(true), displayNotes(true) {}
Symbols symbols;
- int index;
+ qsizetype index;
bool displayWarnings;
bool displayNotes;
@@ -43,11 +44,15 @@ public:
inline QByteArray lexem() { return symbols.at(index-1).lexem();}
inline QByteArray unquotedLexem() { return symbols.at(index-1).unquotedLexem();}
inline const Symbol &symbol() { return symbols.at(index-1);}
+ inline const Symbol &symbolAt(qsizetype idx) { return symbols.at(idx); }
- Q_NORETURN void error(int rollback);
+ Q_NORETURN void error(const Symbol &symbol);
Q_NORETURN void error(const char *msg = nullptr);
void warning(const char * = nullptr);
+ void warning(const Symbol &sym, QByteArrayView msg);
void note(const char * = nullptr);
+ void defaultErrorMsg(const Symbol &sym);
+ void printMsg(QByteArrayView formatStringSuffix, QByteArrayView msg, const Symbol &sym);
};
@@ -62,7 +67,7 @@ inline bool Parser::test(Token token)
inline Token Parser::lookup(int k)
{
- const int l = index - 1 + k;
+ const qsizetype l = index - 1 + k;
return l < symbols.size() ? symbols.at(l).token : NOTOKEN;
}
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index a0c0b7ffaa..11ea8d417e 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -12,6 +12,8 @@
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
#include "ppkeywords.cpp"
#include "keywords.cpp"
@@ -212,7 +214,9 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
data -= 2;
break;
case DIGIT:
- while (is_digit_char(*data) || *data == '\'')
+ {
+ bool hasSeenTokenSeparator = false;;
+ while (isAsciiDigit(*data) || (hasSeenTokenSeparator = *data == '\''))
++data;
if (!*data || *data != '.') {
token = INTEGER_LITERAL;
@@ -221,22 +225,30 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
|| *data == 'b' || *data == 'B')
&& *lexem == '0') {
++data;
- while (is_hex_char(*data) || *data == '\'')
+ while (isHexDigit(*data) || (hasSeenTokenSeparator = *data == '\''))
+ ++data;
+ } else if (*data == 'L') // TODO: handle other suffixes
+ ++data;
+ if (!hasSeenTokenSeparator) {
+ while (is_ident_char(*data)) {
++data;
+ token = IDENTIFIER;
+ }
}
break;
}
token = FLOATING_LITERAL;
++data;
Q_FALLTHROUGH();
+ }
case FLOATING_LITERAL:
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
if (*data == '+' || *data == '-')
++data;
if (*data == 'e' || *data == 'E') {
++data;
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
}
if (*data == 'f' || *data == 'F'
@@ -315,16 +327,7 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
continue; //ignore
}
}
-#ifdef USE_LEXEM_STORE
- if (!Preprocessor::preprocessOnly
- && token != IDENTIFIER
- && token != STRING_LITERAL
- && token != FLOATING_LITERAL
- && token != INTEGER_LITERAL)
- symbols += Symbol(lineNum, token);
- else
-#endif
- symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
+ symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
} else { // Preprocessor
@@ -390,7 +393,7 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
token = PP_CHARACTER_LITERAL;
break;
case PP_DIGIT:
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
if (!*data || *data != '.') {
token = PP_INTEGER_LITERAL;
@@ -398,22 +401,23 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
(*data == 'x' || *data == 'X')
&& *lexem == '0') {
++data;
- while (is_hex_char(*data) || *data == '\'')
+ while (isHexDigit(*data) || *data == '\'')
++data;
- }
+ } else if (*data == 'L') // TODO: handle other suffixes
+ ++data;
break;
}
token = PP_FLOATING_LITERAL;
++data;
Q_FALLTHROUGH();
case PP_FLOATING_LITERAL:
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
if (*data == '+' || *data == '-')
++data;
if (*data == 'e' || *data == 'E') {
++data;
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
}
if (*data == 'f' || *data == 'F'
@@ -495,22 +499,14 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
}
if (mode == PreparePreprocessorStatement)
continue;
-#ifdef USE_LEXEM_STORE
- if (token != PP_IDENTIFIER
- && token != PP_STRING_LITERAL
- && token != PP_FLOATING_LITERAL
- && token != PP_INTEGER_LITERAL)
- symbols += Symbol(lineNum, token);
- else
-#endif
- symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
+ symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
}
}
symbols += Symbol(); // eof symbol
return symbols;
}
-void Preprocessor::macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand, int &index,
+void Preprocessor::macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand, qsizetype &index,
int lineNum, bool one, const QSet<QByteArray> &excludeSymbols)
{
SymbolStack symbols;
@@ -618,19 +614,22 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
HashHash
} mode = Normal;
- for (int i = 0; i < macro.symbols.size(); ++i) {
- const Symbol &s = macro.symbols.at(i);
+ const auto end = macro.symbols.cend();
+ auto it = macro.symbols.cbegin();
+ const auto lastSym = std::prev(macro.symbols.cend(), !macro.symbols.isEmpty() ? 1 : 0);
+ for (; it != end; ++it) {
+ const Symbol &s = *it;
if (s.token == HASH || s.token == PP_HASHHASH) {
mode = (s.token == HASH ? Hash : HashHash);
continue;
}
- int index = macro.arguments.indexOf(s);
+ const qsizetype index = macro.arguments.indexOf(s);
if (mode == Normal) {
if (index >= 0 && index < arguments.size()) {
// each argument undoergoes macro expansion if it's not used as part of a # or ##
- if (i == macro.symbols.size() - 1 || macro.symbols.at(i + 1).token != PP_HASHHASH) {
+ if (it == lastSym || std::next(it)->token != PP_HASHHASH) {
Symbols arg = arguments.at(index);
- int idx = 1;
+ qsizetype idx = 1;
macroExpand(&expansion, that, arg, idx, lineNum, false, symbols.excludeSymbols());
} else {
expansion += arguments.at(index);
@@ -649,9 +648,9 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
const Symbols &arg = arguments.at(index);
QByteArray stringified;
- for (int i = 0; i < arg.size(); ++i) {
- stringified += arg.at(i).lexem();
- }
+ for (const Symbol &sym : arg)
+ stringified += sym.lexem();
+
stringified.replace('"', "\\\"");
stringified.prepend('"');
stringified.append('"');
@@ -685,8 +684,8 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
if (index >= 0 && index < arguments.size()) {
const Symbols &arg = arguments.at(index);
- for (int i = 1; i < arg.size(); ++i)
- expansion += arg.at(i);
+ if (!arg.isEmpty())
+ expansion.append(arg.cbegin() + 1, arg.cend());
}
}
mode = Normal;
@@ -927,7 +926,11 @@ int PP_Expression::primary_expression()
test(PP_RPAREN);
} else {
next();
- value = lexem().toInt(nullptr, 0);
+ const QByteArray &lex = lexem();
+ auto lexView = QByteArrayView(lex);
+ if (lex.endsWith('L'))
+ lexView.chop(1);
+ value = lexView.toInt(nullptr, 0);
}
return value;
}
@@ -966,7 +969,7 @@ static void mergeStringLiterals(Symbols *_symbols)
for (Symbols::iterator i = symbols.begin(); i != symbols.end(); ++i) {
if (i->token == STRING_LITERAL) {
Symbols::Iterator mergeSymbol = i;
- int literalsLength = mergeSymbol->len;
+ qsizetype literalsLength = mergeSymbol->len;
while (++i != symbols.end() && i->token == STRING_LITERAL)
literalsLength += i->len - 2; // no quotes
@@ -980,7 +983,7 @@ static void mergeStringLiterals(Symbols *_symbols)
for (Symbols::iterator j = mergeSymbol + 1; j != i; ++j)
mergeSymbolLexem.append(j->lex.constData() + j->from + 1, j->len - 2); // append j->unquotedLexem()
mergeSymbolLexem.append('"');
- mergeSymbol->len = mergeSymbol->lex.length();
+ mergeSymbol->len = mergeSymbol->lex.size();
mergeSymbol->from = 0;
i = symbols.erase(mergeSymbol + 1, i);
}
@@ -1000,10 +1003,12 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
fprintf(stderr, "debug-includes: searching for '%s'\n", include.constData());
}
- for (int j = 0; j < includepaths.size() && !fi.exists(); ++j) {
- const Parser::IncludePath &p = includepaths.at(j);
+ for (const Parser::IncludePath &p : includepaths) {
+ if (fi.exists())
+ break;
+
if (p.isFrameworkPath) {
- const int slashPos = include.indexOf('/');
+ const qsizetype slashPos = include.indexOf('/');
if (slashPos == -1)
continue;
fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
@@ -1099,7 +1104,7 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
continue;
Symbols saveSymbols = symbols;
- int saveIndex = index;
+ qsizetype saveIndex = index;
// phase 1: get rid of backslash-newlines
input = cleaned(input);
@@ -1134,14 +1139,14 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
} else {
macro.isFunction = false;
}
- int start = index;
+ qsizetype start = index;
until(PP_NEWLINE);
macro.symbols.reserve(index - start - 1);
// remove whitespace where there shouldn't be any:
// Before and after the macro, after a # and around ##
Token lastToken = HASH; // skip shitespace at the beginning
- for (int i = start; i < index - 1; ++i) {
+ for (qsizetype i = start; i < index - 1; ++i) {
Token token = symbols.at(i).token;
if (token == WHITESPACE) {
if (lastToken == PP_HASH || lastToken == HASH ||
@@ -1284,7 +1289,7 @@ void Preprocessor::parseDefineArguments(Macro *m)
if (!test(PP_RPAREN))
error("missing ')' in macro argument list");
break;
- } else if (!is_identifier(l.constData(), l.length())) {
+ } else if (!is_identifier(l.constData(), l.size())) {
error("Unexpected character in macro argument list.");
}
}
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index 84186fec9e..3509e83dce 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -20,11 +20,7 @@ struct Macro
Symbols symbols;
};
-#ifdef USE_LEXEM_STORE
-typedef QByteArray MacroName;
-#else
typedef SubArray MacroName;
-#endif
typedef QHash<MacroName, Macro> Macros;
class QFile;
@@ -48,8 +44,9 @@ public:
void substituteUntilNewline(Symbols &substituted);
static Symbols macroExpandIdentifier(Preprocessor *that, SymbolStack &symbols, int lineNum, QByteArray *macroName);
- static void macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand, int &index, int lineNum, bool one,
- const QSet<QByteArray> &excludeSymbols = QSet<QByteArray>());
+ static void macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand,
+ qsizetype &index, int lineNum, bool one,
+ const QSet<QByteArray> &excludeSymbols = QSet<QByteArray>());
int evaluateCondition();
diff --git a/src/tools/moc/symbols.h b/src/tools/moc/symbols.h
index cde01cf11d..869f7c793f 100644
--- a/src/tools/moc/symbols.h
+++ b/src/tools/moc/symbols.h
@@ -7,7 +7,7 @@
#include "token.h"
#include <qdebug.h>
-#include <qhash.h>
+#include <qhashfunctions.h>
#include <qlist.h>
#include <qstack.h>
#include <qstring.h>
@@ -15,73 +15,48 @@
QT_BEGIN_NAMESPACE
-//#define USE_LEXEM_STORE
-
struct SubArray
{
- inline SubArray():from(0),len(-1){}
+ inline SubArray() = default;
inline SubArray(const QByteArray &a):array(a),from(0), len(a.size()){}
inline SubArray(const char *s):array(s),from(0) { len = array.size(); }
- inline SubArray(const QByteArray &a, int from, int len):array(a), from(from), len(len){}
+ SubArray(const QByteArray &a, qsizetype from, qsizetype len)
+ : array(a), from(from), len(len)
+ {
+ }
QByteArray array;
- int from, len;
+ qsizetype from = 0;
+ qsizetype len = -1;
inline bool operator==(const SubArray &other) const {
if (len != other.len)
return false;
- for (int i = 0; i < len; ++i)
- if (array.at(from + i) != other.array.at(other.from + i))
- return false;
- return true;
+ const auto begin = array.cbegin() + from;
+ const auto end = begin + len;
+ const auto other_begin = other.array.cbegin() + other.from;
+ return std::equal(begin, end, other_begin);
}
};
-inline size_t qHash(const SubArray &key)
+inline size_t qHash(const SubArray &key, size_t seed = 0)
{
- return qHash(QLatin1StringView(key.array.constData() + key.from, key.len));
+ return qHash(QLatin1StringView(key.array.constData() + key.from, key.len), seed);
}
struct Symbol
{
-
-#ifdef USE_LEXEM_STORE
- typedef QHash<SubArray, QHashDummyValue> LexemStore;
- static LexemStore lexemStore;
-
- inline Symbol() : lineNum(-1),token(NOTOKEN){}
- inline Symbol(int lineNum, Token token):
- lineNum(lineNum), token(token){}
- inline Symbol(int lineNum, Token token, const QByteArray &lexem):
- lineNum(lineNum), token(token),lex(lexem){}
- inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len):
- lineNum(lineNum), token(token){
- LexemStore::const_iterator it = lexemStore.constFind(SubArray(lexem, from, len));
-
- if (it != lexemStore.constEnd()) {
- lex = it.key().array;
- } else {
- lex = lexem.mid(from, len);
- lexemStore.insert(lex, QHashDummyValue());
- }
+ inline Symbol() = default;
+ inline Symbol(int lineNum, Token token) : lineNum(lineNum), token(token) { }
+ inline Symbol(int lineNum, Token token, const QByteArray &lexem)
+ : lineNum(lineNum), token(token), lex(lexem), len(lex.size())
+ {
}
- int lineNum;
- Token token;
- inline QByteArray unquotedLexem() const { return lex.mid(1, lex.length()-2); }
- inline QByteArray lexem() const { return lex; }
- inline operator QByteArray() const { return lex; }
- QByteArray lex;
-
-#else
-
- inline Symbol() : lineNum(-1),token(NOTOKEN), from(0),len(-1) {}
- inline Symbol(int lineNum, Token token):
- lineNum(lineNum), token(token), from(0), len(-1) {}
- inline Symbol(int lineNum, Token token, const QByteArray &lexem):
- lineNum(lineNum), token(token), lex(lexem), from(0) { len = lex.size(); }
- inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len):
- lineNum(lineNum), token(token),lex(lexem),from(from), len(len){}
- int lineNum;
- Token token;
+ Symbol(int lineNum, Token token, const QByteArray &lexem, qsizetype from, qsizetype len)
+ : lineNum(lineNum), token(token), lex(lexem), from(from), len(len)
+ {
+ }
+ int lineNum = -1;
+ Token token = NOTOKEN;
inline QByteArray lexem() const { return lex.mid(from, len); }
inline QByteArray unquotedLexem() const { return lex.mid(from+1, len-2); }
inline operator SubArray() const { return SubArray(lex, from, len); }
@@ -90,9 +65,8 @@ struct Symbol
return SubArray(lex, from, len) == SubArray(o.lex, o.from, o.len);
}
QByteArray lex;
- int from, len;
-
-#endif
+ qsizetype from = 0;
+ qsizetype len = -1;
};
Q_DECLARE_TYPEINFO(Symbol, Q_RELOCATABLE_TYPE);
@@ -102,7 +76,7 @@ struct SafeSymbols {
Symbols symbols;
QByteArray expandedMacro;
QSet<QByteArray> excludedSymbols;
- int index;
+ qsizetype index;
};
Q_DECLARE_TYPEINFO(SafeSymbols, Q_RELOCATABLE_TYPE);
@@ -127,13 +101,13 @@ public:
inline QByteArray lexem() const { return symbol().lexem(); }
inline QByteArray unquotedLexem() { return symbol().unquotedLexem(); }
- bool dontReplaceSymbol(const QByteArray &name);
- QSet<QByteArray> excludeSymbols();
+ bool dontReplaceSymbol(const QByteArray &name) const;
+ QSet<QByteArray> excludeSymbols() const;
};
inline bool SymbolStack::test(Token token)
{
- int stackPos = size() - 1;
+ qsizetype stackPos = size() - 1;
while (stackPos >= 0 && at(stackPos).index >= at(stackPos).symbols.size())
--stackPos;
if (stackPos < 0)
@@ -145,21 +119,20 @@ inline bool SymbolStack::test(Token token)
return false;
}
-inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name)
+inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name) const
{
- for (int i = 0; i < size(); ++i) {
- if (name == at(i).expandedMacro || at(i).excludedSymbols.contains(name))
- return true;
- }
- return false;
+ auto matchesName = [&name](const SafeSymbols &sf) {
+ return name == sf.expandedMacro || sf.excludedSymbols.contains(name);
+ };
+ return std::any_of(cbegin(), cend(), matchesName);
}
-inline QSet<QByteArray> SymbolStack::excludeSymbols()
+inline QSet<QByteArray> SymbolStack::excludeSymbols() const
{
QSet<QByteArray> set;
- for (int i = 0; i < size(); ++i) {
- set << at(i).expandedMacro;
- set += at(i).excludedSymbols;
+ for (const SafeSymbols &sf : *this) {
+ set << sf.expandedMacro;
+ set += sf.excludedSymbols;
}
return set;
}
diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h
index a58b2e9f9f..a70808370d 100644
--- a/src/tools/moc/token.h
+++ b/src/tools/moc/token.h
@@ -133,6 +133,7 @@ QT_BEGIN_NAMESPACE
F(Q_NAMESPACE_TOKEN) \
F(Q_NAMESPACE_EXPORT_TOKEN) \
F(Q_PROPERTY_TOKEN) \
+ F(QT_ANONYMOUS_PROPERTY_TOKEN) \
F(Q_PLUGIN_METADATA_TOKEN) \
F(Q_ENUMS_TOKEN) \
F(Q_ENUM_TOKEN) \
@@ -154,6 +155,7 @@ QT_BEGIN_NAMESPACE
F(Q_INVOKABLE_TOKEN) \
F(Q_SCRIPTABLE_TOKEN) \
F(Q_PRIVATE_PROPERTY_TOKEN) \
+ F(QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN) \
F(Q_REVISION_TOKEN) \
F(Q_MOC_INCLUDE_TOKEN) \
F(SPECIAL_TREATMENT_MARK) \
diff --git a/src/tools/moc/util/generate.sh b/src/tools/moc/util/generate.sh
index 4514ca4930..6be06e5a91 100755
--- a/src/tools/moc/util/generate.sh
+++ b/src/tools/moc/util/generate.sh
@@ -6,7 +6,7 @@ set -ex
qmake
make
-cat licenseheader.txt > ../keywords.cpp
-cat licenseheader.txt > ../ppkeywords.cpp
+cat licenseheader.cpp.in > ../keywords.cpp
+cat licenseheader.cpp.in > ../ppkeywords.cpp
./generate_keywords >> ../keywords.cpp
./generate_keywords preprocessor >> ../ppkeywords.cpp
diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp
index fb78ae87d0..a6c85af9f1 100644
--- a/src/tools/moc/util/generate_keywords.cpp
+++ b/src/tools/moc/util/generate_keywords.cpp
@@ -193,6 +193,7 @@ static const Keyword keywords[] = {
{ "Q_GADGET", "Q_GADGET_TOKEN" },
{ "Q_GADGET_EXPORT", "Q_GADGET_EXPORT_TOKEN" },
{ "Q_PROPERTY", "Q_PROPERTY_TOKEN" },
+ { "QT_ANONYMOUS_PROPERTY", "QT_ANONYMOUS_PROPERTY_TOKEN" },
{ "Q_PLUGIN_METADATA", "Q_PLUGIN_METADATA_TOKEN" },
{ "Q_ENUMS", "Q_ENUMS_TOKEN" },
{ "Q_ENUM", "Q_ENUM_TOKEN" },
@@ -218,6 +219,7 @@ static const Keyword keywords[] = {
{ "Q_SLOT", "Q_SLOT_TOKEN" },
{ "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" },
{ "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" },
+ { "QT_ANONYMOUS_PRIVATE_PROPERTY", "QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN" },
{ "Q_REVISION", "Q_REVISION_TOKEN" },
{ "Q_MOC_INCLUDE", "Q_MOC_INCLUDE_TOKEN" },
{ "\n", "NEWLINE" },
diff --git a/src/tools/moc/util/licenseheader.txt b/src/tools/moc/util/licenseheader.cpp.in
index 42958a66f5..42958a66f5 100644
--- a/src/tools/moc/util/licenseheader.txt
+++ b/src/tools/moc/util/licenseheader.cpp.in
diff --git a/src/tools/moc/utils.h b/src/tools/moc/utils.h
index 358780a33d..0b0d70f462 100644
--- a/src/tools/moc/utils.h
+++ b/src/tools/moc/utils.h
@@ -5,6 +5,9 @@
#define UTILS_H
#include <QtCore/qglobal.h>
+#include <private/qtools_p.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -20,49 +23,20 @@ inline bool is_space(char s)
inline bool is_ident_start(char s)
{
- return ((s >= 'a' && s <= 'z')
- || (s >= 'A' && s <= 'Z')
- || s == '_' || s == '$'
- );
+ using namespace QtMiscUtils;
+ return isAsciiLower(s) || isAsciiUpper(s) || s == '_' || s == '$';
}
inline bool is_ident_char(char s)
{
- return ((s >= 'a' && s <= 'z')
- || (s >= 'A' && s <= 'Z')
- || (s >= '0' && s <= '9')
- || s == '_' || s == '$'
- );
+ return QtMiscUtils::isAsciiLetterOrNumber(s) || s == '_' || s == '$';
}
-inline bool is_identifier(const char *s, int len)
+inline bool is_identifier(const char *s, qsizetype len)
{
if (len < 1)
return false;
- if (!is_ident_start(*s))
- return false;
- for (int i = 1; i < len; ++i)
- if (!is_ident_char(s[i]))
- return false;
- return true;
-}
-
-inline bool is_digit_char(char s)
-{
- return (s >= '0' && s <= '9');
-}
-
-inline bool is_octal_char(char s)
-{
- return (s >= '0' && s <= '7');
-}
-
-inline bool is_hex_char(char s)
-{
- return ((s >= 'a' && s <= 'f')
- || (s >= 'A' && s <= 'F')
- || (s >= '0' && s <= '9')
- );
+ return std::all_of(s, s + len, is_ident_char);
}
inline const char *skipQuote(const char *data)