diff options
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 40 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 6 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 28 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/failures.qml | 5 |
4 files changed, 41 insertions, 38 deletions
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index 2072b2a8ad..c1df2d9cca 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -725,6 +725,8 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) access = u"QString("_s + access + u")"_s; else if (m_state.isRegisterAffectedBySideEffects(base)) reject(u"LoadElement on a sequence potentially affected by side effects"_s); + else if (baseType.storedType()->accessSemantics() != QQmlJSScope::AccessSemantics::Sequence) + reject(u"LoadElement on a sequence wrapped in a non-sequence type"_s); m_body += u"if ("_s + indexName + u" < "_s + baseName + u".size())\n"_s; m_body += u" "_s + m_state.accumulatorVariableOut + u" = "_s + @@ -1091,15 +1093,28 @@ void QQmlJSCodeGenerator::generate_GetLookup(int index) const QString preparation = getLookupPreparation( m_state.accumulatorOut(), m_state.accumulatorVariableOut, index); generateLookup(lookup, initialization, preparation); - } else if (m_typeResolver->registerIsStoredIn(accumulatorIn, m_typeResolver->listPropertyType()) + } else if ((accumulatorIn.isList() + || m_typeResolver->registerContains(accumulatorIn, m_typeResolver->stringType())) && m_jsUnitGenerator->lookupName(index) == u"length"_s) { - m_body += m_state.accumulatorVariableOut + u" = "_s; - m_body += conversion( - 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; + const QQmlJSScope::ConstPtr stored = accumulatorIn.storedType(); + if (stored->isListProperty()) { + m_body += m_state.accumulatorVariableOut + u" = "_s; + m_body += conversion( + 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; + } else if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence + || m_typeResolver->equals(stored, m_typeResolver->stringType())) { + m_body += m_state.accumulatorVariableOut + u" = "_s + + conversion(m_typeResolver->globalType(m_typeResolver->int32Type()), + m_state.accumulatorOut(), + m_state.accumulatorVariableIn + u".length()"_s) + + u";\n"_s; + } else { + reject(u"access to 'length' property of sequence wrapped in non-sequence"_s); + } } else if (m_typeResolver->registerIsStoredIn(accumulatorIn, m_typeResolver->variantMapType())) { QString mapLookup = m_state.accumulatorVariableIn + u"["_s @@ -1108,15 +1123,6 @@ void QQmlJSCodeGenerator::generate_GetLookup(int index) m_body += conversion(m_typeResolver->globalType(m_typeResolver->varType()), m_state.accumulatorOut(), mapLookup); m_body += u";\n"_s; - } else if ((m_typeResolver->registerIsStoredIn(accumulatorIn, m_typeResolver->stringType()) - || accumulatorIn.storedType()->accessSemantics() - == QQmlJSScope::AccessSemantics::Sequence) - && m_jsUnitGenerator->lookupName(index) == u"length"_s) { - m_body += m_state.accumulatorVariableOut + u" = "_s - + conversion(m_typeResolver->globalType(m_typeResolver->int32Type()), - m_state.accumulatorOut(), - m_state.accumulatorVariableIn + u".length()"_s) - + u";\n"_s; } else { if (m_state.isRegisterAffectedBySideEffects(Accumulator)) reject(u"reading from a value that's potentially affected by side effects"_s); diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 19d8e8a695..609f8d8100 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -660,8 +660,8 @@ void QQmlJSTypePropagator::generate_LoadElement(int base) { const QQmlJSRegisterContent baseRegister = m_state.registers[base].content; - if ((baseRegister.storedType()->accessSemantics() != QQmlJSScope::AccessSemantics::Sequence - && !m_typeResolver->registerIsStoredIn(baseRegister, m_typeResolver->stringType())) + if ((!baseRegister.isList() + && !m_typeResolver->registerContains(baseRegister, m_typeResolver->stringType())) || !m_typeResolver->isNumeric(m_state.accumulatorIn())) { const auto jsValue = m_typeResolver->globalType(m_typeResolver->jsValueType()); addReadAccumulator(jsValue); @@ -690,7 +690,7 @@ void QQmlJSTypePropagator::generate_StoreElement(int base, int index) const QQmlJSRegisterContent baseRegister = m_state.registers[base].content; const QQmlJSRegisterContent indexRegister = checkedInputRegister(index); - if (baseRegister.storedType()->accessSemantics() != QQmlJSScope::AccessSemantics::Sequence + if (!baseRegister.isList() || !m_typeResolver->isNumeric(indexRegister)) { const auto jsValue = m_typeResolver->globalType(m_typeResolver->jsValueType()); addReadAccumulator(jsValue); diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 7fb37f3dfa..17c79095a2 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -814,26 +814,18 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType( 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) - || equals(type, m_varType) || equals(type, m_stringListType) - || equals(type, m_byteArrayType)) { + if (isPrimitive(type)) return type; - } - if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence) { - if (const QQmlJSScope::ConstPtr valueType = type->valueType()) { - switch (valueType->accessSemantics()) { - case QQmlJSScope::AccessSemantics::Value: - return genericType(valueType)->listType(); - case QQmlJSScope::AccessSemantics::Reference: - return m_qObjectListType; - default: - break; - } - } - return m_variantListType; + for (const QQmlJSScope::ConstPtr &builtin : { + m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type, + m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType, + m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType, + m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType, + m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType, + m_metaObjectType }) { + if (equals(type, builtin) || equals(type, builtin->listType())) + return type; } return m_varType; diff --git a/tests/auto/qml/qmlcppcodegen/data/failures.qml b/tests/auto/qml/qmlcppcodegen/data/failures.qml index b19b7f9ea2..e6f3af5e87 100644 --- a/tests/auto/qml/qmlcppcodegen/data/failures.qml +++ b/tests/auto/qml/qmlcppcodegen/data/failures.qml @@ -82,4 +82,9 @@ QtObject { } return a; } + + // TODO: Drop these once we can manipulate QVariant-wrapped lists. + property list<withLength> withLengths + property int l: withLengths.length + property withLength w: withLengths[10] } |