aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2023-03-27 18:00:46 +0200
committerUlf Hermann <[email protected]>2023-03-30 15:46:55 +0200
commit03ff348b4942ae29dd5bc2bd563998d7ba82ecd7 (patch)
tree8077bce26455108b449bb7bb9a3974a2b424cf3b
parent407ed344dadec77ae8ddb976a8ab1acfedcdb86d (diff)
QmlCompiler: Support more integer types
This adds support for 8- and 16-bit signed and unsigned integer types. The test exposes that the engine fails to correctly convert out of range values when assigning to a 32-bit int property. Fix that as drive-by. Fixes: QTBUG-101634 Change-Id: I0a4177f49ffc062a1f444e30424e94c1f293e70c Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Qt CI Bot <[email protected]>
-rw-r--r--src/imports/builtins/builtins.qmltypes32
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp96
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp67
-rw-r--r--src/qmlcompiler/qqmljstyperesolver.cpp100
-rw-r--r--src/qmlcompiler/qqmljstyperesolver_p.h23
-rw-r--r--src/qmltyperegistrar/qqmltypescreator.cpp4
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml42
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp83
9 files changed, 320 insertions, 129 deletions
diff --git a/src/imports/builtins/builtins.qmltypes b/src/imports/builtins/builtins.qmltypes
index 7a74279ee8..98f2d7ac75 100644
--- a/src/imports/builtins/builtins.qmltypes
+++ b/src/imports/builtins/builtins.qmltypes
@@ -168,6 +168,30 @@ Module {
}
Component {
+ name: "qint8"
+ extension: "Number"
+ accessSemantics: "value"
+ }
+
+ Component {
+ name: "quint8"
+ extension: "Number"
+ accessSemantics: "value"
+ }
+
+ Component {
+ name: "short"
+ extension: "Number"
+ accessSemantics: "value"
+ }
+
+ Component {
+ name: "ushort"
+ extension: "Number"
+ accessSemantics: "value"
+ }
+
+ Component {
name: "int"
extension: "Number"
exports: ["QML/int 1.0"]
@@ -182,13 +206,13 @@ Module {
}
Component {
- name: "qlonglong"
- accessSemantics: "value"
+ name: "qlonglong"
+ accessSemantics: "value"
}
Component {
- name: "qulonglong"
- accessSemantics: "value"
+ name: "qulonglong"
+ accessSemantics: "value"
}
Component {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 694b7828b6..e2ebda7d0e 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -602,7 +602,7 @@ void QObjectWrapper::setProperty(
scope.engine->throwError(error);
return;
} else if (propType == QMetaType::fromType<int>() && value.isNumber()) {
- PROPERTY_STORE(int, value.asDouble());
+ PROPERTY_STORE(int, value.toInt32());
} else if (propType == QMetaType::fromType<qreal>() && value.isNumber()) {
PROPERTY_STORE(qreal, qreal(value.asDouble()));
} else if (propType == QMetaType::fromType<float>() && value.isNumber()) {
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index c7a1940907..265347a577 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -336,7 +336,7 @@ void QQmlJSCodeGenerator::generate_LoadConst(int index)
m_body += conversion(
type, m_state.accumulatorOut(),
toNumericString(value.doubleValue()));
- } else if (type == m_typeResolver->intType()) {
+ } else if (type == m_typeResolver->int32Type()) {
m_body += conversion(
type, m_state.accumulatorOut(),
QString::number(value.integerValue()));
@@ -365,7 +365,7 @@ void QQmlJSCodeGenerator::generate_LoadZero()
m_body += m_state.accumulatorVariableOut;
m_body += u" = "_s + conversion(
- m_typeResolver->intType(), m_state.accumulatorOut(), u"0"_s);
+ m_typeResolver->int32Type(), m_state.accumulatorOut(), u"0"_s);
m_body += u";\n"_s;
}
@@ -415,7 +415,7 @@ void QQmlJSCodeGenerator::generate_LoadInt(int value)
m_body += m_state.accumulatorVariableOut;
m_body += u" = "_s;
- m_body += conversion(m_typeResolver->intType(), m_state.accumulatorOut(),
+ m_body += conversion(m_typeResolver->int32Type(), m_state.accumulatorOut(),
QString::number(value));
m_body += u";\n"_s;
}
@@ -446,7 +446,7 @@ void QQmlJSCodeGenerator::generate_MoveConst(int constIndex, int destTemp)
contained = m_typeResolver->boolType();
input = v4Value.booleanValue() ? u"true"_s : u"false"_s;
} else if (v4Value.isInteger()) {
- contained = m_typeResolver->intType();
+ contained = m_typeResolver->int32Type();
input = QString::number(v4Value.int_32());
} else if (v4Value.isDouble()) {
contained = m_typeResolver->realType();
@@ -691,15 +691,21 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base)
+ u"else "_s;
}
+ if (!m_typeResolver->isUnsignedInteger(
+ m_typeResolver->containedType(m_state.accumulatorIn()))) {
+ m_body += u"if ("_s + indexName + u" < 0)\n"_s
+ + voidAssignment
+ + u"else "_s;
+ }
+
if (m_typeResolver->registerIsStoredIn(baseType, m_typeResolver->listPropertyType())) {
// Our QQmlListProperty only keeps plain QObject*.
const auto valueType = m_typeResolver->valueType(baseType);
const auto elementType = m_typeResolver->globalType(
m_typeResolver->genericType(m_typeResolver->containedType(valueType)));
- m_body += u"if ("_s + indexName + u" >= 0 && "_s + indexName
- + u" < "_s + baseName + u".count(&"_s + baseName
- + u"))\n"_s;
+ m_body += u"if ("_s + indexName + u" < "_s + baseName
+ + u".count(&"_s + baseName + u"))\n"_s;
m_body += u" "_s + m_state.accumulatorVariableOut + u" = "_s +
conversion(elementType, m_state.accumulatorOut(),
baseName + u".at(&"_s + baseName + u", "_s
@@ -719,8 +725,7 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base)
else if (!m_typeResolver->canUseValueTypes())
reject(u"LoadElement in sequence type reference"_s);
- m_body += u"if ("_s + indexName + u" >= 0 && "_s + indexName
- + u" < "_s + baseName + u".size())\n"_s;
+ m_body += u"if ("_s + indexName + u" < "_s + baseName + u".size())\n"_s;
m_body += u" "_s + m_state.accumulatorVariableOut + u" = "_s +
conversion(elementType, m_state.accumulatorOut(), access) + u";\n"_s;
m_body += u"else\n"_s
@@ -757,8 +762,9 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index)
m_body += u"if ("_s;
if (!m_typeResolver->isIntegral(indexType))
m_body += u"QJSNumberCoercion::isInteger("_s + indexName + u") && "_s;
- m_body += indexName + u" >= 0 && "_s
- + indexName + u" < "_s + baseName + u".count(&"_s + baseName
+ if (!m_typeResolver->isUnsignedInteger(m_typeResolver->containedType(indexType)))
+ m_body += indexName + u" >= 0 && "_s;
+ m_body += indexName + u" < "_s + baseName + u".count(&"_s + baseName
+ u"))\n"_s;
m_body += u" "_s + baseName + u".replace(&"_s + baseName
+ u", "_s + indexName + u", "_s;
@@ -1067,7 +1073,8 @@ void QQmlJSCodeGenerator::generate_GetLookup(int index)
&& m_jsUnitGenerator->lookupName(index) == u"length"_s) {
m_body += m_state.accumulatorVariableOut + u" = "_s;
m_body += conversion(
- m_typeResolver->globalType(m_typeResolver->intType()), m_state.accumulatorOut(),
+ m_typeResolver->globalType(m_typeResolver->int32Type()),
+ m_state.accumulatorOut(),
m_state.accumulatorVariableIn + u".count("_s + u'&'
+ m_state.accumulatorVariableIn + u')');
m_body += u";\n"_s;
@@ -1084,7 +1091,7 @@ void QQmlJSCodeGenerator::generate_GetLookup(int index)
== QQmlJSScope::AccessSemantics::Sequence)
&& m_jsUnitGenerator->lookupName(index) == u"length"_s) {
m_body += m_state.accumulatorVariableOut + u" = "_s
- + conversion(m_typeResolver->globalType(m_typeResolver->intType()),
+ + conversion(m_typeResolver->globalType(m_typeResolver->int32Type()),
m_state.accumulatorOut(),
m_state.accumulatorVariableIn + u".length()"_s)
+ u";\n"_s;
@@ -1393,16 +1400,10 @@ bool QQmlJSCodeGenerator::inlineStringMethod(const QString &name, int base, int
const QQmlJSRegisterContent input = m_state.readRegister(argv);
m_body += m_state.accumulatorVariableOut + u" = "_s;
- if (m_typeResolver->registerContains(input, m_typeResolver->intType()))
- m_body += ret(arg(m_typeResolver->intType()));
- else if (m_typeResolver->registerContains(input, m_typeResolver->uintType()))
- m_body += ret(arg(m_typeResolver->uintType()));
+ if (m_typeResolver->isNumeric(input))
+ m_body += ret(arg(m_typeResolver->containedType(input)));
else if (m_typeResolver->registerContains(input, m_typeResolver->boolType()))
m_body += ret(arg(m_typeResolver->boolType()));
- else if (m_typeResolver->registerContains(input, m_typeResolver->realType()))
- m_body += ret(arg(m_typeResolver->realType()));
- else if (m_typeResolver->registerContains(input, m_typeResolver->floatType()))
- m_body += ret(arg(m_typeResolver->floatType()));
else
m_body += ret(arg(m_typeResolver->stringType()));
m_body += u";\n"_s;
@@ -1426,7 +1427,7 @@ bool QQmlJSCodeGenerator::inlineTranslateMethod(const QString &name, int argc, i
};
const auto intArg = [&](int i) {
- return i < argc ? arg(i, m_typeResolver->intType()) : u"-1"_s;
+ return i < argc ? arg(i, m_typeResolver->int32Type()) : u"-1"_s;
};
const auto stringRet = [&](const QString &expression) {
@@ -2207,27 +2208,24 @@ void QQmlJSCodeGenerator::generate_CmpNeNull()
QString QQmlJSCodeGenerator::eqIntExpression(int lhsConst)
{
- if (m_typeResolver->registerIsStoredIn(m_state.accumulatorIn(), m_typeResolver->intType())
- || m_typeResolver->registerIsStoredIn(
- m_state.accumulatorIn(), m_typeResolver->uintType())) {
+ if (m_typeResolver->isIntegral(m_state.accumulatorIn()))
return QString::number(lhsConst) + u" == "_s + m_state.accumulatorVariableIn;
- }
if (m_typeResolver->registerIsStoredIn(m_state.accumulatorIn(), m_typeResolver->boolType())) {
return QString::number(lhsConst) + u" == "_s
- + convertStored(m_state.accumulatorIn().storedType(), m_typeResolver->intType(),
+ + convertStored(m_state.accumulatorIn().storedType(), m_typeResolver->int32Type(),
consumedAccumulatorVariableIn());
}
if (m_typeResolver->isNumeric(m_state.accumulatorIn())) {
- return convertStored(m_typeResolver->intType(), m_typeResolver->realType(),
+ return convertStored(m_typeResolver->int32Type(), m_typeResolver->realType(),
QString::number(lhsConst)) + u" == "_s
+ convertStored(m_state.accumulatorIn().storedType(), m_typeResolver->realType(),
consumedAccumulatorVariableIn());
}
QString result;
- result += convertStored(m_typeResolver->intType(), m_typeResolver->jsPrimitiveType(),
+ result += convertStored(m_typeResolver->int32Type(), m_typeResolver->jsPrimitiveType(),
QString::number(lhsConst));
result += u".equals("_s;
result += convertStored(m_state.accumulatorIn().storedType(), m_typeResolver->jsPrimitiveType(),
@@ -2264,7 +2262,7 @@ QString QQmlJSCodeGenerator::contentPointer(const QQmlJSRegisterContent &content
if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
return u'&' + var;
- if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->intType())
+ if (m_typeResolver->isNumeric(content.storedType())
&& m_typeResolver->containedType(content)->scopeType() == QQmlJSScope::EnumScope) {
return u'&' + var;
}
@@ -2292,10 +2290,8 @@ QString QQmlJSCodeGenerator::contentType(const QQmlJSRegisterContent &content, c
if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
return metaTypeFromName(contained);
- if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->intType())
- && m_typeResolver->containedType(content)->scopeType() == QQmlJSScope::EnumScope) {
- return metaTypeFromType(m_typeResolver->intType());
- }
+ if (m_typeResolver->isNumeric(stored) && contained->scopeType() == QQmlJSScope::EnumScope)
+ return metaTypeFromType(contained->baseType());
if (stored->isListProperty() && m_typeResolver->containedType(content)->isListProperty())
return metaTypeFromType(m_typeResolver->listPropertyType());
@@ -2832,7 +2828,7 @@ void QQmlJSCodeGenerator::generateArithmeticConstOperation(int rhsConst, const Q
generateArithmeticOperation(
conversion(m_state.accumulatorIn(), m_state.readAccumulator(),
consumedAccumulatorVariableIn()),
- conversion(m_typeResolver->globalType(m_typeResolver->intType()),
+ conversion(m_typeResolver->globalType(m_typeResolver->int32Type()),
m_state.readAccumulator(), QString::number(rhsConst)),
cppOperator);
}
@@ -3017,7 +3013,7 @@ QString QQmlJSCodeGenerator::conversion(
const QString conversion = variable + u".to<QJSPrimitiveValue::%1>()"_s;
if (m_typeResolver->equals(contained, m_typeResolver->boolType()))
return conversion.arg(u"Boolean"_s);
- if (m_typeResolver->equals(contained, m_typeResolver->intType()))
+ if (m_typeResolver->isIntegral(to))
return conversion.arg(u"Integer"_s);
if (m_typeResolver->equals(contained, m_typeResolver->realType()))
return conversion.arg(u"Double"_s);
@@ -3027,12 +3023,12 @@ QString QQmlJSCodeGenerator::conversion(
}
if (m_typeResolver->registerIsStoredIn(to, contained)
- || m_typeResolver->registerIsStoredIn(from, m_typeResolver->intType())
+ || m_typeResolver->isNumeric(from.storedType())
|| to.storedType()->isReferenceType()
|| m_typeResolver->registerContains(from, contained)) {
// If:
// * the output is not actually wrapped at all, or
- // * the input is stored in an int (as there are no internals to an int), or
+ // * the input is stored in a numeric type (as there are no internals to a number), or
// * the output is a QObject pointer, or
// * we merely wrap the value into a new container,
// we can convert by stored type.
@@ -3057,9 +3053,9 @@ QString QQmlJSCodeGenerator::convertStored(
auto zeroBoolOrInt = [&](const QQmlJSScope::ConstPtr &to) {
if (m_typeResolver->equals(to, boolType))
return u"false"_s;
- if (m_typeResolver->equals(to, m_typeResolver->intType()))
+ if (m_typeResolver->isSignedInteger(to))
return u"0"_s;
- if (m_typeResolver->equals(to, m_typeResolver->uintType()))
+ if (m_typeResolver->isUnsignedInteger(to))
return u"0u"_s;
return QString();
};
@@ -3153,9 +3149,9 @@ QString QQmlJSCodeGenerator::convertStored(
if (m_typeResolver->equals(from, m_typeResolver->realType())
|| m_typeResolver->equals(from, m_typeResolver->floatType())) {
- if (m_typeResolver->equals(to, m_typeResolver->intType()))
+ if (m_typeResolver->isSignedInteger(to))
return u"QJSNumberCoercion::toInteger("_s + variable + u')';
- if (m_typeResolver->equals(to, m_typeResolver->uintType()))
+ if (m_typeResolver->isUnsignedInteger(to))
return u"uint(QJSNumberCoercion::toInteger("_s + variable + u"))"_s;
if (m_typeResolver->equals(to, m_typeResolver->boolType()))
return u'(' + variable + u" && !std::isnan("_s + variable + u"))"_s;
@@ -3170,9 +3166,9 @@ QString QQmlJSCodeGenerator::convertStored(
return variable + u".toDouble()"_s;
if (m_typeResolver->equals(to, boolType))
return variable + u".toBoolean()"_s;
- if (m_typeResolver->equals(to, m_typeResolver->intType()))
+ if (m_typeResolver->isSignedInteger(to))
return variable + u".toInteger()"_s;
- if (m_typeResolver->equals(to, m_typeResolver->uintType()))
+ if (m_typeResolver->isUnsignedInteger(to))
return u"uint("_s + variable + u".toInteger())"_s;
if (m_typeResolver->equals(to, m_typeResolver->stringType()))
return variable + u".toString()"_s;
@@ -3198,10 +3194,14 @@ QString QQmlJSCodeGenerator::convertStored(
Q_ASSERT(!m_typeResolver->equals(from, m_typeResolver->voidType()));
if (m_typeResolver->equals(from, m_typeResolver->boolType())
- || m_typeResolver->equals(from, m_typeResolver->intType())
+ || m_typeResolver->equals(from, m_typeResolver->int32Type())
|| m_typeResolver->equals(from, m_typeResolver->realType())
|| m_typeResolver->equals(from, m_typeResolver->stringType())) {
return u"QJSPrimitiveValue("_s + variable + u')';
+ } else if (m_typeResolver->isSignedInteger(from)
+ || m_typeResolver->equals(from, m_typeResolver->uint16Type())
+ || m_typeResolver->equals(from, m_typeResolver->uint8Type())) {
+ return u"QJSPrimitiveValue(int("_s + variable + u"))"_s;
} else if (m_typeResolver->isNumeric(from)) {
return u"QJSPrimitiveValue(double("_s + variable + u"))"_s;
}
@@ -3264,9 +3264,9 @@ QString QQmlJSCodeGenerator::convertStored(
{
if (m_typeResolver->equals(type, m_typeResolver->boolType()))
return expression + u".toBoolean()"_s;
- if (m_typeResolver->equals(type, m_typeResolver->intType()))
+ if (m_typeResolver->isSignedInteger(type))
return expression + u".toInteger()"_s;
- if (m_typeResolver->equals(type, m_typeResolver->uintType()))
+ if (m_typeResolver->isUnsignedInteger(type))
return u"uint("_s + expression + u".toInteger())"_s;
if (m_typeResolver->equals(type, m_typeResolver->realType()))
return expression + u".toDouble()"_s;
@@ -3321,7 +3321,7 @@ QString QQmlJSCodeGenerator::convertContained(const QQmlJSRegisterContent &from,
// Those should be handled before, by convertStored().
Q_ASSERT(!to.storedType()->isReferenceType());
Q_ASSERT(!m_typeResolver->registerIsStoredIn(to, containedTo));
- Q_ASSERT(!m_typeResolver->registerIsStoredIn(from, m_typeResolver->intType()));
+ Q_ASSERT(!m_typeResolver->isIntegral(from.storedType()));
Q_ASSERT(!m_typeResolver->equals(containedFrom, containedTo));
if (!m_typeResolver->registerIsStoredIn(to, m_typeResolver->varType()) &&
diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp
index 67b12d299f..57844dee61 100644
--- a/src/qmlcompiler/qqmljstypepropagator.cpp
+++ b/src/qmlcompiler/qqmljstypepropagator.cpp
@@ -122,7 +122,7 @@ void QQmlJSTypePropagator::generate_LoadConst(int index)
void QQmlJSTypePropagator::generate_LoadZero()
{
- setAccumulator(m_typeResolver->globalType(m_typeResolver->intType()));
+ setAccumulator(m_typeResolver->globalType(m_typeResolver->int32Type()));
}
void QQmlJSTypePropagator::generate_LoadTrue()
@@ -147,7 +147,7 @@ void QQmlJSTypePropagator::generate_LoadUndefined()
void QQmlJSTypePropagator::generate_LoadInt(int)
{
- setAccumulator(m_typeResolver->globalType(m_typeResolver->intType()));
+ setAccumulator(m_typeResolver->globalType(m_typeResolver->int32Type()));
}
void QQmlJSTypePropagator::generate_MoveConst(int constIndex, int destTemp)
@@ -669,8 +669,11 @@ void QQmlJSTypePropagator::generate_LoadElement(int base)
return;
}
- if (m_typeResolver->isIntegral(m_state.accumulatorIn()))
- addReadAccumulator(m_typeResolver->globalType(m_typeResolver->intType()));
+ const auto contained = m_typeResolver->containedType(m_state.accumulatorIn());
+ if (m_typeResolver->isSignedInteger(contained))
+ addReadAccumulator(m_typeResolver->globalType(m_typeResolver->int32Type()));
+ else if (m_typeResolver->isUnsignedInteger(contained))
+ addReadAccumulator(m_typeResolver->globalType(m_typeResolver->uint32Type()));
else
addReadAccumulator(m_typeResolver->globalType(m_typeResolver->realType()));
@@ -699,8 +702,11 @@ void QQmlJSTypePropagator::generate_StoreElement(int base, int index)
return;
}
- if (m_typeResolver->isIntegral(indexRegister))
- addReadRegister(index, m_typeResolver->globalType(m_typeResolver->intType()));
+ const auto contained = m_typeResolver->containedType(indexRegister);
+ if (m_typeResolver->isSignedInteger(contained))
+ addReadRegister(index, m_typeResolver->globalType(m_typeResolver->int32Type()));
+ else if (m_typeResolver->isUnsignedInteger(contained))
+ addReadRegister(index, m_typeResolver->globalType(m_typeResolver->uint32Type()));
else
addReadRegister(index, m_typeResolver->globalType(m_typeResolver->realType()));
@@ -1261,7 +1267,7 @@ bool QQmlJSTypePropagator::propagateTranslationMethod(
const QQmlJSMetaMethod method = methods.front();
const QQmlJSRegisterContent intType
- = m_typeResolver->globalType(m_typeResolver->intType());
+ = m_typeResolver->globalType(m_typeResolver->int32Type());
const QQmlJSRegisterContent stringType
= m_typeResolver->globalType(m_typeResolver->stringType());
const QQmlJSRegisterContent returnType
@@ -1370,17 +1376,25 @@ void QQmlJSTypePropagator::propagateStringArgCall(int argv)
const QQmlJSScope::ConstPtr input = m_typeResolver->containedType(
m_state.registers[argv].content);
- for (QQmlJSScope::ConstPtr targetType : {
- m_typeResolver->intType(),
- m_typeResolver->uintType(),
- m_typeResolver->realType(),
- m_typeResolver->floatType(),
- m_typeResolver->boolType(),
- }) {
- if (m_typeResolver->equals(input, targetType)) {
- addReadRegister(argv, m_typeResolver->globalType(targetType));
- return;
- }
+
+ if (m_typeResolver->equals(input, m_typeResolver->uint32Type())) {
+ addReadRegister(argv, m_typeResolver->globalType(m_typeResolver->realType()));
+ return;
+ }
+
+ if (m_typeResolver->isIntegral(input)) {
+ addReadRegister(argv, m_typeResolver->globalType(m_typeResolver->int32Type()));
+ return;
+ }
+
+ if (m_typeResolver->isNumeric(input)) {
+ addReadRegister(argv, m_typeResolver->globalType(m_typeResolver->realType()));
+ return;
+ }
+
+ if (m_typeResolver->equals(input, m_typeResolver->boolType())) {
+ addReadRegister(argv, m_typeResolver->globalType(m_typeResolver->boolType()));
+ return;
}
addReadRegister(argv, m_typeResolver->globalType(m_typeResolver->stringType()));
@@ -1779,10 +1793,11 @@ void QQmlJSTypePropagator::recordEqualsType(int lhs)
};
const auto isIntCompatible = [this](const QQmlJSRegisterContent &content) {
- const QQmlJSScope::ConstPtr contained = m_typeResolver->containedType(content);
- return contained->scopeType() == QQmlJSScope::EnumScope
- || m_typeResolver->equals(contained, m_typeResolver->intType())
- || m_typeResolver->equals(contained, m_typeResolver->uintType());
+ auto contained = m_typeResolver->containedType(content);
+ if (contained->scopeType() == QQmlJSScope::EnumScope)
+ contained = contained->baseType();
+ return m_typeResolver->isIntegral(contained)
+ && !m_typeResolver->equals(contained, m_typeResolver->uint32Type());
};
const auto accumulatorIn = m_state.accumulatorIn();
@@ -1797,7 +1812,7 @@ void QQmlJSTypePropagator::recordEqualsType(int lhs)
return;
} else if (isNumericOrEnum(accumulatorIn) && isNumericOrEnum(lhsRegister)) {
const auto targetType = isIntCompatible(accumulatorIn) && isIntCompatible(lhsRegister)
- ? m_typeResolver->globalType(m_typeResolver->intType())
+ ? m_typeResolver->globalType(m_typeResolver->int32Type())
: m_typeResolver->globalType(m_typeResolver->realType());
addReadRegister(lhs, targetType);
addReadAccumulator(targetType);
@@ -1858,7 +1873,7 @@ void QQmlJSTypePropagator::generate_CmpEqInt(int lhsConst)
recordEqualsIntType();
Q_UNUSED(lhsConst)
setAccumulator(QQmlJSRegisterContent(m_typeResolver->typeForBinaryOperation(
- QSOperator::Op::Equal, m_typeResolver->globalType(m_typeResolver->intType()),
+ QSOperator::Op::Equal, m_typeResolver->globalType(m_typeResolver->int32Type()),
m_state.accumulatorIn())));
}
@@ -1867,7 +1882,7 @@ void QQmlJSTypePropagator::generate_CmpNeInt(int lhsConst)
recordEqualsIntType();
Q_UNUSED(lhsConst)
setAccumulator(QQmlJSRegisterContent(m_typeResolver->typeForBinaryOperation(
- QSOperator::Op::NotEqual, m_typeResolver->globalType(m_typeResolver->intType()),
+ QSOperator::Op::NotEqual, m_typeResolver->globalType(m_typeResolver->int32Type()),
m_state.accumulatorIn())));
}
@@ -2040,7 +2055,7 @@ void QQmlJSTypePropagator::generateBinaryConstArithmeticOperation(QSOperator::Op
{
const QQmlJSRegisterContent type = m_typeResolver->typeForBinaryOperation(
op, m_state.accumulatorIn(),
- m_typeResolver->builtinType(m_typeResolver->intType()));
+ m_typeResolver->builtinType(m_typeResolver->int32Type()));
checkConversion(m_state.accumulatorIn(), type);
addReadAccumulator(type);
diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp
index ece40f20ef..4c200b5677 100644
--- a/src/qmlcompiler/qqmljstyperesolver.cpp
+++ b/src/qmlcompiler/qqmljstyperesolver.cpp
@@ -28,8 +28,14 @@ QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer)
m_nullType = builtinTypes.type(u"std::nullptr_t"_s).scope;
m_realType = builtinTypes.type(u"double"_s).scope;
m_floatType = builtinTypes.type(u"float"_s).scope;
- m_intType = builtinTypes.type(u"int"_s).scope;
- m_uintType = builtinTypes.type(u"uint"_s).scope;
+ m_int8Type = builtinTypes.type(u"qint8"_s).scope;
+ m_uint8Type = builtinTypes.type(u"quint8"_s).scope;
+ m_int16Type = builtinTypes.type(u"short"_s).scope;
+ m_uint16Type = builtinTypes.type(u"ushort"_s).scope;
+ m_int32Type = builtinTypes.type(u"int"_s).scope;
+ m_uint32Type = builtinTypes.type(u"uint"_s).scope;
+ m_int64Type = builtinTypes.type(u"qlonglong"_s).scope;
+ m_uint64Type = builtinTypes.type(u"qulonglong"_s).scope;
m_boolType = builtinTypes.type(u"bool"_s).scope;
m_stringType = builtinTypes.type(u"QString"_s).scope;
m_stringListType = builtinTypes.type(u"QStringList"_s).scope;
@@ -147,7 +153,7 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::typeForConst(QV4::ReturnedValue rv) co
return voidType();
if (value.isInt32())
- return intType();
+ return int32Type();
if (value.isBoolean())
return boolType();
@@ -187,9 +193,9 @@ QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, const QQmlJSRegi
case QSOperator::Op::BitXor:
case QSOperator::Op::LShift:
case QSOperator::Op::RShift:
- return builtinType(intType());
+ return builtinType(int32Type());
case QSOperator::Op::URShift:
- return builtinType(uintType());
+ return builtinType(uint32Type());
case QSOperator::Op::Add: {
const auto leftContents = containedType(left);
const auto rightContents = containedType(right);
@@ -198,7 +204,7 @@ QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, const QQmlJSRegi
const QQmlJSScope::ConstPtr result = merge(leftContents, rightContents);
if (equals(result, boolType()))
- return builtinType(intType());
+ return builtinType(int32Type());
if (isNumeric(result))
return builtinType(realType());
@@ -208,7 +214,7 @@ QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, const QQmlJSRegi
case QSOperator::Op::Mul:
case QSOperator::Op::Exp: {
const QQmlJSScope::ConstPtr result = merge(containedType(left), containedType(right));
- return builtinType(equals(result, boolType()) ? intType() : realType());
+ return builtinType(equals(result, boolType()) ? int32Type() : realType());
}
case QSOperator::Op::Div:
case QSOperator::Op::Mod:
@@ -229,14 +235,14 @@ QQmlJSRegisterContent QQmlJSTypeResolver::typeForArithmeticUnaryOperation(
case UnaryOperator::Not:
return builtinType(boolType());
case UnaryOperator::Complement:
- return builtinType(intType());
+ return builtinType(int32Type());
case UnaryOperator::Plus:
if (isIntegral(operand))
return operand;
Q_FALLTHROUGH();
default:
if (equals(containedType(operand), boolType()))
- return builtinType(intType());
+ return builtinType(int32Type());
break;
}
@@ -255,13 +261,18 @@ bool QQmlJSTypeResolver::isNumeric(const QQmlJSRegisterContent &type) const
bool QQmlJSTypeResolver::isIntegral(const QQmlJSRegisterContent &type) const
{
- return equals(containedType(type), m_intType) || equals(containedType(type), m_uintType);
+ return isIntegral(containedType(type));
+}
+
+bool QQmlJSTypeResolver::isIntegral(const QQmlJSScope::ConstPtr &type) const
+{
+ // Only types of length <= 32bit count as integral
+ return isSignedInteger(type) || isUnsignedInteger(type);
}
bool QQmlJSTypeResolver::isPrimitive(const QQmlJSScope::ConstPtr &type) const
{
- return equals(type, m_intType) || equals(type, m_uintType)
- || equals(type, m_realType) || equals(type, m_floatType)
+ return isNumeric(type)
|| equals(type, m_boolType) || equals(type, m_voidType) || equals(type, m_nullType)
|| equals(type, m_stringType) || equals(type, m_jsPrimitiveType);
}
@@ -273,7 +284,23 @@ bool QQmlJSTypeResolver::isNumeric(const QQmlJSScope::ConstPtr &type) const
if (mode == QQmlJSScope::ExtensionNamespace)
return false;
return equals(scope, m_numberPrototype);
- });
+ });
+}
+
+bool QQmlJSTypeResolver::isSignedInteger(const QQmlJSScope::ConstPtr &type) const
+{
+ // Only types of length <= 32bit count as integral
+ return equals(type, m_int8Type)
+ || equals(type, m_int16Type)
+ || equals(type, m_int32Type);
+}
+
+bool QQmlJSTypeResolver::isUnsignedInteger(const QQmlJSScope::ConstPtr &type) const
+{
+ // Only types of length <= 32bit count as integral
+ return equals(type, m_uint8Type)
+ || equals(type, m_uint16Type)
+ || equals(type, m_uint32Type);
}
QQmlJSScope::ConstPtr
@@ -623,21 +650,31 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(const QQmlJSScope::ConstPtr &a,
if (equals(b, jsValueType()) || equals(b, varType()))
return b;
- auto canConvert = [&](const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) {
- return (equals(a, from) && equals(b, to)) || (equals(b, from) && equals(a, to));
+ const auto isInt32Compatible = [&](const QQmlJSScope::ConstPtr &type) {
+ return (isIntegral(type) && !equals(type, uint32Type())) || equals(type, boolType());
+ };
+
+ if (isInt32Compatible(a) && isInt32Compatible(b))
+ return int32Type();
+
+ const auto isUInt32Compatible = [&](const QQmlJSScope::ConstPtr &type) {
+ return isUnsignedInteger(type) || equals(type, boolType());
};
+ if (isUInt32Compatible(a) && isUInt32Compatible(b))
+ return uint32Type();
+
if (isNumeric(a) && isNumeric(b))
return realType();
- if (canConvert(boolType(), intType()))
- return intType();
- if (canConvert(boolType(), uintType()))
- return uintType();
- if (canConvert(intType(), stringType()))
- return stringType();
- if (canConvert(uintType(), stringType()))
+ const auto isStringCompatible = [&](const QQmlJSScope::ConstPtr &type) {
+ // TODO: We can losslessly coerce more types to string. Should we?
+ return isIntegral(type) || equals(type, stringType());
+ };
+
+ if (isStringCompatible(a) && isStringCompatible(b))
return stringType();
+
if (isPrimitive(a) && isPrimitive(b))
return jsPrimitiveType();
@@ -765,6 +802,9 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
if (type->isListProperty())
return m_listPropertyType;
+ if (type->scopeType() == QQmlJSScope::EnumScope)
+ return type->baseType();
+
if (isPrimitive(type) || equals(type, m_jsValueType) || equals(type, m_urlType)
|| equals(type, m_dateTimeType) || equals(type, m_dateType) || equals(type, m_timeType)
|| equals(type, m_variantListType) || equals(type, m_variantMapType)
@@ -773,12 +813,6 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
return type;
}
- if (type->scopeType() == QQmlJSScope::EnumScope)
- return m_intType;
-
- if (isNumeric(type))
- return m_realType;
-
if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence) {
if (const QQmlJSScope::ConstPtr valueType = type->valueType()) {
switch (valueType->accessSemantics()) {
@@ -944,7 +978,7 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS
for (const auto &enumeration : enums) {
if (enumeration.name() == name) {
*result = QQmlJSRegisterContent::create(
- storedType(intType()), enumeration, QString(),
+ storedType(enumeration.type()), enumeration, QString(),
inExtension ? QQmlJSRegisterContent::ExtensionObjectEnum
: QQmlJSRegisterContent::ObjectEnum,
scope);
@@ -953,7 +987,7 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS
if (enumeration.hasKey(name)) {
*result = QQmlJSRegisterContent::create(
- storedType(intType()), enumeration, name,
+ storedType(enumeration.type()), enumeration, name,
inExtension ? QQmlJSRegisterContent::ExtensionObjectEnum
: QQmlJSRegisterContent::ObjectEnum,
scope);
@@ -1109,9 +1143,9 @@ QQmlJSRegisterContent QQmlJSTypeResolver::lengthProperty(
QQmlJSMetaProperty prop;
prop.setPropertyName(u"length"_s);
prop.setTypeName(u"int"_s);
- prop.setType(intType());
+ prop.setType(int32Type());
prop.setIsWritable(isWritable);
- return QQmlJSRegisterContent::create(intType(), prop, QQmlJSRegisterContent::Builtin, scope);
+ return QQmlJSRegisterContent::create(int32Type(), prop, QQmlJSRegisterContent::Builtin, scope);
}
QQmlJSRegisterContent QQmlJSTypeResolver::memberType(const QQmlJSScope::ConstPtr &type,
@@ -1252,7 +1286,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType(const QQmlJSRegisterContent
const auto enumeration = type.enumeration();
if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
return {};
- return QQmlJSRegisterContent::create(storedType(intType()), enumeration, name,
+ return QQmlJSRegisterContent::create(storedType(enumeration.type()), enumeration, name,
QQmlJSRegisterContent::ObjectEnum, type.scopeType());
}
if (type.isMethod()) {
diff --git a/src/qmlcompiler/qqmljstyperesolver_p.h b/src/qmlcompiler/qqmljstyperesolver_p.h
index 9d730630e0..4776caf226 100644
--- a/src/qmlcompiler/qqmljstyperesolver_p.h
+++ b/src/qmlcompiler/qqmljstyperesolver_p.h
@@ -45,8 +45,14 @@ public:
QQmlJSScope::ConstPtr nullType() const { return m_nullType; }
QQmlJSScope::ConstPtr realType() const { return m_realType; }
QQmlJSScope::ConstPtr floatType() const { return m_floatType; }
- QQmlJSScope::ConstPtr intType() const { return m_intType; }
- QQmlJSScope::ConstPtr uintType() const { return m_uintType; }
+ QQmlJSScope::ConstPtr int8Type() const { return m_int8Type; }
+ QQmlJSScope::ConstPtr uint8Type() const { return m_uint8Type; }
+ QQmlJSScope::ConstPtr int16Type() const { return m_int16Type; }
+ QQmlJSScope::ConstPtr uint16Type() const { return m_uint16Type; }
+ QQmlJSScope::ConstPtr int32Type() const { return m_int32Type; }
+ QQmlJSScope::ConstPtr uint32Type() const { return m_uint32Type; }
+ QQmlJSScope::ConstPtr int64Type() const { return m_int64Type; }
+ QQmlJSScope::ConstPtr uint64Type() const { return m_uint64Type; }
QQmlJSScope::ConstPtr boolType() const { return m_boolType; }
QQmlJSScope::ConstPtr stringType() const { return m_stringType; }
QQmlJSScope::ConstPtr stringListType() const { return m_stringListType; }
@@ -166,6 +172,9 @@ public:
bool canHoldUndefined(const QQmlJSRegisterContent &content) const;
bool isNumeric(const QQmlJSScope::ConstPtr &type) const;
+ bool isIntegral(const QQmlJSScope::ConstPtr &type) const;
+ bool isSignedInteger(const QQmlJSScope::ConstPtr &type) const;
+ bool isUnsignedInteger(const QQmlJSScope::ConstPtr &type) const;
bool canHold(const QQmlJSScope::ConstPtr &container,
const QQmlJSScope::ConstPtr &contained) const;
@@ -202,8 +211,14 @@ protected:
QQmlJSScope::ConstPtr m_arrayType;
QQmlJSScope::ConstPtr m_realType;
QQmlJSScope::ConstPtr m_floatType;
- QQmlJSScope::ConstPtr m_intType;
- QQmlJSScope::ConstPtr m_uintType;
+ QQmlJSScope::ConstPtr m_int8Type;
+ QQmlJSScope::ConstPtr m_uint8Type;
+ QQmlJSScope::ConstPtr m_int16Type;
+ QQmlJSScope::ConstPtr m_uint16Type;
+ QQmlJSScope::ConstPtr m_int32Type;
+ QQmlJSScope::ConstPtr m_uint32Type;
+ QQmlJSScope::ConstPtr m_int64Type;
+ QQmlJSScope::ConstPtr m_uint64Type;
QQmlJSScope::ConstPtr m_boolType;
QQmlJSScope::ConstPtr m_stringType;
QQmlJSScope::ConstPtr m_stringListType;
diff --git a/src/qmltyperegistrar/qqmltypescreator.cpp b/src/qmltyperegistrar/qqmltypescreator.cpp
index df9ba2b6c6..51a4d3de8e 100644
--- a/src/qmltyperegistrar/qqmltypescreator.cpp
+++ b/src/qmltyperegistrar/qqmltypescreator.cpp
@@ -187,6 +187,10 @@ void QmlTypesCreator::writeType(const QJsonObject &property, const QString &key)
#else
type = QLatin1String("double");
#endif
+ } else if (type == QLatin1String("qint16")) {
+ type = QLatin1String("short");
+ } else if (type == QLatin1String("quint16")) {
+ type = QLatin1String("ushort");
} else if (type == QLatin1String("qint32")) {
type = QLatin1String("int");
} else if (type == QLatin1String("quint32")) {
diff --git a/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml b/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
index f12d3f5ea2..ec848429e8 100644
--- a/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
@@ -4,23 +4,57 @@ import TestTypes
QtObject {
function writeValues() {
+ Druggeljug.myInt8 = 35
+ Druggeljug.myUint8 = 36
+ Druggeljug.myInt16 = 37
+ Druggeljug.myUint16 = 38
Druggeljug.myInt = 39
Druggeljug.myUint = 40
Druggeljug.myInt32 = 41
Druggeljug.myUint32 = 42
}
+ function negateValues() {
+ Druggeljug.myInt8 = -Druggeljug.myInt8;
+ Druggeljug.myUint8 = -Druggeljug.myUint8;
+ Druggeljug.myInt16 = -Druggeljug.myInt16;
+ Druggeljug.myUint16 = -Druggeljug.myUint16;
+ Druggeljug.myInt = -Druggeljug.myInt;
+ Druggeljug.myUint = -Druggeljug.myUint;
+ Druggeljug.myInt32 = -Druggeljug.myInt32;
+ Druggeljug.myUint32 = -Druggeljug.myUint32;
+ }
+
+ function shuffleValues() {
+ Druggeljug.myInt8 = Druggeljug.myUint8;
+ Druggeljug.myUint8 = Druggeljug.myInt16;
+ Druggeljug.myInt16 = Druggeljug.myUint16;
+ Druggeljug.myUint16 = Druggeljug.myInt;
+ Druggeljug.myInt = Druggeljug.myUint;
+ Druggeljug.myUint = Druggeljug.myInt32;
+ Druggeljug.myInt32 = Druggeljug.myUint32;
+ Druggeljug.myUint32 = Druggeljug.myInt8;
+ }
+
function readValueAsString(i: int) : string {
switch (i) {
- case 0: return Druggeljug.myInt;
- case 1: return Druggeljug.myUint;
- case 2: return Druggeljug.myInt32;
- case 3: return Druggeljug.myUint32;
+ case 0: return Druggeljug.myInt8;
+ case 1: return Druggeljug.myUint8;
+ case 2: return Druggeljug.myInt16;
+ case 3: return Druggeljug.myUint16;
+ case 4: return Druggeljug.myInt;
+ case 5: return Druggeljug.myUint;
+ case 6: return Druggeljug.myInt32;
+ case 7: return Druggeljug.myUint32;
default: return "";
}
}
function storeValues() {
+ Druggeljug.storeMyInt8(1330)
+ Druggeljug.storeMyUint8(1331)
+ Druggeljug.storeMyInt16(1332)
+ Druggeljug.storeMyUint16(1333)
Druggeljug.storeMyInt(1334)
Druggeljug.storeMyUint(1335)
Druggeljug.storeMyInt32(1336)
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 821e676786..92b8efc203 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -3043,10 +3043,10 @@ void tst_QmlCppCodegen::lengthAccessArraySequenceCompat()
QCOMPARE(o->property("length").toInt(), 100);
}
-static QList<QString> convertToStrings(const QList<int> &ints)
+static QList<QString> convertToStrings(const QList<qint64> &ints)
{
QList<QString> strings;
- for (int i : ints)
+ for (qint64 i : ints)
strings.append(QString::number(i));
return strings;
}
@@ -3059,12 +3059,41 @@ void tst_QmlCppCodegen::numbersInJsPrimitive()
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- const QList<int> zeroes = {0, 0, 0, 0};
- const QList<int> written = {39, 40, 41, 42};
- const QList<int> stored = {1334, 1335, 1336, 1337};
- QStringList asStrings(4);
+ const QList<qint64> zeroes
+ = {0, 0, 0, 0, 0, 0, 0, 0};
+ const QList<qint64> written
+ = {35, 36, 37, 38, 39, 40, 41, 42};
+ const QList<qint64> writtenNegative
+ = {-35, 220, -37, 65498, -39, 4294967256, -41, 4294967254};
+ const QList<QList<qint64>> writtenShuffled = {
+ { -36, 219, -38, 65497, -40, 4294967255, -42, 4294967260 },
+ { -37, 218, -39, 65496, -41, 4294967254, -36, 4294967259 },
+ { -38, 217, -40, 65495, -42, 4294967260, -37, 4294967258 },
+ { -39, 216, -41, 65494, -36, 4294967259, -38, 4294967257 },
+ { -40, 215, -42, 65500, -37, 4294967258, -39, 4294967256 },
+ { -41, 214, -36, 65499, -38, 4294967257, -40, 4294967255 },
+ { -42, 220, -37, 65498, -39, 4294967256, -41, 4294967254 },
+ { -36, 219, -38, 65497, -40, 4294967255, -42, 4294967260 },
+ };
+
+ const QList<qint64> stored
+ = {50, 51, 1332, 1333, 1334, 1335, 1336, 1337};
+ const QList<qint64> storedNegative
+ = {-50, 205, -1332, 64203, -1334, 4294965961, -1336, 4294965959};
+ const QList<QList<qint64>> storedShuffled = {
+ { -51, 204, -1333, 64202, -1335, 4294965960, -1337, 4294967245 },
+ { -52, 203, -1334, 64201, -1336, 4294965959, -51, 4294967244 },
+ { -53, 202, -1335, 64200, -1337, 4294967245, -52, 4294967243 },
+ { -54, 201, -1336, 64199, -51, 4294967244, -53, 4294967242 },
+ { -55, 200, -1337, 65485, -52, 4294967243, -54, 4294967241 },
+ { -56, 199, -51, 65484, -53, 4294967242, -55, 4294967240 },
+ { -57, 205, -52, 65483, -54, 4294967241, -56, 4294967239 },
+ { -51, 204, -53, 65482, -55, 4294967240, -57, 4294967245 },
+ };
- for (int i = 0; i < 4; ++i) {
+ QStringList asStrings(8);
+
+ for (int i = 0; i < 8; ++i) {
QMetaObject::invokeMethod(
o.data(), "readValueAsString",
Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
@@ -3072,20 +3101,56 @@ void tst_QmlCppCodegen::numbersInJsPrimitive()
QCOMPARE(asStrings, convertToStrings(zeroes));
QMetaObject::invokeMethod(o.data(), "writeValues");
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 8; ++i) {
QMetaObject::invokeMethod(
o.data(), "readValueAsString",
Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
}
QCOMPARE(asStrings, convertToStrings(written));
+ QMetaObject::invokeMethod(o.data(), "negateValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(writtenNegative));
+
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(o.data(), "shuffleValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(writtenShuffled[i]));
+ }
+
QMetaObject::invokeMethod(o.data(), "storeValues");
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 8; ++i) {
QMetaObject::invokeMethod(
o.data(), "readValueAsString",
Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
}
QCOMPARE(asStrings, convertToStrings(stored));
+
+ QMetaObject::invokeMethod(o.data(), "negateValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(storedNegative));
+
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(o.data(), "shuffleValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(storedShuffled[i]));
+ }
}
void tst_QmlCppCodegen::infinitiesToInt()