aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Shalayel <sami.shalayel@qt.io>2022-10-12 15:56:00 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-12-07 13:50:01 +0100
commitee9e3a10d967874eddc5400b2b7aa36950140b9b (patch)
tree0765f56ac0ea367140b241235eb571b295d152d1
parenta354d91b885b16e6246d7ff166244b31d33f56a7 (diff)
qmltc: fix handlers for c++-signals
Allow qmltc to generate handlers for c++-defined signals with const parameters by changing the safeguard to avoid type mismatch between slots and signals. First, remove the qOverload in the generated QObject::connect call to be able the connect slots and signals with different types (namely, pass by const references and pass by value should be interchangeable but is not allowed by qOverload). Second, save in QQmlJSMetaParameter when types are passed by pointer. Like this, qqmljsimportvisitor can check if a value type is indeed passed by value or const reference in a C++ signal. The same for reference types that need to be passed by (const and non-const) pointer. Print a message when an type is passed by argument in an incompatible way instead of letting qmltc generate uncompilable code, which makes the compiler print out cryptical messages. Third, add a qqmlcpptypehelpers template that decides if value types should be passed by value or reference, by letting the c++ compiler check if sizeof(T) > 3*sizeof(void*). Fixes: QTBUG-107625 Fixes: QTBUG-107622 Change-Id: I1a00532df591d10f74c1fd00dff5b7fccf40cb22 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--src/qml/CMakeLists.txt1
-rw-r--r--src/qml/doc/snippets/qmltc/special/HelloWorld.qml.cpp2
-rw-r--r--src/qml/qmltc/supportlibrary/qqmlcpptypehelpers_p.h28
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp65
-rw-r--r--src/qmlcompiler/qqmljsmetatypes_p.h3
-rw-r--r--src/qmlcompiler/qqmljsscope.cpp2
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h1
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp6
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h34
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/mySignals.qml27
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp58
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h1
-rw-r--r--tests/auto/qml/qmltc_qprocess/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h14
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml10
-rw-r--r--tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp20
-rw-r--r--tools/qmltc/qmltccodewriter.cpp1
-rw-r--r--tools/qmltc/qmltccompiler.cpp28
19 files changed, 294 insertions, 12 deletions
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index 5781b03573..686c9dfb24 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -359,6 +359,7 @@ qt_internal_add_qml_module(Qml
qmltc/supportlibrary/qqmlcppbinding.cpp
qmltc/supportlibrary/qqmlcpponassignment_p.h
qmltc/supportlibrary/qqmlcpponassignment.cpp
+ qmltc/supportlibrary/qqmlcpptypehelpers_p.h
DEFINES
BUILDING_QT__
ENABLE_ASSEMBLER_WX_EXCLUSIVE=1
diff --git a/src/qml/doc/snippets/qmltc/special/HelloWorld.qml.cpp b/src/qml/doc/snippets/qmltc/special/HelloWorld.qml.cpp
index 732d915b99..eda9009bb7 100644
--- a/src/qml/doc/snippets/qmltc/special/HelloWorld.qml.cpp
+++ b/src/qml/doc/snippets/qmltc/special/HelloWorld.qml.cpp
@@ -31,7 +31,7 @@ public:
void setHello(const QString& hello_);
QString hello();
QBindable<QString> bindableHello();
- Q_INVOKABLE void printHello(QString prefix, QString suffix);
+ Q_INVOKABLE void printHello(passByConstRefOrValue<QString> prefix, passByConstRefOrValue<QString> suffix);
// ...
};
diff --git a/src/qml/qmltc/supportlibrary/qqmlcpptypehelpers_p.h b/src/qml/qmltc/supportlibrary/qqmlcpptypehelpers_p.h
new file mode 100644
index 0000000000..2470d87efe
--- /dev/null
+++ b/src/qml/qmltc/supportlibrary/qqmlcpptypehelpers_p.h
@@ -0,0 +1,28 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQMLCPPTYPEHELPERS_H
+#define QQMLCPPTYPEHELPERS_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <type_traits>
+
+/*! \internal
+ Used by Qmltc to decide when value types should be passed by value or reference.
+ */
+template<typename T>
+using passByConstRefOrValue =
+ std::conditional_t<((sizeof(T) > 3 * sizeof(void *)) || !std::is_trivial_v<T>), const T &,
+ T>;
+
+#endif // QQMLCPPTYPEHELPERS_H
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 8ce58cdcca..b44550cade 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -986,8 +986,69 @@ void QQmlJSImportVisitor::checkSignals()
const auto signalParameters = signalMethod->parameters();
QHash<QString, qsizetype> parameterNameIndexes;
- for (int i = 0; i < signalParameters.size(); i++)
- parameterNameIndexes[signalParameters[i].name()] = i;
+ // check parameter positions and also if signal is suitable for onSignal handler
+ for (int i = 0, end = signalParameters.size(); i < end; ++i) {
+ auto &p = signalParameters[i];
+ parameterNameIndexes[p.name()] = i;
+
+ auto signalName = [&]() {
+ if (signal)
+ return u" called %1"_s.arg(*signal);
+ return QString();
+ };
+ auto type = p.type();
+ if (!type) {
+ m_logger->log(
+ QStringLiteral(
+ "Type %1 of parameter %2 in signal%3 was not found, but is "
+ "required to compile %4. Did you add all import paths?")
+ .arg(p.typeName(), p.name(), signalName(), pair.first),
+ qmlSignalParameters, location);
+ continue;
+ }
+
+ if (type->isComposite())
+ continue;
+
+ // only accept following parameters for non-composite types:
+ // * QObjects by pointer (nonconst*, const*, const*const,*const)
+ // * Value types by value (QFont, int)
+ // * Value types by const ref (const QFont&, const int&)
+
+ auto parameterName = [&]() {
+ if (p.name().isEmpty())
+ return QString();
+ return u" called %1"_s.arg(p.name());
+ };
+ switch (type->accessSemantics()) {
+ case QQmlJSScope::AccessSemantics::Reference:
+ if (!p.isPointer())
+ m_logger->log(QStringLiteral("Type %1 of parameter%2 in signal%3 should be "
+ "passed by pointer to be able to compile %4. ")
+ .arg(p.typeName(), parameterName(), signalName(),
+ pair.first),
+ qmlSignalParameters, location);
+ break;
+ case QQmlJSScope::AccessSemantics::Value:
+ case QQmlJSScope::AccessSemantics::Sequence:
+ if (p.isPointer())
+ m_logger->log(
+ QStringLiteral(
+ "Type %1 of parameter%2 in signal%3 should be passed by "
+ "value or const reference to be able to compile %4. ")
+ .arg(p.typeName(), parameterName(), signalName(),
+ pair.first),
+ qmlSignalParameters, location);
+ break;
+ case QQmlJSScope::AccessSemantics::None:
+ m_logger->log(
+ QStringLiteral("Type %1 of parameter%2 in signal%3 required by the "
+ "compilation of %4 cannot be used. ")
+ .arg(p.typeName(), parameterName(), signalName(), pair.first),
+ qmlSignalParameters, location);
+ break;
+ }
+ }
if (pair.second.size() > signalParameters.size()) {
m_logger->log(QStringLiteral("Signal handler for \"%2\" has more formal"
diff --git a/src/qmlcompiler/qqmljsmetatypes_p.h b/src/qmlcompiler/qqmljsmetatypes_p.h
index 593a16b0c4..823a1849e5 100644
--- a/src/qmlcompiler/qqmljsmetatypes_p.h
+++ b/src/qmlcompiler/qqmljsmetatypes_p.h
@@ -135,6 +135,8 @@ public:
void setType(QWeakPointer<const QQmlJSScope> type) { m_type = type; }
Constness typeQualifier() const { return m_typeQualifier; }
void setTypeQualifier(Constness typeQualifier) { m_typeQualifier = typeQualifier; }
+ bool isPointer() const { return m_isPointer; }
+ void setIsPointer(bool isPointer) { m_isPointer = isPointer; }
friend bool operator==(const QQmlJSMetaParameter &a, const QQmlJSMetaParameter &b)
{
@@ -159,6 +161,7 @@ private:
QString m_typeName;
QWeakPointer<const QQmlJSScope> m_type;
Constness m_typeQualifier = NonConst;
+ bool m_isPointer = false;
};
class QQmlJSMetaMethod
diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp
index ec0a90643d..e3d8bafeb3 100644
--- a/src/qmlcompiler/qqmljsscope.cpp
+++ b/src/qmlcompiler/qqmljsscope.cpp
@@ -508,6 +508,8 @@ QTypeRevision QQmlJSScope::resolveType(
if (const QString typeName = parameter.typeName();
!parameter.type() && !typeName.isEmpty()) {
const auto type = findType(typeName, context, usedTypes);
+ if (type.scope && type.scope->isReferenceType())
+ parameter.setIsPointer(true);
parameter.setType({ type.scope });
}
}
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h
index 9586d1c333..127d58abcc 100644
--- a/src/qmlcompiler/qqmljsscope_p.h
+++ b/src/qmlcompiler/qqmljsscope_p.h
@@ -561,6 +561,7 @@ public:
void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; }
AccessSemantics accessSemantics() const { return m_semantics; }
bool isReferenceType() const { return m_semantics == QQmlJSScope::AccessSemantics::Reference; }
+ bool isValueType() const { return m_semantics == QQmlJSScope::AccessSemantics::Value; }
bool isIdInCurrentQmlScopes(const QString &id) const;
bool isIdInCurrentJSScopes(const QString &id) const;
diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
index 6f40b1d42f..8528d39f0f 100644
--- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp
+++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
@@ -428,6 +428,7 @@ void QQmlJSTypeDescriptionReader::readParameter(UiObjectDefinition *ast, QQmlJSM
QString name;
QString type;
bool isConstant = false;
+ bool isPointer = false;
for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) {
UiObjectMember *member = it->member;
@@ -443,9 +444,9 @@ void QQmlJSTypeDescriptionReader::readParameter(UiObjectDefinition *ast, QQmlJSM
} else if (id == QLatin1String("type")) {
type = readStringBinding(script);
} else if (id == QLatin1String("isPointer")) {
- // ### unhandled
+ isPointer = readBoolBinding(script);
} else if (id == QLatin1String("isConstant")) {
- isConstant = true;
+ isConstant = readBoolBinding(script);
} else if (id == QLatin1String("isReadonly")) {
// ### unhandled
} else if (id == QLatin1String("isList")) {
@@ -458,6 +459,7 @@ void QQmlJSTypeDescriptionReader::readParameter(UiObjectDefinition *ast, QQmlJSM
QQmlJSMetaParameter p(name, type);
p.setTypeQualifier(isConstant ? QQmlJSMetaParameter::Const : QQmlJSMetaParameter::NonConst);
+ p.setIsPointer(isPointer);
metaMethod->addParameter(std::move(p));
}
diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
index e81364d3e5..dc9a25a33a 100644
--- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
@@ -20,6 +20,7 @@ set(cpp_sources
cpptypes/typewithmanyproperties.h
cpptypes/singletontype.h cpptypes/singletontype.cpp
+ cpptypes/typewithsignal.h
)
set(qml_sources
@@ -105,6 +106,7 @@ set(qml_sources
aliases.qml
inlineComponentsFromDifferentFiles.qml
singletons.qml
+ mySignals.qml
# support types:
DefaultPropertySingleChild.qml
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
new file mode 100644
index 0000000000..139b431a40
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef TYPEWITHSIGNAL_H
+#define TYPEWITHSIGNAL_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqmlregistration.h>
+#include <QtGui/qfont.h>
+
+class TypeWithSignal : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+Q_SIGNALS:
+ // value types by value
+ void signalWithPrimitive(int);
+ void signalWithGadget(QFont);
+
+ // value types by const reference
+ void signalWithConstReferenceToGadget(const QFont &);
+ void signalWithConstReferenceToPrimitive(const int &);
+
+ // object by pointers
+ void signalWithPointer(QObject *);
+ void signalWithPointerToConst(const QObject *);
+ void signalWithPointerToConst2(QObject const *);
+ void signalWithConstPointer(QObject *const);
+ void signalWithConstPointerToConst(const QObject *const);
+ void signalWithConstPointerToConst2(QObject const *const);
+};
+
+#endif // TYPEWITHSIGNAL_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/mySignals.qml b/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
new file mode 100644
index 0000000000..c79a0518c2
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QmltcTests
+import QtQuick
+
+
+TypeWithSignal {
+ property int primitive
+ property font gadget
+ property QtObject object
+
+ // value types by value
+ onSignalWithPrimitive: (x) => { primitive = x; }
+ onSignalWithGadget: (x) => { gadget = x; }
+
+ // value types by const reference
+ onSignalWithConstReferenceToGadget: (x) => { gadget = x; }
+
+ // object by pointers
+ onSignalWithPointer: (x) => { object = x; }
+ onSignalWithPointerToConst: (x) => { object = x; }
+ onSignalWithPointerToConst2: (x) => { object = x; }
+ onSignalWithConstPointer: (x) => { object = x; }
+ onSignalWithConstPointerToConst: (x) => { object = x; }
+ onSignalWithConstPointerToConst2: (x) => { object = x; }
+}
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index af03af264c..06d63333fc 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -80,6 +80,7 @@
#include "testprivateproperty.h"
#include "singletons.h"
+#include "mysignals.h"
// Qt:
#include <QtCore/qstring.h>
@@ -3124,4 +3125,61 @@ void tst_qmltc::singletons()
QCOMPARE(createdByComponent->property("qmlSingleton2"), 100);
}
}
+
+void tst_qmltc::constSignalParameters()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(mySignals) fromQmltc(&e);
+
+ int primitive = 123;
+ QFont defaultGadget;
+ QFont gadget;
+ gadget.setBold(true);
+ QQuickItem myItem;
+ myItem.setObjectName("New Name");
+
+ // by value
+ fromQmltc.setPrimitive(123);
+ emit fromQmltc.signalWithPrimitive(primitive);
+ QCOMPARE(fromQmltc.primitive(), primitive);
+
+ fromQmltc.setGadget(defaultGadget);
+ emit fromQmltc.signalWithGadget(gadget);
+ QCOMPARE(fromQmltc.gadget(), gadget);
+
+ // by const ref
+ fromQmltc.setPrimitive(123);
+ emit fromQmltc.signalWithConstReferenceToPrimitive(primitive);
+ QCOMPARE(fromQmltc.primitive(), primitive);
+
+ fromQmltc.setGadget(defaultGadget);
+ emit fromQmltc.signalWithConstReferenceToGadget(gadget);
+ QCOMPARE(fromQmltc.gadget(), gadget);
+
+ // by pointer
+ fromQmltc.setObject(nullptr);
+ emit fromQmltc.signalWithPointer(&myItem);
+ QCOMPARE(fromQmltc.object(), &myItem);
+
+ fromQmltc.setObject(nullptr);
+ emit fromQmltc.signalWithPointerToConst(&myItem);
+ QCOMPARE(fromQmltc.object(), &myItem);
+
+ fromQmltc.setObject(nullptr);
+ emit fromQmltc.signalWithPointerToConst2(&myItem);
+ QCOMPARE(fromQmltc.object(), &myItem);
+
+ fromQmltc.setObject(nullptr);
+ emit fromQmltc.signalWithConstPointer(&myItem);
+ QCOMPARE(fromQmltc.object(), &myItem);
+
+ fromQmltc.setObject(nullptr);
+ emit fromQmltc.signalWithConstPointerToConst(&myItem);
+ QCOMPARE(fromQmltc.object(), &myItem);
+
+ fromQmltc.setObject(nullptr);
+ emit fromQmltc.signalWithConstPointerToConst2(&myItem);
+ QCOMPARE(fromQmltc.object(), &myItem);
+}
+
QTEST_MAIN(tst_qmltc)
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index ff55401c14..05a05bf9b6 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -90,4 +90,5 @@ private slots:
void aliases();
void inlineComponentsFromDifferentFiles();
void singletons();
+ void constSignalParameters();
};
diff --git a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
index 04d2084d4f..d936e2c757 100644
--- a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
@@ -20,6 +20,8 @@ qt6_add_qml_module(tst_qmltc_qprocess
AUTO_RESOURCE_PREFIX
SOURCES
cpptypes/testtype.h
+ DEPENDENCIES
+ QtQuick/auto
QML_FILES
data/dummy.qml
data/inlineComponentInvalidAlias.qml
@@ -30,6 +32,7 @@ qt6_add_qml_module(tst_qmltc_qprocess
data/inlineComponentWithEnum.qml
data/singletonUncreatable.qml
data/uncreatable.qml
+ data/invalidSignalHandlers.qml
)
set(common_libraries
diff --git a/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h b/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
index 6082870c76..2130004def 100644
--- a/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
+++ b/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
@@ -7,6 +7,7 @@
#include <QtQmlIntegration/qqmlintegration.h>
#include <QtCore/qobject.h>
#include <QtQml/qqmlregistration.h>
+#include <QtGui/qfont.h>
class TypeWithVersionedAlias : public QObject
{
@@ -67,6 +68,19 @@ class NormalType : public QObject
}
};
+class TypeWithSignals : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+Q_SIGNALS:
+ void signalWithConstPointerToGadget(const QFont *); // not allowed
+ void signalWithConstPointerToGadgetConst(const QFont *const); // not allowed
+ void signalWithPointerToGadgetConst(QFont *const); // not allowed
+ void signalWithPointerToGadget(QFont *); // not allowed
+ void signalWithPrimitivePointer(int *);
+ void signalWithConstPrimitivePointer(const int *);
+};
#endif // TESTTYPE_H
diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml b/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml
new file mode 100644
index 0000000000..a2a100ab3b
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml
@@ -0,0 +1,10 @@
+
+TypeWithSignals
+{
+ onSignalWithConstPointerToGadget: (x) => { console.log(x); }
+ onSignalWithConstPointerToGadgetConst: (x) => { console.log(x); }
+ onSignalWithPointerToGadgetConst: (x) => { console.log(x); }
+ onSignalWithPointerToGadget: (x) => { console.log(x); }
+ onSignalWithPrimitivePointer: (x) => { console.log(x); }
+ onSignalWithConstPrimitivePointer: (x) => { console.log(x); }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
index 04b3426298..1cea44206f 100644
--- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
+++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
@@ -50,6 +50,7 @@ private slots:
void invalidAliasRevision();
void topLevelComponent();
void dashesInFilename();
+ void invalidSignalHandlers();
};
#ifndef TST_QMLTC_QPROCESS_RESOURCES
@@ -241,5 +242,24 @@ void tst_qmltc_qprocess::dashesInFilename()
}
}
+void tst_qmltc_qprocess::invalidSignalHandlers()
+{
+ {
+ const auto errors = runQmltc(u"invalidSignalHandlers.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"invalidSignalHandlers.qml:4:5: Type QFont of parameter in signal called signalWithConstPointerToGadget should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadget. [signal-handler-parameters]"_s));
+ QVERIFY(errors.contains(
+ u"invalidSignalHandlers.qml:5:5: Type QFont of parameter in signal called signalWithConstPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadgetConst. [signal-handler-parameters]"_s));
+ QVERIFY(errors.contains(
+ u"invalidSignalHandlers.qml:6:5: Type QFont of parameter in signal called signalWithPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithPointerToGadgetConst. [signal-handler-parameters]"_s));
+ QVERIFY(errors.contains(
+ u"invalidSignalHandlers.qml:7:5: Type QFont of parameter in signal called signalWithPointerToGadget should be passed by value or const reference to be able to compile onSignalWithPointerToGadget. [signal-handler-parameters]"_s));
+ QVERIFY(errors.contains(
+ u"invalidSignalHandlers.qml:8:5: Type int of parameter in signal called signalWithPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithPrimitivePointer. [signal-handler-parameters]"_s));
+ QVERIFY(errors.contains(
+ u"invalidSignalHandlers.qml:9:5: Type int of parameter in signal called signalWithConstPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithConstPrimitivePointer. [signal-handler-parameters]"_s));
+ }
+}
+
QTEST_MAIN(tst_qmltc_qprocess)
#include "tst_qmltc_qprocess.moc"
diff --git a/tools/qmltc/qmltccodewriter.cpp b/tools/qmltc/qmltccodewriter.cpp
index 68bd803b15..c4c5c30f83 100644
--- a/tools/qmltc/qmltccodewriter.cpp
+++ b/tools/qmltc/qmltccodewriter.cpp
@@ -137,6 +137,7 @@ void QmltcCodeWriter::writeGlobalHeader(QmltcOutputWrapper &code, const QString
code.rawAppendToCpp(u"// qmltc support library:");
code.rawAppendToCpp(u"#include <private/qqmlcppbinding_p.h>"); // QmltcSupportLib
code.rawAppendToCpp(u"#include <private/qqmlcpponassignment_p.h>"); // QmltcSupportLib
+ code.rawAppendToHeader(u"#include <private/qqmlcpptypehelpers_p.h> "); // QmltcSupportLib
code.rawAppendToCpp(u"#include <private/qqmlobjectcreator_p.h>"); // createComponent()
code.rawAppendToCpp(u"#include <private/qqmlcomponent_p.h>"); // QQmlComponentPrivate::get()
diff --git a/tools/qmltc/qmltccompiler.cpp b/tools/qmltc/qmltccompiler.cpp
index a69f8619e9..4050136ef2 100644
--- a/tools/qmltc/qmltccompiler.cpp
+++ b/tools/qmltc/qmltccompiler.cpp
@@ -425,7 +425,24 @@ compileMethodParameters(const QList<QQmlJSMetaParameter> &parameterInfos, bool a
Q_ASSERT(allowUnnamed || !name.isEmpty()); // assume verified
if (name.isEmpty() && allowUnnamed)
name = u"unnamed_" + QString::number(i);
- parameters.emplaceBack(p.type()->augmentedInternalName(), name, QString());
+
+ QString internalName;
+ const QQmlJSScope::AccessSemantics semantics = p.type()->accessSemantics();
+
+ switch (semantics) {
+ case QQmlJSScope::AccessSemantics::Reference:
+ if (p.typeQualifier() == QQmlJSMetaParameter::Const)
+ internalName = u"const "_s;
+ internalName += u"%1*"_s.arg(p.type()->internalName());
+ break;
+ case QQmlJSScope::AccessSemantics::Value:
+ case QQmlJSScope::AccessSemantics::Sequence:
+ internalName = u"passByConstRefOrValue<%1>"_s.arg(p.type()->internalName());
+ break;
+ case QQmlJSScope::AccessSemantics::None:
+ Q_ASSERT(false); // or maybe print an error message
+ }
+ parameters.emplaceBack(internalName, name, QString());
}
return parameters;
}
@@ -1658,12 +1675,9 @@ void QmltcCompiler::compileScriptBinding(QmltcType &current,
slotMethod.type = QQmlJSMetaMethod::Slot;
current.functions << std::move(slotMethod);
- current.setComplexBindings.body
- << u"QObject::connect(" + This_signal + u", "
- + QmltcCodeGenerator::wrap_qOverload(
- slotParameters, u"&" + objectClassName_signal + u"::" + signalName)
- + u", " + This_slot + u", &" + objectClassName_slot + u"::" + slotName
- + u");";
+ current.setComplexBindings.body << u"QObject::connect(" + This_signal + u", " + u"&"
+ + objectClassName_signal + u"::" + signalName + u", " + This_slot + u", &"
+ + objectClassName_slot + u"::" + slotName + u");";
};
switch (binding.scriptKind()) {