summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tools/moc/moc.cpp23
-rw-r--r--tests/auto/tools/moc/faulty_qml_registration/CMakeLists.txt18
-rw-r--r--tests/auto/tools/moc/faulty_qml_registration/faulty_registration.cpp6
-rw-r--r--tests/auto/tools/moc/faulty_qml_registration/faulty_registration.h13
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp18
5 files changed, 78 insertions, 0 deletions
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 283a75dad20..27655dbe2aa 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -869,6 +869,7 @@ void Moc::parse()
continue;
ClassDef def;
if (parseClassHead(&def)) {
+ Symbol qmlRegistrationMacroSymbol = {};
prependNamespaces(def, namespaceList);
FunctionDef::Access access = FunctionDef::Private;
@@ -984,6 +985,17 @@ void Moc::parse()
case SEMIC:
case COLON:
break;
+ case IDENTIFIER:
+ {
+ const QByteArray lex = lexem();
+ if (lex.startsWith("QML_")) {
+ if ( lex == "QML_ELEMENT" || lex == "QML_NAMED_ELEMENT"
+ || lex == "QML_ANONYMOUS" || lex == "QML_VALUE_TYPE") {
+ qmlRegistrationMacroSymbol = symbol();
+ }
+ }
+ }
+ Q_FALLTHROUGH();
default:
FunctionDef funcDef;
funcDef.access = access;
@@ -1024,6 +1036,17 @@ void Moc::parse()
next(RBRACE);
+ /* if the header is available, moc will see a Q_CLASSINFO entry; the
+ token is only visible if the header is missing
+ To avoid false positives, we only warn when encountering the token in a QObject or gadget
+ */
+ if ((def.hasQObject || def.hasQGadget) && qmlRegistrationMacroSymbol.token != NOTOKEN) {
+ QByteArray msg("Potential QML registration macro was found, but no header containing it was included.\n"
+ "This might cause runtime errors in QML applications\n"
+ "Include <QtQmlIntegration/qqmlintegration.h> or <QtQml/qqmlregistration.h> to fix this.");
+ warning(qmlRegistrationMacroSymbol, msg.constData());
+ }
+
if (!def.hasQObject && !def.hasQGadget && def.signalList.isEmpty() && def.slotList.isEmpty()
&& def.propertyList.isEmpty() && def.enumDeclarations.isEmpty())
continue; // no meta object code required
diff --git a/tests/auto/tools/moc/faulty_qml_registration/CMakeLists.txt b/tests/auto/tools/moc/faulty_qml_registration/CMakeLists.txt
new file mode 100644
index 00000000000..c0a60687ee4
--- /dev/null
+++ b/tests/auto/tools/moc/faulty_qml_registration/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# This folder is intentionally not added in the parent directory
+# The project structure here is only there to support running it as
+# a manual test
+cmake_minimum_required(VERSION 3.16)
+
+project(test_add_resource_options)
+
+find_package(Qt6Core REQUIRED)
+
+qt_wrap_cpp(faulty_registration.h)
+
+
+qt6_add_executable(faulty_registration faulty_registration.h faulty_registration.cpp)
+target_link_libraries(faulty_registration PRIVATE Qt::Core)
+
diff --git a/tests/auto/tools/moc/faulty_qml_registration/faulty_registration.cpp b/tests/auto/tools/moc/faulty_qml_registration/faulty_registration.cpp
new file mode 100644
index 00000000000..d42f20871dd
--- /dev/null
+++ b/tests/auto/tools/moc/faulty_qml_registration/faulty_registration.cpp
@@ -0,0 +1,6 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "faulty_registration.h"
+
+int main() {}
diff --git a/tests/auto/tools/moc/faulty_qml_registration/faulty_registration.h b/tests/auto/tools/moc/faulty_qml_registration/faulty_registration.h
new file mode 100644
index 00000000000..abefcd7d4f5
--- /dev/null
+++ b/tests/auto/tools/moc/faulty_qml_registration/faulty_registration.h
@@ -0,0 +1,13 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+#ifndef FAULTY_REGISTRATION
+#define FAULTY_REGISTRATION
+
+#include <QObject>
+
+struct Faulty : QObject {
+ Q_OBJECT
+ QML_ELEMENT
+};
+
+#endif
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 6ba72d2fbe0..09f7a9c75de 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -786,6 +786,7 @@ private slots:
void dontStripNamespaces();
void oldStyleCasts();
+ void faultyQmlRegistration();
void warnOnExtraSignalSlotQualifiaction();
void uLongLong();
void inputFileNameWithDotsButNoExtension();
@@ -1020,6 +1021,23 @@ void tst_Moc::oldStyleCasts()
#endif
}
+void tst_Moc::faultyQmlRegistration()
+{
+#ifdef MOC_CROSS_COMPILED
+ QSKIP("Not tested when cross-compiled");
+#endif
+#if QT_CONFIG(process)
+ QProcess proc;
+ proc.start(m_moc, QStringList(m_sourceDirectory + QStringLiteral("/faulty_qml_registration/faulty_registration.h")));
+ QVERIFY(proc.waitForFinished());
+ QCOMPARE(proc.exitCode(), 0);
+ QByteArray errorMsg = proc.readAllStandardError();
+ QVERIFY2(errorMsg.contains("QML registration macro"), errorMsg.constData());
+#else
+ QSKIP("Requires QProcess");
+#endif
+}
+
void tst_Moc::warnOnExtraSignalSlotQualifiaction()
{
#ifdef MOC_CROSS_COMPILED