summaryrefslogtreecommitdiffstats
path: root/src/tools/moc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/moc')
-rw-r--r--src/tools/moc/CMakeLists.txt17
-rw-r--r--src/tools/moc/cbordevice.h31
-rw-r--r--src/tools/moc/collectjson.cpp31
-rw-r--r--src/tools/moc/collectjson.h29
-rw-r--r--src/tools/moc/generator.cpp776
-rw-r--r--src/tools/moc/generator.h36
-rw-r--r--src/tools/moc/keywords.cpp446
-rw-r--r--src/tools/moc/main.cpp109
-rw-r--r--src/tools/moc/moc.cpp608
-rw-r--r--src/tools/moc/moc.h77
-rw-r--r--src/tools/moc/outputrevision.h29
-rw-r--r--src/tools/moc/parser.cpp105
-rw-r--r--src/tools/moc/parser.h40
-rw-r--r--src/tools/moc/ppkeywords.cpp29
-rw-r--r--src/tools/moc/preprocessor.cpp176
-rw-r--r--src/tools/moc/preprocessor.h41
-rw-r--r--src/tools/moc/symbols.h139
-rw-r--r--src/tools/moc/token.cpp29
-rw-r--r--src/tools/moc/token.h32
-rwxr-xr-xsrc/tools/moc/util/generate.sh33
-rw-r--r--src/tools/moc/util/generate_keywords.cpp32
-rw-r--r--src/tools/moc/util/generate_keywords.pro5
-rw-r--r--src/tools/moc/util/licenseheader.cpp.in3
-rw-r--r--src/tools/moc/util/licenseheader.txt28
-rw-r--r--src/tools/moc/utils.h71
25 files changed, 1359 insertions, 1593 deletions
diff --git a/src/tools/moc/CMakeLists.txt b/src/tools/moc/CMakeLists.txt
index 88dce045f8..b98b7ab4e9 100644
--- a/src/tools/moc/CMakeLists.txt
+++ b/src/tools/moc/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from moc.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## moc Tool:
@@ -6,10 +7,11 @@
qt_get_tool_target_name(target_name moc)
qt_internal_add_tool(${target_name}
- BOOTSTRAP
+ 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
@@ -19,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
@@ -27,17 +28,15 @@ qt_internal_add_tool(${target_name}
QT_MOC
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_FROM_BYTEARRAY
- QT_NO_COMPRESS
QT_NO_FOREACH
+ QT_NO_QPAIR
+ QT_USE_NODISCARD_FILE_OPEN
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
../../3rdparty/tinycbor/src
../shared
)
-
-#### Keys ignored in scope 1:.:.:moc.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt Meta Object Compiler"
-# _OPTION = "host_build"
+qt_internal_return_unless_building_tools()
## Scopes:
#####################################################################
diff --git a/src/tools/moc/cbordevice.h b/src/tools/moc/cbordevice.h
index dbfc537dd2..7668e4c0be 100644
--- a/src/tools/moc/cbordevice.h
+++ b/src/tools/moc/cbordevice.h
@@ -1,34 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#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 6577a3216b..d542e2abc4 100644
--- a/src/tools/moc/collectjson.cpp
+++ b/src/tools/moc/collectjson.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <qfile.h>
#include <qjsonarray.h>
@@ -85,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/collectjson.h b/src/tools/moc/collectjson.h
index 3a33952a54..b16ae61519 100644
--- a/src/tools/moc/collectjson.h
+++ b/src/tools/moc/collectjson.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef COLLECTJSON_H
#define COLLECTJSON_H
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 37797ef7db..02e9ef178a 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -1,32 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "generator.h"
#include "cbordevice.h"
@@ -48,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
uint nameToBuiltinType(const QByteArray &name)
{
if (name.isEmpty())
@@ -80,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),
@@ -92,32 +70,53 @@ 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;
}
+// 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;
+ const qsizetype len = s.size();
+ qsizetype idx = 0;
+
+ do {
+ qsizetype spanLen = qMin(ColumnWidth - 2, len - idx);
+ // don't cut escape sequences at the end of a line
+ const qsizetype backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
+ if (backSlashPos >= idx) {
+ const qsizetype escapeLen = lengthOfEscapeSequence(s, backSlashPos);
+ spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, len - idx);
+ }
+ fprintf(out, "\n \"%.*s\"", int(spanLen), s.constData() + idx);
+ idx += spanLen;
+ } while (idx < len);
+}
+
void Generator::strreg(const QByteArray &s)
{
if (!strings.contains(s))
@@ -126,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;
}
@@ -137,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;
}
@@ -175,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);
}
}
@@ -195,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");
@@ -209,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;
}
@@ -237,128 +251,58 @@ void Generator::generateCode()
registerPropertyStrings();
registerEnumStrings();
- QByteArray qualifiedClassNameIdentifier = cdef->qualified;
- qualifiedClassNameIdentifier.replace(':', '_');
+ const bool hasStaticMetaCall =
+ (cdef->hasQObject || !cdef->methodList.isEmpty()
+ || !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
+
+ const QByteArray qualifiedClassNameIdentifier = generateQualifiedClassNameIdentifier(cdef->qualified);
+
+ // ensure the qt_meta_stringdata_XXXX_t type is local
+ fprintf(out, "namespace {\n");
//
-// Build stringdata struct
+// Build the strings using QtMocHelpers::StringData
//
- const int constCharArraySizeLimit = 65535;
- fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
- fprintf(out, " const uint offsetsAndSize[%d];\n", int(strings.size()*2));
- {
- int stringDataLength = 0;
- int stringDataCounter = 0;
- for (int i = 0; i < strings.size(); ++i) {
- int thisLength = strings.at(i).length() + 1;
- stringDataLength += thisLength;
- if (stringDataLength / constCharArraySizeLimit) {
- // save previous stringdata and start computing the next one.
- fprintf(out, " char stringdata%d[%d];\n", stringDataCounter++, stringDataLength - thisLength);
- stringDataLength = thisLength;
- }
- }
- fprintf(out, " char stringdata%d[%d];\n", stringDataCounter, stringDataLength);
- }
- fprintf(out, "};\n");
-
- // Macro that expands into a QByteArrayData. The offset member is
- // calculated from 1) the offset of the actual characters in the
- // stringdata.stringdata member, and 2) the stringdata.data index of the
- // QByteArrayData being defined. This calculation relies on the
- // QByteArrayData::data() implementation returning simply "this + offset".
- fprintf(out, "#define QT_MOC_LITERAL(ofs, len) \\\n"
- " uint(offsetof(qt_meta_stringdata_%s_t, stringdata0) + ofs), len \n",
- qualifiedClassNameIdentifier.constData());
-
- fprintf(out, "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n",
+ fprintf(out, "\n#ifdef QT_MOC_HAS_STRINGDATA\n"
+ "struct qt_meta_stringdata_%s_t {};\n"
+ "constexpr auto qt_meta_stringdata_%s = QtMocHelpers::stringData(",
qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
- fprintf(out, " {\n");
{
- int idx = 0;
- for (int i = 0; i < strings.size(); ++i) {
- const QByteArray &str = strings.at(i);
- fprintf(out, "QT_MOC_LITERAL(%d, %d)", idx, int(str.length()));
- if (i != strings.size() - 1)
- fputc(',', out);
- const QByteArray comment = str.length() > 32 ? str.left(29) + "..." : str;
- fprintf(out, " // \"%s\"\n", comment.size() ? comment.constData() : "");
- idx += str.length() + 1;
- for (int j = 0; j < str.length(); ++j) {
- if (str.at(j) == '\\') {
- int cnt = lengthOfEscapeSequence(str, j) - 1;
- idx -= cnt;
- j += cnt;
- }
- }
- }
- fprintf(out, "\n },\n");
- }
-
-//
-// Build stringdata array
-//
- fprintf(out, " \"");
- int col = 0;
- int len = 0;
- int stringDataLength = 0;
- for (int i = 0; i < strings.size(); ++i) {
- QByteArray s = strings.at(i);
- len = s.length();
- stringDataLength += len + 1;
- if (stringDataLength >= constCharArraySizeLimit) {
- fprintf(out, "\",\n \"");
- stringDataLength = len + 1;
- col = 0;
- } else if (i)
- fputs("\\0", out); // add \0 at the end of each string
-
- if (col && col + len >= 72) {
- fprintf(out, "\"\n \"");
- col = 0;
- } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
- fprintf(out, "\"\"");
- len += 2;
- }
- int idx = 0;
- while (idx < s.length()) {
- if (idx > 0) {
- col = 0;
- fprintf(out, "\"\n \"");
- }
- int spanLen = qMin(70, s.length() - idx);
- // don't cut escape sequences at the end of a line
- int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
- if (backSlashPos >= idx) {
- int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
- spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
- }
- fprintf(out, "%.*s", spanLen, s.constData() + idx);
- idx += spanLen;
- col += spanLen;
+ char comma = 0;
+ for (const QByteArray &str : strings) {
+ if (comma)
+ fputc(comma, out);
+ printStringWithIndentation(out, str);
+ comma = ',';
}
- col += len + 2;
}
-
-// Terminate stringdata struct
- fprintf(out, "\"\n};\n");
- fprintf(out, "#undef QT_MOC_LITERAL\n\n");
+ fprintf(out, "\n);\n"
+ "#else // !QT_MOC_HAS_STRINGDATA\n");
+ fprintf(out, "#error \"qtmochelpers.h not found or too old.\"\n");
+ fprintf(out, "#endif // !QT_MOC_HAS_STRINGDATA\n");
+ fprintf(out, "} // unnamed namespace\n\n");
//
// build the data array
//
int index = MetaObjectPrivateFieldCount;
- fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
+ fprintf(out, "Q_CONSTINIT static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
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;
@@ -369,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;
@@ -388,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()));
//
@@ -396,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
@@ -454,30 +405,20 @@ void Generator::generateCode()
fprintf(out, "\n 0 // eod\n};\n\n");
//
-// Generate internal qt_static_metacall() function
-//
- const bool hasStaticMetaCall =
- (cdef->hasQObject || !cdef->methodList.isEmpty()
- || !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
- if (hasStaticMetaCall)
- generateStaticMetacall();
-
-//
// Build extra array
//
QList<QByteArray> extraList;
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;
@@ -488,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);
@@ -514,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))
@@ -527,28 +468,29 @@ void Generator::generateCode()
//
if (!extraList.isEmpty()) {
- fprintf(out, "static const QMetaObject::SuperData qt_meta_extradata_%s[] = {\n",
+ 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");
}
//
// Finally create and initialize the static meta object
//
- fprintf(out, "const QMetaObject %s::staticMetaObject = { {\n", cdef->qualified.constData());
+ fprintf(out, "Q_CONSTINIT const QMetaObject %s::staticMetaObject = { {\n",
+ cdef->qualified.constData());
if (isQObject)
fprintf(out, " nullptr,\n");
else if (cdef->superclassList.size() && !cdef->hasQGadget && !cdef->hasQNamespace) // for qobject, we know the super class must have a static metaobject
fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", purestSuperClass.constData());
else if (cdef->superclassList.size()) // for gadgets we need to query at compile time for it
- fprintf(out, " QtPrivate::MetaObjectForType<%s>::value(),\n", purestSuperClass.constData());
+ fprintf(out, " QtPrivate::MetaObjectForType<%s>::value,\n", purestSuperClass.constData());
else
fprintf(out, " nullptr,\n");
- fprintf(out, " qt_meta_stringdata_%s.offsetsAndSize,\n"
+ fprintf(out, " qt_meta_stringdata_%s.offsetsAndSizes,\n"
" qt_meta_data_%s,\n", qualifiedClassNameIdentifier.constData(),
qualifiedClassNameIdentifier.constData());
if (hasStaticMetaCall)
@@ -561,63 +503,75 @@ void Generator::generateCode()
else
fprintf(out, " qt_meta_extradata_%s,\n", qualifiedClassNameIdentifier.constData());
- bool needsComma = false;
+ const char *comma = "";
const bool requireCompleteness = requireCompleteTypes || cdef->requireCompleteMethodTypes;
+ auto stringForType = [requireCompleteness](const QByteArray &type, bool forceComplete) -> QByteArray {
+ const char *forceCompleteType = forceComplete ? ", std::true_type>" : ", std::false_type>";
+ if (requireCompleteness)
+ return type;
+ return "QtPrivate::TypeAndForceComplete<" % type % forceCompleteType;
+ };
if (!requireCompleteness) {
- fprintf(out, "qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t\n", qualifiedClassNameIdentifier.constData());
- needsComma = true;
+ fprintf(out, " qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t", qualifiedClassNameIdentifier.constData());
+ comma = ",";
} else {
- fprintf(out, "qt_metaTypeArray<\n");
+ fprintf(out, " qt_metaTypeArray<");
}
// metatypes for properties
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
- if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data());
- else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", p.type.data());
- needsComma = true;
+ 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";
- if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", ownType);
- else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", ownType);
+ fprintf(out, "%s\n // Q_OBJECT / Q_GADGET\n %s",
+ comma, stringForType(ownType, true).constData());
+ comma = ",";
// metatypes for all exposed methods
- // no need to check for needsComma any longer, as we always need one due to the classname being present
- 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);
- if (requireCompleteness)
- fprintf(out, ", %s", fdef.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", fdef.type.name.data());
- for (const auto &argument: fdef.arguments) {
- if (requireCompleteness)
- fprintf(out, ", %s", argument.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
- }
+ // because we definitely printed something above, this section doesn't need comma control
+ 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)
+ fprintf(out, ",\n %s", stringForType(argument.type.name, false).constData());
}
- fprintf(out, "\n");
}
- for (int i = 0; i< cdef->constructorList.count(); ++i) {
- const FunctionDef& fdef = cdef->constructorList.at(i);
+
+ // but constructors have no return types, so this needs comma control again
+ for (const FunctionDef &fdef : std::as_const(cdef->constructorList)) {
+ if (fdef.arguments.isEmpty())
+ continue;
+
+ fprintf(out, "%s\n // constructor '%s'", comma, fdef.name.constData());
+ comma = "";
for (const auto &argument: fdef.arguments) {
- if (requireCompleteness)
- fprintf(out, ", %s", argument.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
+ fprintf(out, "%s\n %s", comma,
+ stringForType(argument.type.name, false).constData());
+ comma = ",";
}
}
- fprintf(out, "\n");
- fprintf(out, ">,\n");
+ fprintf(out, "\n >,\n");
fprintf(out, " nullptr\n} };\n\n");
+//
+// Generate internal qt_static_metacall() function
+//
+ if (hasStaticMetaCall)
+ generateStaticMetacall();
+
if (!cdef->hasQObject)
return;
@@ -633,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());
}
@@ -665,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
@@ -677,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");
}
}
@@ -690,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);
}
@@ -704,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);
@@ -743,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) {
@@ -780,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());
@@ -792,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)
@@ -805,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");
}
@@ -856,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);
@@ -870,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;
@@ -917,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);
@@ -926,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);
}
}
@@ -942,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))
@@ -955,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);
@@ -1022,8 +980,6 @@ void Generator::generateMetacall()
}
if (cdef->propertyList.size()) {
-
- fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
if (needElse)
fprintf(out, "else ");
fprintf(out,
@@ -1031,8 +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()));
- fprintf(out, "\n#endif // QT_NO_PROPERTIES");
+ " _id -= %d;\n }", int(cdef->propertyList.size()));
}
if (methodList.size() || cdef->propertyList.size())
fprintf(out, "\n ");
@@ -1040,10 +995,11 @@ void Generator::generateMetacall()
}
+// ### Qt 7 (6.x?): remove
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);
@@ -1057,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);
@@ -1074,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;
@@ -1142,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()");
}
@@ -1204,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;
@@ -1212,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");
}
@@ -1228,7 +1199,7 @@ void Generator::generateStaticMetacall()
fprintf(out, ") const;\n");
else
fprintf(out, ");\n");
- fprintf(out, " if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&%s::%s)) {\n",
+ fprintf(out, " if (_t _q_method = &%s::%s; *reinterpret_cast<_t *>(_a[1]) == _q_method) {\n",
cdef->classname.constData(), f.name.constData());
fprintf(out, " *result = %d;\n", methodindex);
fprintf(out, " return;\n");
@@ -1260,7 +1231,7 @@ void Generator::generateStaticMetacall()
fprintf(out, " *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< %s >(); break;\n", lastKey.constData());
}
fprintf(out, " }\n");
- fprintf(out, " }\n");
+ fprintf(out, " } ");
isUsed_a = true;
needElse = true;
}
@@ -1271,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
@@ -1282,10 +1252,8 @@ void Generator::generateStaticMetacall()
needReset |= !p.reset.isEmpty();
hasBindableProperties |= !p.bind.isEmpty();
}
- fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
-
if (needElse)
- fprintf(out, "else ");
+ fprintf(out, " else ");
fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
auto setupMemberAccess = [this]() {
@@ -1305,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;
@@ -1323,6 +1291,9 @@ void Generator::generateStaticMetacall()
else if (cdef->enumDeclarations.value(p.type, false))
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
propindex, prefix.constData(), p.read.constData());
+ else if (p.read == "default")
+ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s().value(); break;\n",
+ propindex, p.type.constData(), prefix.constData(), p.bind.constData());
else if (!p.read.isEmpty())
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
propindex, p.type.constData(), prefix.constData(), p.read.constData());
@@ -1343,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;
@@ -1356,6 +1327,12 @@ void Generator::generateStaticMetacall()
if (cdef->enumDeclarations.value(p.type, false)) {
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
propindex, prefix.constData(), p.write.constData());
+ } else if (p.write == "default") {
+ fprintf(out, " case %d: {\n", propindex);
+ fprintf(out, " %s%s().setValue(*reinterpret_cast< %s*>(_v));\n",
+ prefix.constData(), p.bind.constData(), p.type.constData());
+ fprintf(out, " break;\n");
+ fprintf(out, " }\n");
} else if (!p.write.isEmpty()) {
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
propindex, prefix.constData(), p.write.constData(), p.type.constData());
@@ -1390,15 +1367,15 @@ 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.endsWith(')'))
+ if (p.reset.isEmpty())
continue;
QByteArray prefix = "_t->";
if (p.inPrivateClass.size()) {
prefix += p.inPrivateClass + "->";
}
- fprintf(out, " case %d: %s%s; break;\n",
+ fprintf(out, " case %d: %s%s(); break;\n",
propindex, prefix.constData(), p.reset.constData());
}
fprintf(out, " default: break;\n");
@@ -1411,17 +1388,23 @@ 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;
- fprintf(out, " case %d: *static_cast<QUntypedBindable *>(_a[0]) = _t->%s(); break;\n", propindex, p.bind.constData());
+ QByteArray prefix = "_t->";
+ if (p.inPrivateClass.size()) {
+ prefix += p.inPrivateClass + "->";
+ }
+ fprintf(out,
+ " case %d: *static_cast<QUntypedBindable *>(_a[0]) = %s%s(); "
+ "break;\n",
+ propindex, prefix.constData(), p.bind.constData());
}
fprintf(out, " default: break;\n");
fprintf(out, " }\n");
}
fprintf(out, " }");
- fprintf(out, "\n#endif // QT_NO_PROPERTIES");
needElse = true;
}
@@ -1438,10 +1421,10 @@ void Generator::generateStaticMetacall()
if (!isUsed_a)
fprintf(out, " (void)_a;\n");
- fprintf(out, "}\n\n");
+ fprintf(out, "}\n");
}
-void Generator::generateSignal(FunctionDef *def,int index)
+void Generator::generateSignal(const FunctionDef *def, int index)
{
if (def->wasCloned || def->isAbstract)
return;
@@ -1465,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);
@@ -1498,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);
@@ -1557,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()
@@ -1566,62 +1550,76 @@ void Generator::generatePluginMetaData()
if (cdef->pluginData.iid.isEmpty())
return;
- fprintf(out, "\nQT_PLUGIN_METADATA_SECTION\n"
- "static constexpr unsigned char qt_pluginMetaData_%s[] = {\n"
- " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',\n"
- " // metadata version, Qt version, architectural requirements\n"
- " 0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),",
- cdef->classname.constData());
-
+ auto outputCborData = [this]() {
+ CborDevice dev(out);
+ CborEncoder enc;
+ cbor_encoder_init_writer(&enc, CborDevice::callback, &dev);
- CborDevice dev(out);
- CborEncoder enc;
- cbor_encoder_init_writer(&enc, CborDevice::callback, &dev);
+ CborEncoder map;
+ cbor_encoder_create_map(&enc, &map, CborIndefiniteLength);
- CborEncoder map;
- cbor_encoder_create_map(&enc, &map, CborIndefiniteLength);
-
- dev.nextItem("\"IID\"");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::IID));
- cbor_encode_text_string(&map, cdef->pluginData.iid.constData(), cdef->pluginData.iid.size());
+ dev.nextItem("\"IID\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::IID));
+ cbor_encode_text_string(&map, cdef->pluginData.iid.constData(), cdef->pluginData.iid.size());
- dev.nextItem("\"className\"");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::ClassName));
- cbor_encode_text_string(&map, cdef->classname.constData(), cdef->classname.size());
+ dev.nextItem("\"className\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::ClassName));
+ cbor_encode_text_string(&map, cdef->classname.constData(), cdef->classname.size());
- QJsonObject o = cdef->pluginData.metaData.object();
- if (!o.isEmpty()) {
- dev.nextItem("\"MetaData\"");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::MetaData));
- jsonObjectToCbor(&map, o);
- }
+ QJsonObject o = cdef->pluginData.metaData.object();
+ if (!o.isEmpty()) {
+ dev.nextItem("\"MetaData\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::MetaData));
+ jsonObjectToCbor(&map, o);
+ }
- if (!cdef->pluginData.uri.isEmpty()) {
- dev.nextItem("\"URI\"");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::URI));
- cbor_encode_text_string(&map, cdef->pluginData.uri.constData(), cdef->pluginData.uri.size());
- }
+ if (!cdef->pluginData.uri.isEmpty()) {
+ dev.nextItem("\"URI\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::URI));
+ cbor_encode_text_string(&map, cdef->pluginData.uri.constData(), cdef->pluginData.uri.size());
+ }
- // Add -M args from the command line:
- for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) {
- const QJsonArray &a = it.value();
- QByteArray key = it.key().toUtf8();
- dev.nextItem(QByteArray("command-line \"" + key + "\"").constData());
- cbor_encode_text_string(&map, key.constData(), key.size());
- jsonArrayToCbor(&map, a);
- }
+ // Add -M args from the command line:
+ for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) {
+ const QJsonArray &a = it.value();
+ QByteArray key = it.key().toUtf8();
+ dev.nextItem(QByteArray("command-line \"" + key + "\"").constData());
+ cbor_encode_text_string(&map, key.constData(), key.size());
+ jsonArrayToCbor(&map, a);
+ }
- // Close the CBOR map manually
- dev.nextItem();
- cbor_encoder_close_container(&enc, &map);
- fputs("\n};\n", out);
+ // Close the CBOR map manually
+ dev.nextItem();
+ cbor_encoder_close_container(&enc, &map);
+ };
// '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());
- fprintf(out, "QT_MOC_EXPORT_PLUGIN(%s, %s)\n\n",
+
+ fputs("\n#ifdef QT_MOC_EXPORT_PLUGIN_V2", out);
+
+ // Qt 6.3+ output
+ fprintf(out, "\nstatic constexpr unsigned char qt_pluginMetaDataV2_%s[] = {",
+ cdef->classname.constData());
+ outputCborData();
+ fprintf(out, "\n};\nQT_MOC_EXPORT_PLUGIN_V2(%s, %s, qt_pluginMetaDataV2_%s)\n",
+ cdef->qualified.constData(), cdef->classname.constData(), cdef->classname.constData());
+
+ // compatibility with Qt 6.0-6.2
+ fprintf(out, "#else\nQT_PLUGIN_METADATA_SECTION\n"
+ "Q_CONSTINIT static constexpr unsigned char qt_pluginMetaData_%s[] = {\n"
+ " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',\n"
+ " // metadata version, Qt version, architectural requirements\n"
+ " 0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),",
+ cdef->classname.constData());
+ outputCborData();
+ fprintf(out, "\n};\nQT_MOC_EXPORT_PLUGIN(%s, %s)\n"
+ "#endif // QT_MOC_EXPORT_PLUGIN_V2\n",
cdef->qualified.constData(), cdef->classname.constData());
+
+ fputs("\n", out);
}
QT_WARNING_DISABLE_GCC("-Wunused-function")
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 35128cb543..2d4d69ca05 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef GENERATOR_H
#define GENERATOR_H
@@ -35,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();
@@ -62,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 cc7d747f5b..6a1f58490f 100644
--- a/src/tools/moc/keywords.cpp
+++ b/src/tools/moc/keywords.cpp
@@ -1,41 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// auto generated
// DO NOT EDIT.
static const short keyword_trans[][128] = {
- {0,0,0,0,0,0,0,0,0,579,576,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,
- 579,252,577,580,8,38,239,578,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,582,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,
@@ -116,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,497,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,
@@ -155,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,521,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,
@@ -177,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,
- 585,585,585,585,585,585,585,585,585,585,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,
@@ -336,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,584,0,0,0,0,583,
+ 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,
@@ -372,29 +347,29 @@ 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,494,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,475,424,408,416,380,0,484,0,0,0,565,364,358,
- 386,0,557,472,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,394,0,0,0,
- 0,0,387,0,0,0,0,0,0,0,0,0,0,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},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,511,0,0,0,0,0,388,
+ 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},
@@ -402,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,412,0,0,0,0,0,0,0,0,0,0,0,413,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,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,420,0,0,0,0,0,0,0,0,0,0,0,421,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,454,432,0,0,437,0,0,0,446,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,540,0,473,0,0,0,501,0,0,507,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,486,0,533,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,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,
- 549,0,0,517,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,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}
};
@@ -841,85 +832,85 @@ static const struct
{CHARACTER, 0, 71, 383, CHARACTER},
{CHARACTER, 0, 69, 384, CHARACTER},
{CHARACTER, 0, 84, 385, CHARACTER},
- {Q_GADGET_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 44, 0, 0, CHARACTER},
- {CHARACTER, 45, 0, 0, CHARACTER},
+ {Q_GADGET_TOKEN, 0, 95, 386, CHARACTER},
+ {CHARACTER, 0, 69, 387, CHARACTER},
+ {CHARACTER, 0, 88, 388, CHARACTER},
{CHARACTER, 0, 80, 389, CHARACTER},
- {CHARACTER, 0, 69, 390, CHARACTER},
+ {CHARACTER, 0, 79, 390, CHARACTER},
{CHARACTER, 0, 82, 391, CHARACTER},
{CHARACTER, 0, 84, 392, CHARACTER},
- {CHARACTER, 0, 89, 393, CHARACTER},
+ {Q_GADGET_EXPORT_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 44, 0, 0, CHARACTER},
+ {CHARACTER, 45, 0, 0, CHARACTER},
+ {CHARACTER, 0, 80, 396, CHARACTER},
+ {CHARACTER, 0, 69, 397, CHARACTER},
+ {CHARACTER, 0, 82, 398, CHARACTER},
+ {CHARACTER, 0, 84, 399, CHARACTER},
+ {CHARACTER, 0, 89, 400, CHARACTER},
{Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 85, 395, CHARACTER},
- {CHARACTER, 0, 71, 396, CHARACTER},
- {CHARACTER, 0, 73, 397, CHARACTER},
- {CHARACTER, 0, 78, 398, CHARACTER},
- {CHARACTER, 0, 95, 399, CHARACTER},
- {CHARACTER, 0, 77, 400, CHARACTER},
- {CHARACTER, 0, 69, 401, CHARACTER},
- {CHARACTER, 0, 84, 402, CHARACTER},
- {CHARACTER, 0, 65, 403, CHARACTER},
- {CHARACTER, 0, 68, 404, CHARACTER},
- {CHARACTER, 0, 65, 405, CHARACTER},
- {CHARACTER, 0, 84, 406, CHARACTER},
- {CHARACTER, 0, 65, 407, CHARACTER},
- {Q_PLUGIN_METADATA_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 409, 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, 77, 411, CHARACTER},
- {Q_ENUM_TOKEN, 46, 0, 0, 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, 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, 414, CHARACTER},
- {CHARACTER, 0, 83, 415, CHARACTER},
+ {CHARACTER, 0, 78, 441, CHARACTER},
+ {CHARACTER, 0, 83, 442, CHARACTER},
{Q_ENUM_NS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 417, CHARACTER},
- {CHARACTER, 0, 65, 418, CHARACTER},
- {CHARACTER, 0, 71, 419, 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, 422, CHARACTER},
- {CHARACTER, 0, 83, 423, CHARACTER},
+ {CHARACTER, 0, 78, 449, CHARACTER},
+ {CHARACTER, 0, 83, 450, CHARACTER},
{Q_FLAG_NS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 425, CHARACTER},
- {CHARACTER, 0, 67, 426, CHARACTER},
- {CHARACTER, 0, 76, 427, CHARACTER},
- {CHARACTER, 0, 65, 428, CHARACTER},
- {CHARACTER, 0, 82, 429, CHARACTER},
- {CHARACTER, 0, 69, 430, CHARACTER},
- {CHARACTER, 0, 95, 431, CHARACTER},
- {CHARACTER, 48, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 433, CHARACTER},
- {CHARACTER, 0, 65, 434, CHARACTER},
- {CHARACTER, 0, 71, 435, CHARACTER},
- {CHARACTER, 0, 83, 436, CHARACTER},
- {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 438, CHARACTER},
- {CHARACTER, 0, 84, 439, CHARACTER},
- {CHARACTER, 0, 69, 440, CHARACTER},
- {CHARACTER, 0, 82, 441, CHARACTER},
- {CHARACTER, 0, 70, 442, CHARACTER},
- {CHARACTER, 0, 65, 443, CHARACTER},
- {CHARACTER, 0, 67, 444, CHARACTER},
- {CHARACTER, 0, 69, 445, CHARACTER},
- {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 447, CHARACTER},
- {CHARACTER, 0, 84, 448, CHARACTER},
- {CHARACTER, 0, 65, 449, CHARACTER},
- {CHARACTER, 0, 84, 450, CHARACTER},
- {CHARACTER, 0, 89, 451, CHARACTER},
- {CHARACTER, 0, 80, 452, CHARACTER},
- {CHARACTER, 0, 69, 453, CHARACTER},
- {Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 88, 455, CHARACTER},
- {CHARACTER, 0, 84, 456, CHARACTER},
+ {CHARACTER, 0, 69, 452, 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, 78, 458, CHARACTER},
- {CHARACTER, 0, 83, 459, CHARACTER},
- {CHARACTER, 0, 73, 460, CHARACTER},
- {CHARACTER, 0, 79, 461, CHARACTER},
- {CHARACTER, 0, 78, 462, CHARACTER},
- {CHARACTER, 0, 95, 463, CHARACTER},
- {CHARACTER, 0, 73, 464, 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, 84, 466, CHARACTER},
{CHARACTER, 0, 69, 467, CHARACTER},
@@ -927,116 +918,155 @@ static const struct
{CHARACTER, 0, 70, 469, CHARACTER},
{CHARACTER, 0, 65, 470, CHARACTER},
{CHARACTER, 0, 67, 471, CHARACTER},
- {CHARACTER, 0, 69, 445, CHARACTER},
- {CHARACTER, 49, 0, 0, CHARACTER},
- {CHARACTER, 0, 84, 474, CHARACTER},
- {CHARACTER, 0, 83, 420, CHARACTER},
- {CHARACTER, 0, 76, 476, CHARACTER},
- {CHARACTER, 0, 65, 477, CHARACTER},
- {CHARACTER, 0, 83, 478, CHARACTER},
- {CHARACTER, 0, 83, 479, CHARACTER},
- {CHARACTER, 0, 73, 480, CHARACTER},
- {CHARACTER, 0, 78, 481, CHARACTER},
- {CHARACTER, 0, 70, 482, CHARACTER},
- {CHARACTER, 0, 79, 483, CHARACTER},
- {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 69, 472, CHARACTER},
+ {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 69, 474, 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, 50, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 487, CHARACTER},
- {CHARACTER, 0, 82, 488, CHARACTER},
- {CHARACTER, 0, 70, 489, CHARACTER},
- {CHARACTER, 0, 65, 490, CHARACTER},
- {CHARACTER, 0, 67, 491, CHARACTER},
- {CHARACTER, 0, 69, 492, CHARACTER},
- {CHARACTER, 0, 83, 493, CHARACTER},
+ {CHARACTER, 0, 83, 486, CHARACTER},
+ {CHARACTER, 0, 73, 487, 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, 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, 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, 495, CHARACTER},
- {CHARACTER, 0, 115, 496, CHARACTER},
+ {CHARACTER, 0, 108, 522, CHARACTER},
+ {CHARACTER, 0, 115, 523, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 111, 498, CHARACTER},
- {CHARACTER, 0, 116, 499, CHARACTER},
- {CHARACTER, 0, 115, 500, CHARACTER},
+ {CHARACTER, 0, 111, 525, CHARACTER},
+ {CHARACTER, 0, 116, 526, CHARACTER},
+ {CHARACTER, 0, 115, 527, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 71, 502, CHARACTER},
- {CHARACTER, 0, 78, 503, CHARACTER},
- {CHARACTER, 0, 65, 504, CHARACTER},
- {CHARACTER, 0, 76, 505, CHARACTER},
- {Q_SIGNAL_TOKEN, 0, 83, 506, 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, 508, CHARACTER},
- {CHARACTER, 0, 84, 509, CHARACTER},
- {Q_SLOT_TOKEN, 0, 83, 510, 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, 512, CHARACTER},
- {CHARACTER, 0, 65, 513, CHARACTER},
- {CHARACTER, 0, 84, 514, CHARACTER},
- {CHARACTER, 0, 69, 515, CHARACTER},
- {CHARACTER, 0, 95, 516, CHARACTER},
- {CHARACTER, 51, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 518, CHARACTER},
- {CHARACTER, 0, 79, 519, CHARACTER},
- {CHARACTER, 0, 84, 520, 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, 522, CHARACTER},
- {CHARACTER, 0, 77, 523, CHARACTER},
- {CHARACTER, 0, 79, 524, CHARACTER},
- {CHARACTER, 0, 67, 525, CHARACTER},
- {CHARACTER, 0, 95, 526, CHARACTER},
- {CHARACTER, 0, 67, 527, CHARACTER},
- {CHARACTER, 0, 79, 528, CHARACTER},
- {CHARACTER, 0, 77, 529, CHARACTER},
- {CHARACTER, 0, 80, 530, CHARACTER},
- {CHARACTER, 0, 65, 531, CHARACTER},
- {CHARACTER, 0, 84, 532, 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, 534, CHARACTER},
- {CHARACTER, 0, 75, 535, CHARACTER},
- {CHARACTER, 0, 65, 536, CHARACTER},
- {CHARACTER, 0, 66, 537, CHARACTER},
- {CHARACTER, 0, 76, 538, CHARACTER},
- {CHARACTER, 0, 69, 539, 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, 541, CHARACTER},
- {CHARACTER, 0, 73, 542, CHARACTER},
- {CHARACTER, 0, 80, 543, CHARACTER},
- {CHARACTER, 0, 84, 544, CHARACTER},
- {CHARACTER, 0, 65, 545, CHARACTER},
- {CHARACTER, 0, 66, 546, CHARACTER},
- {CHARACTER, 0, 76, 547, CHARACTER},
- {CHARACTER, 0, 69, 548, 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, 550, CHARACTER},
- {CHARACTER, 0, 79, 551, CHARACTER},
- {CHARACTER, 0, 80, 552, CHARACTER},
- {CHARACTER, 0, 69, 553, CHARACTER},
- {CHARACTER, 0, 82, 554, CHARACTER},
- {CHARACTER, 0, 84, 555, CHARACTER},
- {CHARACTER, 0, 89, 556, 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, 558, CHARACTER},
- {CHARACTER, 0, 86, 559, CHARACTER},
- {CHARACTER, 0, 73, 560, CHARACTER},
- {CHARACTER, 0, 83, 561, CHARACTER},
- {CHARACTER, 0, 73, 562, CHARACTER},
- {CHARACTER, 0, 79, 563, CHARACTER},
- {CHARACTER, 0, 78, 564, 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, 566, CHARACTER},
- {CHARACTER, 0, 67, 567, CHARACTER},
- {CHARACTER, 0, 95, 568, CHARACTER},
- {CHARACTER, 0, 73, 569, CHARACTER},
- {CHARACTER, 0, 78, 570, CHARACTER},
- {CHARACTER, 0, 67, 571, CHARACTER},
- {CHARACTER, 0, 76, 572, CHARACTER},
- {CHARACTER, 0, 85, 573, CHARACTER},
- {CHARACTER, 0, 68, 574, CHARACTER},
- {CHARACTER, 0, 69, 575, 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, 581, 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 3e98fbf2b8..bb51352519 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <depfile_shared.h>
#include "preprocessor.h"
@@ -48,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*
This function looks at two file names and returns the name of the
infile with a path relative to outfile.
@@ -153,7 +130,7 @@ static QStringList argumentsFromCommandLineAndFile(const QStringList &arguments,
allArguments.reserve(arguments.size());
for (const QString &argument : arguments) {
// "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
- if (argument.startsWith(QLatin1Char('@'))) {
+ if (argument.startsWith(u'@')) {
QString optionsFile = argument;
optionsFile.remove(0, 1);
if (optionsFile.isEmpty()) {
@@ -306,6 +283,10 @@ int runMoc(int argc, char **argv)
jsonOption.setDescription(QStringLiteral("In addition to generating C++ code, create a machine-readable JSON file in a file that matches the output file and an extra .json extension."));
parser.addOption(jsonOption);
+ QCommandLineOption debugIncludesOption(QStringLiteral("debug-includes"));
+ debugIncludesOption.setDescription(QStringLiteral("Display debug messages of each considered include path."));
+ parser.addOption(debugIncludesOption);
+
QCommandLineOption collectOption(QStringLiteral("collect-json"));
collectOption.setDescription(QStringLiteral("Instead of processing C++ code, collect previously generated JSON output into a single file."));
parser.addOption(collectOption);
@@ -349,8 +330,8 @@ int runMoc(int argc, char **argv)
if (parser.isSet(collectOption))
return collectJson(files, output, hasOptionFiles);
- if (files.count() > 1) {
- error(qPrintable(QLatin1String("Too many input files specified: '") + files.join(QLatin1String("' '")) + QLatin1Char('\'')));
+ if (files.size() > 1) {
+ error(qPrintable("Too many input files specified: '"_L1 + files.join("' '"_L1) + u'\''));
parser.showHelp(1);
} else if (!files.isEmpty()) {
filename = files.first();
@@ -358,6 +339,7 @@ int runMoc(int argc, char **argv)
const bool ignoreConflictingOptions = parser.isSet(ignoreConflictsOption);
pp.preprocessOnly = parser.isSet(preprocessOption);
+ pp.setDebugIncludes(parser.isSet(debugIncludesOption));
if (parser.isSet(noIncludeOption)) {
moc.noInclude = true;
autoInclude = false;
@@ -385,7 +367,7 @@ int runMoc(int argc, char **argv)
for (const QString &path : includePaths)
pp.includes += Preprocessor::IncludePath(QFile::encodeName(path));
QString compilerFlavor = parser.value(compilerFlavorOption);
- if (compilerFlavor.isEmpty() || compilerFlavor == QLatin1String("unix")) {
+ if (compilerFlavor.isEmpty() || compilerFlavor == "unix"_L1) {
// traditional Unix compilers use both CPATH and CPLUS_INCLUDE_PATH
// $CPATH feeds to #include <...> and #include "...", whereas
// CPLUS_INCLUDE_PATH is equivalent to GCC's -isystem, so we parse later
@@ -395,14 +377,14 @@ int runMoc(int argc, char **argv)
const auto cplus_include_path = qgetenv("CPLUS_INCLUDE_PATH").split(QDir::listSeparator().toLatin1());
for (const QByteArray &p : cplus_include_path)
pp.includes += Preprocessor::IncludePath(p);
- } else if (compilerFlavor == QLatin1String("msvc")) {
+ } else if (compilerFlavor == "msvc"_L1) {
// MSVC uses one environment variable: INCLUDE
const auto include = qgetenv("INCLUDE").split(QDir::listSeparator().toLatin1());
for (const QByteArray &p : include)
pp.includes += Preprocessor::IncludePath(p);
} else {
- error(qPrintable(QLatin1String("Unknown compiler flavor '") + compilerFlavor +
- QLatin1String("'; valid values are: msvc, unix.")));
+ error(qPrintable("Unknown compiler flavor '"_L1 + compilerFlavor +
+ "'; valid values are: msvc, unix."_L1));
parser.showHelp(1);
}
@@ -417,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);
@@ -441,16 +423,16 @@ int runMoc(int argc, char **argv)
pp.macros.remove(macro);
}
const QStringList noNotesCompatValues = parser.values(noNotesWarningsCompatOption);
- if (parser.isSet(noNotesOption) || noNotesCompatValues.contains(QLatin1String("n")))
+ if (parser.isSet(noNotesOption) || noNotesCompatValues.contains("n"_L1))
moc.displayNotes = false;
- if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains(QLatin1String("w")))
+ if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains("w"_L1))
moc.displayWarnings = moc.displayNotes = false;
if (autoInclude) {
- int spos = filename.lastIndexOf(QDir::separator());
- int ppos = filename.lastIndexOf(QLatin1Char('.'));
+ qsizetype spos = filename.lastIndexOf(QDir::separator());
+ qsizetype ppos = filename.lastIndexOf(u'.');
// spos >= -1 && ppos > spos => ppos >= 0
- moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != QLatin1Char('h'));
+ moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != u'h');
}
if (defaultInclude) {
if (moc.includePath.isEmpty()) {
@@ -467,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();
@@ -479,13 +464,13 @@ int runMoc(int argc, char **argv)
const auto metadata = parser.values(metadataOption);
for (const QString &md : metadata) {
- int split = md.indexOf(QLatin1Char('='));
+ qsizetype split = md.indexOf(u'=');
QString key = md.left(split);
QString value = md.mid(split + 1);
if (split == -1 || key.isEmpty() || value.isEmpty()) {
error("missing key or value for option '-M'");
- } else if (key.indexOf(QLatin1Char('.')) != -1) {
+ } else if (key.indexOf(u'.') != -1) {
// Don't allow keys with '.' for now, since we might need this
// format later for more advanced meta data API
error("A key cannot contain the letter '.' for option '-M'");
@@ -499,6 +484,17 @@ int runMoc(int argc, char **argv)
moc.currentFilenames.push(filename.toLocal8Bit());
moc.includes = pp.includes;
+ if (Q_UNLIKELY(parser.isSet(debugIncludesOption))) {
+ fprintf(stderr, "debug-includes: include search list:\n");
+
+ for (auto &includePath : pp.includes) {
+ fprintf(stderr, "debug-includes: '%s' framework: %d \n",
+ includePath.path.constData(),
+ includePath.isFrameworkPath);
+ }
+ fprintf(stderr, "debug-includes: end of search list.\n");
+ }
+
// 1. preprocess
const auto includeFiles = parser.values(includeOption);
QStringList validIncludesFiles;
@@ -543,12 +539,15 @@ 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;
}
if (parser.isSet(jsonOption)) {
- const QString jsonOutputFileName = output + QLatin1String(".json");
+ const QString jsonOutputFileName = output + ".json"_L1;
FILE *f;
#if defined(_MSC_VER)
if (_wfopen_s(&f, reinterpret_cast<const wchar_t *>(jsonOutputFileName.utf16()), L"w") != 0)
@@ -556,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
@@ -589,7 +591,7 @@ int runMoc(int argc, char **argv)
if (parser.isSet(depFilePathOption)) {
depOutputFileName = parser.value(depFilePathOption);
} else if (outputToFile) {
- depOutputFileName = output + QLatin1String(".d");
+ depOutputFileName = output + ".d"_L1;
} else {
fprintf(stderr, "moc: Writing to stdout, but no depfile path specified.\n");
}
@@ -603,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 d57e43b59d..3cbe331f14 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "moc.h"
#include "generator.h"
@@ -43,12 +18,23 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// only moc needs this function
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
@@ -63,6 +49,9 @@ bool Moc::parseClassHead(ClassDef *def)
return false;
} while (token);
+ // support attributes like "class [[deprecated]]] name"
+ skipCxxAttributes();
+
if (!test(IDENTIFIER)) // typedef struct { ... }
return false;
QByteArray name = lexem();
@@ -107,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);
@@ -263,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;
@@ -285,10 +274,9 @@ bool Moc::parseEnum(EnumDef *def)
return IncludeState::NoInclude;
};
do {
+ handleInclude();
if (lookup() == RBRACE) // accept trailing comma
break;
- if ( handleInclude() == IncludeState::IncludeEnd)
- continue;
next(IDENTIFIER);
def->values += lexem();
handleInclude();
@@ -321,7 +309,7 @@ void Moc::parseFunctionArguments(FunctionDef *def)
arg.rightType += lexem();
}
arg.normalizedType = normalizeType(QByteArray(arg.type.name + ' ' + arg.rightType));
- arg.typeNameForCast = normalizeType(QByteArray(noRef(arg.type.name) + "(*)" + arg.rightType));
+ arg.typeNameForCast = QByteArray("std::add_pointer_t<"+arg.normalizedType+">");
if (test(EQ))
arg.isDefault = true;
def->arguments += arg;
@@ -339,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)
@@ -389,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);
@@ -430,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();
@@ -442,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);
@@ -530,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();
@@ -552,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
@@ -602,6 +601,63 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
return true;
}
+inline void handleDefaultArguments(QList<FunctionDef> *functionList, FunctionDef &function)
+{
+ // support a function with a default argument by pretending there is an
+ // overload without the argument (the original function is the overload with
+ // all arguments present)
+ while (function.arguments.size() > 0 && function.arguments.constLast().isDefault) {
+ function.wasCloned = true;
+ function.arguments.removeLast();
+ *functionList += function;
+ }
+}
+
+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()
{
@@ -611,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();
@@ -637,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;
@@ -656,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);
@@ -771,6 +832,12 @@ void Moc::parse()
case Q_OBJECT_TOKEN:
def.hasQObject = true;
break;
+ case Q_GADGET_EXPORT_TOKEN:
+ next(LPAREN);
+ while (test(IDENTIFIER))
+ {}
+ next(RPAREN);
+ Q_FALLTHROUGH();
case Q_GADGET_TOKEN:
def.hasQGadget = true;
break;
@@ -781,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);
@@ -796,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:
@@ -848,13 +912,22 @@ void Moc::parse()
if (def.classname != "Qt" && def.classname != "QObject" && def.superclassList.isEmpty())
error("Class contains Q_OBJECT macro but does not inherit from QObject");
break;
+ case Q_GADGET_EXPORT_TOKEN:
+ next(LPAREN);
+ while (test(IDENTIFIER))
+ {}
+ next(RPAREN);
+ Q_FALLTHROUGH();
case Q_GADGET_TOKEN:
def.hasQGadget = true;
if (templateClass)
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);
@@ -889,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;
@@ -902,16 +978,12 @@ 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) {
def.constructorList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.constructorList += funcDef;
- }
+ handleDefaultArguments(&def.constructorList, funcDef);
}
} else if (funcDef.isDestructor) {
// don't care about destructors
@@ -920,29 +992,17 @@ void Moc::parse()
def.publicList += funcDef;
if (funcDef.isSlot) {
def.slotList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.slotList += funcDef;
- }
+ handleDefaultArguments(&def.slotList, funcDef);
if (funcDef.revision > 0)
++def.revisionedMethods;
} else if (funcDef.isSignal) {
def.signalList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.signalList += funcDef;
- }
+ handleDefaultArguments(&def.signalList, funcDef);
if (funcDef.revision > 0)
++def.revisionedMethods;
} else if (funcDef.isInvokable) {
def.methodList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.methodList += funcDef;
- }
+ handleDefaultArguments(&def.methodList, funcDef);
if (funcDef.revision > 0)
++def.revisionedMethods;
}
@@ -967,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;
@@ -989,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);
@@ -1068,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 + '\"';
@@ -1097,7 +1165,6 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
if (classList.size() && classList.constFirst().classname == "Qt")
fprintf(out, "#include <QtCore/qobject.h>\n");
- fprintf(out, "#include <QtCore/qbytearray.h>\n"); // For QByteArrayData
fprintf(out, "#include <QtCore/qmetatype.h>\n"); // For QMetaType::Type
if (mustIncludeQPluginH)
fprintf(out, "#include <QtCore/qplugin.h>\n");
@@ -1106,6 +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#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());
@@ -1116,32 +1187,44 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
" much.)\"\n", QT_VERSION_STR);
fprintf(out, "#endif\n\n");
- fprintf(out, "QT_BEGIN_MOC_NAMESPACE\n");
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+ fprintf(out, "#ifndef Q_CONSTINIT\n"
+ "#define Q_CONSTINIT\n"
+ "#endif\n\n");
+#endif
+
fprintf(out, "QT_WARNING_PUSH\n");
fprintf(out, "QT_WARNING_DISABLE_DEPRECATED\n");
+ 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);
fprintf(out, "QT_WARNING_POP\n");
- fprintf(out, "QT_END_MOC_NAMESPACE\n");
if (jsonOutput) {
QJsonObject mocData;
- mocData[QLatin1String("outputRevision")] = mocOutputRevision;
- mocData[QLatin1String("inputFile")] = QLatin1String(fn.constData());
+ mocData["outputRevision"_L1] = mocOutputRevision;
+ mocData["inputFile"_L1] = QLatin1StringView(fn.constData());
QJsonArray classesJsonFormatted;
- for (const ClassDef &cdef: qAsConst(classList))
+ for (const ClassDef &cdef: std::as_const(classList))
classesJsonFormatted.append(cdef.toJson());
if (!classesJsonFormatted.isEmpty())
- mocData[QLatin1String("classes")] = classesJsonFormatted;
+ mocData["classes"_L1] = classesJsonFormatted;
QJsonDocument jsonDoc(mocData);
fputs(jsonDoc.toJson().constData(), jsonOutput);
@@ -1186,11 +1269,7 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access)
++def->revisionedMethods;
}
def->slotList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def->slotList += funcDef;
- }
+ handleDefaultArguments(&def->slotList, funcDef);
}
}
@@ -1234,15 +1313,11 @@ void Moc::parseSignals(ClassDef *def)
++def->revisionedMethods;
}
def->signalList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def->signalList += funcDef;
- }
+ handleDefaultArguments(&def->signalList, funcDef);
}
}
-void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex)
+void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex, Moc::PropertyMode mode)
{
propDef.location = index;
propDef.relativeIndex = propertyIndex;
@@ -1272,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);
}
@@ -1290,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;
@@ -1313,11 +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(lsym);
} else {
next(IDENTIFIER);
v = lexem();
@@ -1331,21 +1413,21 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
if (l == "MEMBER")
propDef.member = v;
else
- error(2);
+ error(lsym);
break;
case 'R':
if (l == "READ")
propDef.read = v;
else if (l == "RESET")
- propDef.reset = v + v2;
+ propDef.reset = v;
else if (l == "REVISION") {
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") {
@@ -1355,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()) {
@@ -1396,13 +1478,25 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
propDef.constant = false;
warning(msg.constData());
}
+ if (propDef.read == "default" && propDef.bind.isNull()) {
+ const QByteArray msg = "Property declaration " + propDef.name
+ + " is not BINDable but default-READable. READ will be ignored.";
+ propDef.read = "";
+ warning(msg.constData());
+ }
+ if (propDef.write == "default" && propDef.bind.isNull()) {
+ const QByteArray msg = "Property declaration " + propDef.name
+ + " is not BINDable but default-WRITEable. WRITE will be ignored.";
+ propDef.write = "";
+ warning(msg.constData());
+ }
}
-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;
@@ -1423,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;
@@ -1488,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;
@@ -1496,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;
}
@@ -1594,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");
@@ -1663,11 +1759,7 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
funcDef.access = access;
parseFunction(&funcDef, true);
def->slotList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def->slotList += funcDef;
- }
+ handleDefaultArguments(&def->slotList, funcDef);
if (funcDef.revision > 0)
++def->revisionedMethods;
@@ -1675,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) {
@@ -1709,9 +1801,9 @@ bool Moc::until(Token target) {
}
//when searching commas within the default argument, we should take care of template depth (anglecount)
- // unfortunatelly, we do not have enough semantic information to know if '<' is the operator< or
+ // 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;
@@ -1775,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
@@ -1790,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 "
@@ -1805,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
@@ -1830,34 +1926,30 @@ void Moc::checkSuperClasses(ClassDef *def)
void Moc::checkProperties(ClassDef *cdef)
{
//
- // specify get function, for compatibiliy we accept functions
+ // 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
@@ -1883,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;
@@ -1894,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);
}
}
}
@@ -1909,19 +2001,19 @@ void Moc::checkProperties(ClassDef *cdef)
QJsonObject ClassDef::toJson() const
{
QJsonObject cls;
- cls[QLatin1String("className")] = QString::fromUtf8(classname.constData());
- cls[QLatin1String("qualifiedClassName")] = QString::fromUtf8(qualified.constData());
+ cls["className"_L1] = QString::fromUtf8(classname.constData());
+ 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[QLatin1String("name")] = QString::fromUtf8(info.name);
- infoJson[QLatin1String("value")] = QString::fromUtf8(info.value);
+ infoJson["name"_L1] = QString::fromUtf8(info.name);
+ infoJson["value"_L1] = QString::fromUtf8(info.value);
classInfos.append(infoJson);
}
if (classInfos.size())
- cls[QLatin1String("classInfos")] = classInfos;
+ cls["classInfos"_L1] = classInfos;
const auto appendFunctions = [&cls](const QString &type, const QList<FunctionDef> &funcs) {
QJsonArray jsonFuncs;
@@ -1933,59 +2025,59 @@ QJsonObject ClassDef::toJson() const
cls[type] = jsonFuncs;
};
- appendFunctions(QLatin1String("signals"), signalList);
- appendFunctions(QLatin1String("slots"), slotList);
- appendFunctions(QLatin1String("constructors"), constructorList);
- appendFunctions(QLatin1String("methods"), methodList);
+ appendFunctions("signals"_L1, signalList);
+ appendFunctions("slots"_L1, slotList);
+ appendFunctions("constructors"_L1, constructorList);
+ appendFunctions("methods"_L1, methodList);
QJsonArray props;
- for (const PropertyDef &propDef: qAsConst(propertyList))
+ for (const PropertyDef &propDef: std::as_const(propertyList))
props.append(propDef.toJson());
if (!props.isEmpty())
- cls[QLatin1String("properties")] = props;
+ cls["properties"_L1] = props;
if (hasQObject)
- cls[QLatin1String("object")] = true;
+ cls["object"_L1] = true;
if (hasQGadget)
- cls[QLatin1String("gadget")] = true;
+ cls["gadget"_L1] = true;
if (hasQNamespace)
- cls[QLatin1String("namespace")] = true;
+ cls["namespace"_L1] = true;
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[QLatin1String("name")] = 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);
}
if (!superClasses.isEmpty())
- cls[QLatin1String("superClasses")] = superClasses;
+ 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[QLatin1String("enums")] = enums;
+ cls["enums"_L1] = enums;
QJsonArray ifaces;
for (const QList<Interface> &ifaceList : interfaceList) {
QJsonArray jsonList;
for (const Interface &iface: ifaceList) {
QJsonObject ifaceJson;
- ifaceJson[QLatin1String("id")] = QString::fromUtf8(iface.interfaceId);
- ifaceJson[QLatin1String("className")] = QString::fromUtf8(iface.className);
+ ifaceJson["id"_L1] = QString::fromUtf8(iface.interfaceId);
+ ifaceJson["className"_L1] = QString::fromUtf8(iface.className);
jsonList.append(ifaceJson);
}
ifaces.append(jsonList);
}
if (!ifaces.isEmpty())
- cls[QLatin1String("interfaces")] = ifaces;
+ cls["interfaces"_L1] = ifaces;
return cls;
}
@@ -1993,22 +2085,25 @@ QJsonObject ClassDef::toJson() const
QJsonObject FunctionDef::toJson() const
{
QJsonObject fdef;
- fdef[QLatin1String("name")] = QString::fromUtf8(name);
+ fdef["name"_L1] = QString::fromUtf8(name);
if (!tag.isEmpty())
- fdef[QLatin1String("tag")] = QString::fromUtf8(tag);
- fdef[QLatin1String("returnType")] = QString::fromUtf8(normalizedType);
+ fdef["tag"_L1] = QString::fromUtf8(tag);
+ fdef["returnType"_L1] = QString::fromUtf8(normalizedType);
QJsonArray args;
for (const ArgumentDef &arg: arguments)
args.append(arg.toJson());
if (!args.isEmpty())
- fdef[QLatin1String("arguments")] = args;
+ fdef["arguments"_L1] = args;
accessToJson(&fdef, access);
if (revision > 0)
- fdef[QLatin1String("revision")] = revision;
+ fdef["revision"_L1] = revision;
+
+ if (wasCloned)
+ fdef["isCloned"_L1] = true;
return fdef;
}
@@ -2016,30 +2111,30 @@ QJsonObject FunctionDef::toJson() const
void FunctionDef::accessToJson(QJsonObject *obj, FunctionDef::Access acs)
{
switch (acs) {
- case Private: (*obj)[QLatin1String("access")] = QLatin1String("private"); break;
- case Public: (*obj)[QLatin1String("access")] = QLatin1String("public"); break;
- case Protected: (*obj)[QLatin1String("access")] = QLatin1String("protected"); break;
+ case Private: (*obj)["access"_L1] = "private"_L1; break;
+ case Public: (*obj)["access"_L1] = "public"_L1; break;
+ case Protected: (*obj)["access"_L1] = "protected"_L1; break;
}
}
QJsonObject ArgumentDef::toJson() const
{
QJsonObject arg;
- arg[QLatin1String("type")] = QString::fromUtf8(normalizedType);
+ arg["type"_L1] = QString::fromUtf8(normalizedType);
if (!name.isEmpty())
- arg[QLatin1String("name")] = QString::fromUtf8(name);
+ arg["name"_L1] = QString::fromUtf8(name);
return arg;
}
QJsonObject PropertyDef::toJson() const
{
QJsonObject prop;
- prop[QLatin1String("name")] = QString::fromUtf8(name);
- prop[QLatin1String("type")] = QString::fromUtf8(type);
+ prop["name"_L1] = QString::fromUtf8(name);
+ prop["type"_L1] = QString::fromUtf8(type);
const auto jsonify = [&prop](const char *str, const QByteArray &member) {
if (!member.isEmpty())
- prop[QLatin1String(str)] = QString::fromUtf8(member);
+ prop[QLatin1StringView(str)] = QString::fromUtf8(member);
};
jsonify("member", member);
@@ -2058,7 +2153,7 @@ QJsonObject PropertyDef::toJson() const
value = false;
else
value = QString::fromUtf8(boolOrString); // function name to query at run-time
- prop[QLatin1String(str)] = value;
+ prop[QLatin1StringView(str)] = value;
};
jsonifyBoolOrString("designable", designable);
@@ -2066,12 +2161,12 @@ QJsonObject PropertyDef::toJson() const
jsonifyBoolOrString("stored", stored);
jsonifyBoolOrString("user", user);
- prop[QLatin1String("constant")] = constant;
- prop[QLatin1String("final")] = final;
- prop[QLatin1String("required")] = required;
- prop[QLatin1String("index")] = relativeIndex;
+ prop["constant"_L1] = constant;
+ prop["final"_L1] = final;
+ prop["required"_L1] = required;
+ prop["index"_L1] = relativeIndex;
if (revision > 0)
- prop[QLatin1String("revision")] = revision;
+ prop["revision"_L1] = revision;
return prop;
}
@@ -2079,19 +2174,40 @@ QJsonObject PropertyDef::toJson() const
QJsonObject EnumDef::toJson(const ClassDef &cdef) const
{
QJsonObject def;
- def[QLatin1String("name")] = QString::fromUtf8(name);
+ def["name"_L1] = QString::fromUtf8(name);
if (!enumName.isEmpty())
- def[QLatin1String("alias")] = QString::fromUtf8(enumName);
- def[QLatin1String("isFlag")] = cdef.enumDeclarations.value(name);
- def[QLatin1String("isClass")] = isEnumClass;
+ 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;
QJsonArray valueArr;
for (const QByteArray &value: values)
valueArr.append(QString::fromUtf8(value));
if (!valueArr.isEmpty())
- def[QLatin1String("values")] = valueArr;
+ def["values"_L1] = valueArr;
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 1c2d6624fa..c1759fb0a3 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef MOC_H
#define MOC_H
@@ -32,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
@@ -67,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);
@@ -126,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);
}
@@ -142,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;
};
@@ -172,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
{
@@ -221,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)
{}
@@ -253,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);
@@ -262,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);
@@ -277,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);
@@ -295,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/outputrevision.h b/src/tools/moc/outputrevision.h
index e8d2d1b1b9..3bc5a872ed 100644
--- a/src/tools/moc/outputrevision.h
+++ b/src/tools/moc/outputrevision.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef OUTPUTREVISION_H
#define OUTPUTREVISION_H
diff --git a/src/tools/moc/parser.cpp b/src/tools/moc/parser.cpp
index 4b67e3a99a..1cfb8ce486 100644
--- a/src/tools/moc/parser.cpp
+++ b/src/tools/moc/parser.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "parser.h"
#include "utils.h"
@@ -33,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 f014d7e6b5..6fe982a1ce 100644
--- a/src/tools/moc/parser.h
+++ b/src/tools/moc/parser.h
@@ -1,35 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PARSER_H
#define PARSER_H
#include "symbols.h"
+#include <QtCore/qbytearrayview.h>
#include <stack>
@@ -40,7 +16,7 @@ class Parser
public:
Parser():index(0), displayWarnings(true), displayNotes(true) {}
Symbols symbols;
- int index;
+ qsizetype index;
bool displayWarnings;
bool displayNotes;
@@ -68,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);
};
@@ -87,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/ppkeywords.cpp b/src/tools/moc/ppkeywords.cpp
index b94abf8cd8..dc13f3db95 100644
--- a/src/tools/moc/ppkeywords.cpp
+++ b/src/tools/moc/ppkeywords.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// auto generated
// DO NOT EDIT.
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index c6e84c0913..11ea8d417e 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "preprocessor.h"
#include "utils.h"
@@ -33,9 +8,12 @@
#include <qfile.h>
#include <qdir.h>
#include <qfileinfo.h>
+#include <qvarlengtharray.h>
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
#include "ppkeywords.cpp"
#include "keywords.cpp"
@@ -236,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;
@@ -245,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'
@@ -339,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
@@ -414,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;
@@ -422,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'
@@ -519,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;
@@ -642,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);
@@ -673,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('"');
@@ -709,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;
@@ -951,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;
}
@@ -990,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
@@ -1004,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);
}
@@ -1015,13 +994,21 @@ static void mergeStringLiterals(Symbols *_symbols)
}
static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepaths,
- const QByteArray &include)
+ const QByteArray &include,
+ const bool debugIncludes)
{
QFileInfo fi;
- for (int j = 0; j < includepaths.size() && !fi.exists(); ++j) {
- const Parser::IncludePath &p = includepaths.at(j);
+
+ if (Q_UNLIKELY(debugIncludes)) {
+ fprintf(stderr, "debug-includes: searching for '%s'\n", include.constData());
+ }
+
+ 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/"),
@@ -1029,6 +1016,12 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
} else {
fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include));
}
+
+ if (Q_UNLIKELY(debugIncludes)) {
+ const auto candidate = fi.filePath().toLocal8Bit();
+ fprintf(stderr, "debug-includes: considering '%s'\n", candidate.constData());
+ }
+
// try again, maybe there's a file later in the include paths with the same name
// (186067)
if (fi.isDir()) {
@@ -1037,9 +1030,20 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
}
}
- if (!fi.exists() || fi.isDir())
+ if (!fi.exists() || fi.isDir()) {
+ if (Q_UNLIKELY(debugIncludes)) {
+ fprintf(stderr, "debug-includes: can't find '%s'\n", include.constData());
+ }
return QByteArray();
- return fi.canonicalFilePath().toLocal8Bit();
+ }
+
+ const auto result = fi.canonicalFilePath().toLocal8Bit();
+
+ if (Q_UNLIKELY(debugIncludes)) {
+ fprintf(stderr, "debug-includes: found '%s'\n", result.constData());
+ }
+
+ return result;
}
QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
@@ -1053,7 +1057,11 @@ QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteAr
auto it = nonlocalIncludePathResolutionCache.find(include);
if (it == nonlocalIncludePathResolutionCache.end())
- it = nonlocalIncludePathResolutionCache.insert(include, searchIncludePaths(includes, include));
+ it = nonlocalIncludePathResolutionCache.insert(include,
+ searchIncludePaths(
+ includes,
+ include,
+ debugIncludes));
return it.value();
}
@@ -1096,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);
@@ -1131,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 ||
@@ -1281,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.");
}
}
@@ -1318,4 +1326,10 @@ void Preprocessor::until(Token t)
;
}
+void Preprocessor::setDebugIncludes(bool value)
+{
+ debugIncludes = value;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index 39f56d6e92..3509e83dce 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PREPROCESSOR_H
#define PREPROCESSOR_H
@@ -45,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;
@@ -73,18 +44,22 @@ 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();
enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude, PrepareDefine, TokenizeDefine };
static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp);
+ void setDebugIncludes(bool value);
+
private:
void until(Token);
void preprocess(const QByteArray &filename, Symbols &preprocessed);
+ bool debugIncludes = false;
};
QT_END_NAMESPACE
diff --git a/src/tools/moc/symbols.h b/src/tools/moc/symbols.h
index bbb1312cdc..869f7c793f 100644
--- a/src/tools/moc/symbols.h
+++ b/src/tools/moc/symbols.h
@@ -1,111 +1,62 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef SYMBOLS_H
#define SYMBOLS_H
#include "token.h"
#include <qdebug.h>
-#include <qhash.h>
+#include <qhashfunctions.h>
#include <qlist.h>
#include <qstack.h>
#include <qstring.h>
+#include <qset.h>
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(QLatin1String(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); }
@@ -114,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);
@@ -126,7 +76,7 @@ struct SafeSymbols {
Symbols symbols;
QByteArray expandedMacro;
QSet<QByteArray> excludedSymbols;
- int index;
+ qsizetype index;
};
Q_DECLARE_TYPEINFO(SafeSymbols, Q_RELOCATABLE_TYPE);
@@ -151,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)
@@ -169,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.cpp b/src/tools/moc/token.cpp
index cf1aa102c7..bfefaff57b 100644
--- a/src/tools/moc/token.cpp
+++ b/src/tools/moc/token.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "token.h"
diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h
index c11ec6a38c..a70808370d 100644
--- a/src/tools/moc/token.h
+++ b/src/tools/moc/token.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef TOKEN_H
#define TOKEN_H
@@ -154,9 +129,11 @@ QT_BEGIN_NAMESPACE
F(RETURN) \
F(Q_OBJECT_TOKEN) \
F(Q_GADGET_TOKEN) \
+ F(Q_GADGET_EXPORT_TOKEN) \
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) \
@@ -178,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 5460d28924..6be06e5a91 100755
--- a/src/tools/moc/util/generate.sh
+++ b/src/tools/moc/util/generate.sh
@@ -1,37 +1,12 @@
#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2016 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
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 28c5eeff38..a6c85af9f1 100644
--- a/src/tools/moc/util/generate_keywords.cpp
+++ b/src/tools/moc/util/generate_keywords.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <stdio.h>
#include <string.h>
#include <qbytearray.h>
@@ -216,7 +191,9 @@ static const Keyword keywords[] = {
{ "Q_NAMESPACE", "Q_NAMESPACE_TOKEN" },
{ "Q_NAMESPACE_EXPORT", "Q_NAMESPACE_EXPORT_TOKEN" },
{ "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" },
@@ -242,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/generate_keywords.pro b/src/tools/moc/util/generate_keywords.pro
new file mode 100644
index 0000000000..e29738c18a
--- /dev/null
+++ b/src/tools/moc/util/generate_keywords.pro
@@ -0,0 +1,5 @@
+CONFIG -= moc
+CONFIG += cmdline
+QT = core
+
+SOURCES += generate_keywords.cpp
diff --git a/src/tools/moc/util/licenseheader.cpp.in b/src/tools/moc/util/licenseheader.cpp.in
new file mode 100644
index 0000000000..42958a66f5
--- /dev/null
+++ b/src/tools/moc/util/licenseheader.cpp.in
@@ -0,0 +1,3 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
diff --git a/src/tools/moc/util/licenseheader.txt b/src/tools/moc/util/licenseheader.txt
deleted file mode 100644
index b2b02f82eb..0000000000
--- a/src/tools/moc/util/licenseheader.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
diff --git a/src/tools/moc/utils.h b/src/tools/moc/utils.h
index 4cb1d90345..0b0d70f462 100644
--- a/src/tools/moc/utils.h
+++ b/src/tools/moc/utils.h
@@ -1,35 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef UTILS_H
#define UTILS_H
#include <QtCore/qglobal.h>
+#include <private/qtools_p.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -45,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)