QmlCompiler: Coerce values when calling methods
The type of the register may not be the one to be passed to the method. We cannot rely on the run time internals to coerce the value anymore since we've moved the type determination out of the generated code. To make this happen, we need to adjust the storage types of read registers in the storage generalizer. Pick-to: 6.9 Fixes: QTBUG-132329 Change-Id: I642027f349f7c05f714ec36ef4e23f9d59b4a8df Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
This commit is contained in:
parent
f90bdf9d7a
commit
3d12a83170
|
@ -1735,10 +1735,22 @@ QString QQmlJSCodeGenerator::initAndCall(
|
|||
args = contentPointer(m_state.accumulatorOut(), *outVar);
|
||||
}
|
||||
|
||||
// We may need to convert the arguments to the function call so that they match what the
|
||||
// function expects. They are passed as void* after all. We try to convert them where they
|
||||
// are created, but if they are read as different types in multiple places, we can't.
|
||||
QString argumentPreparation;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
const QQmlJSRegisterContent content = registerType(argv + i);
|
||||
const QString var = registerVariable(argv + i);
|
||||
args += u", "_s + contentPointer(content, var);
|
||||
const QQmlJSRegisterContent read = m_state.readRegister(argv + i);
|
||||
if (read.contains(content.containedType())) {
|
||||
args += u", "_s + contentPointer(read, registerVariable(argv + i));
|
||||
} else {
|
||||
const QString var = u"arg"_s + QString::number(i);
|
||||
argumentPreparation +=
|
||||
u" "_s + read.storedType()->augmentedInternalName() + u' ' + var + u" = "_s
|
||||
+ conversion(content, read, consumedRegisterVariable(argv + i)) + u";\n";
|
||||
args += u", "_s + contentPointer(read, var);
|
||||
}
|
||||
}
|
||||
|
||||
QString initMethod;
|
||||
|
@ -1755,6 +1767,7 @@ QString QQmlJSCodeGenerator::initAndCall(
|
|||
}
|
||||
|
||||
return u"const auto doCall = [&]() {\n"_s
|
||||
+ argumentPreparation
|
||||
+ u" void *args[] = {" + args + u"};\n"_s
|
||||
+ u" return aotContext->"_s + callMethodTemplate.arg(u"args"_s).arg(argc) + u";\n"
|
||||
+ u"};\n"_s
|
||||
|
|
|
@ -55,6 +55,7 @@ QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageGeneralizer::run(Function *
|
|||
for (auto i = m_annotations.begin(), iEnd = m_annotations.end(); i != iEnd; ++i) {
|
||||
transformRegister(i->second.changedRegister);
|
||||
transformRegisters(i->second.typeConversions);
|
||||
transformRegisters(i->second.readRegisters);
|
||||
}
|
||||
|
||||
return { std::move(m_basicBlocks), std::move(m_annotations) };
|
||||
|
|
|
@ -24,6 +24,7 @@ set(cpp_sources
|
|||
sequenceToIterable.h
|
||||
sequencetypeexample.cpp sequencetypeexample.h
|
||||
state.h
|
||||
takenumber.cpp takenumber.h
|
||||
theme.cpp theme.h
|
||||
timelinetheme.cpp timelinetheme.h
|
||||
variantMapLookup.h
|
||||
|
@ -275,6 +276,7 @@ set(qml_files
|
|||
stringLength.qml
|
||||
stringToByteArray.qml
|
||||
structuredValueType.qml
|
||||
takenumber.qml
|
||||
testlogger.js
|
||||
text.qml
|
||||
themerbad.qml
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include "takenumber.h"
|
||||
|
||||
TakeNumber::TakeNumber(QObject *parent)
|
||||
: QObject{parent}
|
||||
{}
|
||||
|
||||
void TakeNumber::takeInt(int a)
|
||||
{
|
||||
takenInt = a;
|
||||
}
|
||||
|
||||
void TakeNumber::takeNegativeInt(int a)
|
||||
{
|
||||
takenNegativeInt = a;
|
||||
}
|
||||
|
||||
void TakeNumber::takeQSizeType(qsizetype a)
|
||||
{
|
||||
takenQSizeType = a;
|
||||
}
|
||||
|
||||
void TakeNumber::takeQLongLong(qlonglong a)
|
||||
{
|
||||
takenQLongLong = a;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#ifndef TAKENUMBER_H
|
||||
#define TAKENUMBER_H
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtQml/qqml.h>
|
||||
|
||||
class TakeNumber : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
explicit TakeNumber(QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void takeInt(int a);
|
||||
Q_INVOKABLE void takeNegativeInt(int a);
|
||||
Q_INVOKABLE void takeQSizeType(qsizetype a);
|
||||
Q_INVOKABLE void takeQLongLong(qlonglong a);
|
||||
|
||||
int takenInt = 0;
|
||||
int takenNegativeInt = 0;
|
||||
qsizetype takenQSizeType = 0;
|
||||
qlonglong takenQLongLong = 0;
|
||||
};
|
||||
|
||||
#endif // TAKENUMBER_H
|
|
@ -0,0 +1,36 @@
|
|||
pragma Strict
|
||||
import QtQml
|
||||
|
||||
TakeNumber {
|
||||
id: foo
|
||||
|
||||
function literal0() {
|
||||
foo.takeInt(0)
|
||||
foo.takeNegativeInt(0)
|
||||
foo.takeQSizeType(0)
|
||||
foo.takeQLongLong(0)
|
||||
}
|
||||
|
||||
function literal56() {
|
||||
foo.takeInt(56)
|
||||
foo.takeNegativeInt(-56)
|
||||
foo.takeQSizeType(56)
|
||||
foo.takeQLongLong(56)
|
||||
}
|
||||
|
||||
function variable0() {
|
||||
var a = 0
|
||||
foo.takeInt(a)
|
||||
foo.takeNegativeInt(-a)
|
||||
foo.takeQSizeType(a)
|
||||
foo.takeQLongLong(a)
|
||||
}
|
||||
|
||||
function variable484() {
|
||||
var a = 484
|
||||
foo.takeInt(a)
|
||||
foo.takeNegativeInt(-a)
|
||||
foo.takeQSizeType(a)
|
||||
foo.takeQLongLong(a)
|
||||
}
|
||||
}
|
|
@ -9,10 +9,11 @@
|
|||
#include <data/getOptionalLookup.h>
|
||||
#include <data/listprovider.h>
|
||||
#include <data/objectwithmethod.h>
|
||||
#include <data/qmlusing.h>
|
||||
#include <data/resettable.h>
|
||||
#include <data/takenumber.h>
|
||||
#include <data/weathermoduleurl.h>
|
||||
#include <data/withlength.h>
|
||||
#include <data/qmlusing.h>
|
||||
|
||||
#include <QtQml/private/qqmlengine_p.h>
|
||||
#include <QtQml/private/qqmlpropertycachecreator_p.h>
|
||||
|
@ -239,6 +240,7 @@ private slots:
|
|||
void stringLength();
|
||||
void stringToByteArray();
|
||||
void structuredValueType();
|
||||
void takeNumbers();
|
||||
void testIsnan();
|
||||
void thisObject();
|
||||
void throwObjectName();
|
||||
|
@ -4909,6 +4911,51 @@ void tst_QmlCppCodegen::structuredValueType()
|
|||
QCOMPARE(o->property("w2").value<WeatherModelUrl>(), w2);
|
||||
}
|
||||
|
||||
void tst_QmlCppCodegen::takeNumbers()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/takenumber.qml"_s));
|
||||
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
||||
QScopedPointer<QObject> o(c.create());
|
||||
QVERIFY(!o.isNull());
|
||||
|
||||
TakeNumber *takeNumber = qobject_cast<TakeNumber *>(o.data());
|
||||
QVERIFY(takeNumber != nullptr);
|
||||
|
||||
QCOMPARE(takeNumber->takenInt, 0);
|
||||
QCOMPARE(takeNumber->takenNegativeInt, 0);
|
||||
QCOMPARE(takeNumber->takenQSizeType, 0);
|
||||
QCOMPARE(takeNumber->takenQLongLong, 0);
|
||||
|
||||
o->metaObject()->invokeMethod(o.data(), "literal56");
|
||||
|
||||
QCOMPARE(takeNumber->takenInt, 56);
|
||||
QCOMPARE(takeNumber->takenNegativeInt, -56);
|
||||
QCOMPARE(takeNumber->takenQSizeType, 56);
|
||||
QCOMPARE(takeNumber->takenQLongLong, 56);
|
||||
|
||||
o->metaObject()->invokeMethod(o.data(), "variable0");
|
||||
|
||||
QCOMPARE(takeNumber->takenInt, 0);
|
||||
QCOMPARE(takeNumber->takenNegativeInt, 0);
|
||||
QCOMPARE(takeNumber->takenQSizeType, 0);
|
||||
QCOMPARE(takeNumber->takenQLongLong, 0);
|
||||
|
||||
o->metaObject()->invokeMethod(o.data(), "variable484");
|
||||
|
||||
QCOMPARE(takeNumber->takenInt, 484);
|
||||
QCOMPARE(takeNumber->takenNegativeInt, -484);
|
||||
QCOMPARE(takeNumber->takenQSizeType, 484);
|
||||
QCOMPARE(takeNumber->takenQLongLong, 484);
|
||||
|
||||
o->metaObject()->invokeMethod(o.data(), "literal0");
|
||||
|
||||
QCOMPARE(takeNumber->takenInt, 0);
|
||||
QCOMPARE(takeNumber->takenNegativeInt, 0);
|
||||
QCOMPARE(takeNumber->takenQSizeType, 0);
|
||||
QCOMPARE(takeNumber->takenQLongLong, 0);
|
||||
}
|
||||
|
||||
void tst_QmlCppCodegen::testIsnan()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
|
|
Loading…
Reference in New Issue