From dd731b880b4bfbe7bad7b0b4d1ac3b72503c0071 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 10 Jun 2024 11:21:15 +0200 Subject: [PATCH] QmlCompiler: Create QQmlJSRegisterContent unstored MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a separate pass to populate the stored types and only run that after we're done with all the type propagation and optimization. Task-number: QTBUG-124670 Change-Id: I740063908b22684f5d2c72d6261fad98850d8636 Reviewed-by: Olivier De Cannière Reviewed-by: Fabian Kosmale --- src/qmlcompiler/CMakeLists.txt | 1 + src/qmlcompiler/qqmljscodegenerator.cpp | 127 +++++++++--------- src/qmlcompiler/qqmljscodegenerator_p.h | 20 ++- src/qmlcompiler/qqmljscompiler.cpp | 8 +- src/qmlcompiler/qqmljslintercodegen.cpp | 7 + src/qmlcompiler/qqmljsoptimizations.cpp | 23 +--- src/qmlcompiler/qqmljsregistercontent.cpp | 80 ++++------- src/qmlcompiler/qqmljsregistercontent_p.h | 26 ++-- src/qmlcompiler/qqmljsshadowcheck.cpp | 2 - src/qmlcompiler/qqmljsstoragegeneralizer.cpp | 1 + src/qmlcompiler/qqmljsstorageinitializer.cpp | 81 +++++++++++ src/qmlcompiler/qqmljsstorageinitializer_p.h | 40 ++++++ src/qmlcompiler/qqmljstypepropagator.cpp | 8 +- src/qmlcompiler/qqmljstyperesolver.cpp | 94 ++++++------- tests/auto/qml/qmllint/tst_qmllint.cpp | 11 +- .../auto/qml/qqmljsscope/tst_qqmljsscope.cpp | 4 +- 16 files changed, 313 insertions(+), 220 deletions(-) create mode 100644 src/qmlcompiler/qqmljsstorageinitializer.cpp create mode 100644 src/qmlcompiler/qqmljsstorageinitializer_p.h diff --git a/src/qmlcompiler/CMakeLists.txt b/src/qmlcompiler/CMakeLists.txt index 663a0d69a3..72fab3cab0 100644 --- a/src/qmlcompiler/CMakeLists.txt +++ b/src/qmlcompiler/CMakeLists.txt @@ -34,6 +34,7 @@ qt_internal_add_module(QmlCompiler qqmljscontextualtypes_p.h qqmljsshadowcheck.cpp qqmljsshadowcheck_p.h qqmljsstoragegeneralizer.cpp qqmljsstoragegeneralizer_p.h + qqmljsstorageinitializer.cpp qqmljsstorageinitializer_p.h qqmljstypedescriptionreader.cpp qqmljstypedescriptionreader_p.h qqmljstypepropagator.cpp qqmljstypepropagator_p.h qqmljstypereader.cpp qqmljstypereader_p.h diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index 8d07d9846b..f4d4a13d23 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -213,7 +213,7 @@ QT_WARNING_POP if (!registerIsArgument && registerIndex != Accumulator && registerIndex != This - && !registerIsStoredIn( + && !m_typeResolver->registerContains( function->registerTypes[registerIndex - firstRegisterIndex()], m_typeResolver->voidType())) { result.code += registerIt->variableName + u" = "_s; @@ -223,10 +223,9 @@ QT_WARNING_POP const int argumentIndex = registerIndex - FirstArgument; const QQmlJSRegisterContent argument = m_function->argumentTypes[argumentIndex]; - const QQmlJSRegisterContent original - = m_typeResolver->original(argument); + const QQmlJSRegisterContent originalArgument = original(argument); - const bool needsConversion = argument != original; + const bool needsConversion = argument != originalArgument; if (!isPointer && registerIt->numTracked == 1 && !needsConversion) { // Not a pointer, never written to, and doesn't need any initial conversion. // This is a readonly argument. @@ -240,11 +239,11 @@ QT_WARNING_POP result.code += registerIt->variableName + u" = "_s; const QString originalValue - = u"(*static_cast<"_s + castTargetName(original.storedType()) + = u"(*static_cast<"_s + castTargetName(originalArgument.storedType()) + u"*>(argv["_s + QString::number(argumentIndex + 1) + u"]))"_s; if (needsConversion) - result.code += conversion(original, argument, originalValue); + result.code += conversion(originalArgument, argument, originalValue); else result.code += originalValue; } else { @@ -683,9 +682,11 @@ void QQmlJSCodeGenerator::generate_LoadQmlContextPropertyLookup(int index) const int nameIndex = m_jsUnitGenerator->lookupNameIndex(index); const QString name = m_jsUnitGenerator->stringForIndex(nameIndex); if (m_state.accumulatorOut().variant() == QQmlJSRegisterContent::JavaScriptGlobal) { + // This produces a QJSValue. The QQmlJSMetaProperty used to analyze it may have more details + // but the QQmlJSAotContext API does not reflect them. m_body += m_state.accumulatorVariableOut + u" = "_s + conversion( - m_typeResolver->original(m_state.accumulatorOut()), m_state.accumulatorOut(), + m_typeResolver->jsValueType(), m_state.accumulatorOut(), u"aotContext->javaScriptGlobalProperty("_s + QString::number(nameIndex) + u")") + u";\n"_s; return; @@ -775,7 +776,7 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) } const QString voidAssignment = u" "_s + m_state.accumulatorVariableOut + u" = "_s + - conversion(m_typeResolver->globalType(m_typeResolver->voidType()), + conversion(global(m_typeResolver->voidType()), m_state.accumulatorOut(), QString()) + u";\n"_s; QString indexName = m_state.accumulatorVariableIn; @@ -812,7 +813,7 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) if (registerIsStoredIn(baseType, m_typeResolver->listPropertyType())) { // Our QQmlListProperty only keeps plain QObject*. - const auto elementType = m_typeResolver->globalType(m_typeResolver->qObjectType()); + const auto elementType = global(m_typeResolver->qObjectType()); m_body += u"if ("_s + indexName + u" < "_s + baseName + u".count(&"_s + baseName + u"))\n"_s; @@ -825,7 +826,9 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) return; } - const auto elementType = m_typeResolver->valueType(baseType); + // Since we can do .at() below, we know that we can natively store the element type. + QQmlJSRegisterContent elementType = m_typeResolver->valueType(baseType); + elementType = elementType.storedIn(m_typeResolver->storedType(elementType.containedType())); QString access = baseName + u".at("_s + indexName + u')'; @@ -865,8 +868,8 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index) const QString indexName = registerVariable(index); const auto valueType = m_typeResolver->valueType(baseType); - const auto elementType = m_typeResolver->globalType(m_typeResolver->genericType( - m_typeResolver->containedType(valueType))); + const auto elementType = global(m_typeResolver->genericType( + m_typeResolver->containedType(valueType))); addInclude(u"QtQml/qjslist.h"_s); if (!m_typeResolver->isNativeArrayIndex(indexType)) @@ -1078,8 +1081,7 @@ void QQmlJSCodeGenerator::generateVariantEqualityComparison( : m_typeResolver->containedType(storableContent); if (contained->isReferenceType()) { - const QQmlJSRegisterContent comparable - = m_typeResolver->builtinType(m_typeResolver->qObjectType()); + const QQmlJSRegisterContent comparable = builtin(m_typeResolver->qObjectType()); m_body += m_state.accumulatorVariableOut + u" = "_s + (invert ? u"!"_s : QString()) + u"((" + varRegisterName + u".metaType().flags() & QMetaType::PointerToQObject) "_s + u" && "_s + conversion(storableContent, comparable, typedRegisterName) + u" == "_s @@ -1088,8 +1090,7 @@ void QQmlJSCodeGenerator::generateVariantEqualityComparison( } if (m_typeResolver->isPrimitive(contained)) { - const QQmlJSRegisterContent comparable - = m_typeResolver->builtinType(m_typeResolver->jsPrimitiveType()); + const QQmlJSRegisterContent comparable = builtin(m_typeResolver->jsPrimitiveType()); m_body += m_state.accumulatorVariableOut + u" = "_s + (invert ? u"!"_s : QString()) + conversion(storableContent, comparable, typedRegisterName) + u".strictlyEquals("_s @@ -1457,7 +1458,7 @@ void QQmlJSCodeGenerator::generate_GetLookupHelper(int index) if (stored->isListProperty()) { m_body += m_state.accumulatorVariableOut + u" = "_s; m_body += conversion( - m_typeResolver->globalType(m_typeResolver->sizeType()), + global(m_typeResolver->sizeType()), m_state.accumulatorOut(), m_state.accumulatorVariableIn + u".count("_s + u'&' + m_state.accumulatorVariableIn + u')'); @@ -1465,7 +1466,7 @@ void QQmlJSCodeGenerator::generate_GetLookupHelper(int index) } 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->sizeType()), + + conversion(global(m_typeResolver->sizeType()), m_state.accumulatorOut(), m_state.accumulatorVariableIn + u".length()"_s) + u";\n"_s; @@ -1476,7 +1477,7 @@ void QQmlJSCodeGenerator::generate_GetLookupHelper(int index) QString mapLookup = m_state.accumulatorVariableIn + u"["_s + QQmlJSUtils::toLiteral(m_jsUnitGenerator->lookupName(index)) + u"]"_s; m_body += m_state.accumulatorVariableOut + u" = "_s; - m_body += conversion(m_typeResolver->globalType(m_typeResolver->varType()), + m_body += conversion(global(m_typeResolver->varType()), m_state.accumulatorOut(), mapLookup); m_body += u";\n"_s; } else { @@ -2189,7 +2190,7 @@ bool QQmlJSCodeGenerator::inlineArrayMethod(const QString &name, int base, int a call += u")"; const auto outType = baseType.storedType()->isListProperty() - ? m_typeResolver->globalType(m_typeResolver->qObjectListType()) + ? global(m_typeResolver->qObjectListType()) : baseType; m_body += m_state.accumulatorVariableOut + u" = "_s @@ -2347,9 +2348,9 @@ void QQmlJSCodeGenerator::generate_Construct(int func, int argc, int argv) INJECT_TRACE_INFO(generate_Construct); Q_UNUSED(func); - const auto original = m_typeResolver->original(m_state.accumulatorOut()); + const auto originalResult = original(m_state.accumulatorOut()); - if (m_typeResolver->registerContains(original, m_typeResolver->dateTimeType())) { + if (m_typeResolver->registerContains(originalResult, m_typeResolver->dateTimeType())) { m_body += m_state.accumulatorVariableOut + u" = "; if (argc == 0) { m_body += conversion( @@ -2382,7 +2383,7 @@ void QQmlJSCodeGenerator::generate_Construct(int func, int argc, int argv) return; } - if (m_typeResolver->registerContains(original, m_typeResolver->variantListType())) { + if (m_typeResolver->registerContains(originalResult, m_typeResolver->variantListType())) { rejectIfBadArray(); if (argc == 1 @@ -2464,8 +2465,7 @@ void QQmlJSCodeGenerator::generate_ThrowException() generateSetInstructionPointer(); m_body += u"aotContext->engine->throwError("_s - + conversion(m_state.accumulatorIn(), m_typeResolver->globalType( - m_typeResolver->jsValueType()), + + conversion(m_state.accumulatorIn(), global(m_typeResolver->jsValueType()), m_state.accumulatorVariableIn) + u");\n"_s; generateReturnError(); m_skipUntilNextLabel = true; @@ -2593,10 +2593,14 @@ void QQmlJSCodeGenerator::generate_IteratorNext(int value, int offset) reject(u"using non-iterator as iterator"_s); m_body += u"if (" + m_state.accumulatorVariableIn + u"->hasNext(" + qjsList + u")) {\n "; + + // We know that this works because we can do ->next() below. + QQmlJSRegisterContent iteratorValue = m_typeResolver->valueType(iteratorContent); + iteratorValue = iteratorValue.storedIn(iteratorValue.containedType()); + m_body += changedRegisterVariable() + u" = " + conversion( - m_typeResolver->valueType(iteratorContent), - m_state.changedRegister(), + iteratorValue, m_state.changedRegister(), m_state.accumulatorVariableIn + u"->next(" + qjsList + u')') + u";\n"; m_body += u"} else {\n "; @@ -2700,7 +2704,7 @@ void QQmlJSCodeGenerator::generate_DefineObjectLiteral(int internalClassId, int m_body += u"{ "_s + conversion( registerType(nameArg), - m_typeResolver->globalType(m_typeResolver->stringType()), + global(m_typeResolver->stringType()), consumedRegisterVariable(nameArg)) + u", "_s; @@ -2891,15 +2895,13 @@ void QQmlJSCodeGenerator::generate_CheckException() void QQmlJSCodeGenerator::generate_CmpEqNull() { INJECT_TRACE_INFO(generate_CmpEqNull); - generateEqualityOperation( - m_typeResolver->globalType(m_typeResolver->nullType()), QString(), u"equals"_s, false); + generateEqualityOperation(global(m_typeResolver->nullType()), QString(), u"equals"_s, false); } void QQmlJSCodeGenerator::generate_CmpNeNull() { INJECT_TRACE_INFO(generate_CmlNeNull); - generateEqualityOperation( - m_typeResolver->globalType(m_typeResolver->nullType()), QString(), u"equals"_s, true); + generateEqualityOperation(global(m_typeResolver->nullType()), QString(), u"equals"_s, true); } QString QQmlJSCodeGenerator::getLookupPreparation( @@ -2973,8 +2975,7 @@ void QQmlJSCodeGenerator::generate_CmpEqInt(int lhsConst) INJECT_TRACE_INFO(generate_CmpEqInt); generateEqualityOperation( - m_typeResolver->globalType(m_typeResolver->int32Type()), QString::number(lhsConst), - u"equals"_s, false); + global(m_typeResolver->int32Type()), QString::number(lhsConst), u"equals"_s, false); } void QQmlJSCodeGenerator::generate_CmpNeInt(int lhsConst) @@ -2982,8 +2983,7 @@ void QQmlJSCodeGenerator::generate_CmpNeInt(int lhsConst) INJECT_TRACE_INFO(generate_CmpNeInt); generateEqualityOperation( - m_typeResolver->globalType(m_typeResolver->int32Type()), QString::number(lhsConst), - u"equals"_s, true); + global(m_typeResolver->int32Type()), QString::number(lhsConst), u"equals"_s, true); } void QQmlJSCodeGenerator::generate_CmpEq(int lhs) @@ -3056,8 +3056,8 @@ void QQmlJSCodeGenerator::generate_As(int lhs) // If the original output is a conversion, we're supposed to check for the contained // type and if it doesn't match, set the result to null or undefined. - const QQmlJSRegisterContent originalContent = m_typeResolver->original(outputContent); - const QQmlJSScope::ConstPtr target = originalContent.storedType()->isReferenceType() + const QQmlJSRegisterContent originalContent = original(outputContent); + const QQmlJSScope::ConstPtr target = originalContent.containedType()->isReferenceType() ? m_typeResolver->containedType(originalContent) : m_typeResolver->extractNonVoidFromOptionalType(originalContent); @@ -3095,14 +3095,13 @@ void QQmlJSCodeGenerator::generate_As(int lhs) || registerIsStoredIn(inputContent, m_typeResolver->jsPrimitiveType())) { const auto source = m_typeResolver->extractNonVoidFromOptionalType( - m_typeResolver->original(inputContent)); + original(inputContent)); if (source && m_typeResolver->equals(source, target)) { m_body += input + u".metaType() == "_s + metaType(target) + u" ? " + conversion(inputContent, outputContent, input) + u" : " + conversion( - m_typeResolver->globalType(m_typeResolver->voidType()), - outputContent, QString()); + global(m_typeResolver->voidType()), outputContent, QString()); m_body += u";\n"_s; return; } @@ -3244,7 +3243,7 @@ void QQmlJSCodeGenerator::generate_Exp(int lhs) Q_ASSERT(m_error->isValid() || !lhsString.isEmpty()); Q_ASSERT(m_error->isValid() || !rhsString.isEmpty()); - const QQmlJSRegisterContent originalOut = m_typeResolver->original(m_state.accumulatorOut()); + const QQmlJSRegisterContent originalOut = original(m_state.accumulatorOut()); m_body += m_state.accumulatorVariableOut + u" = "_s; m_body += conversion( originalOut, m_state.accumulatorOut(), @@ -3412,20 +3411,20 @@ void QQmlJSCodeGenerator::generateEqualityOperation( const auto retrieveOriginal = [this](const QQmlJSRegisterContent &content) { const auto contained = m_typeResolver->containedType(content); - const auto original = m_typeResolver->original(content); - const auto containedOriginal = m_typeResolver->containedType(original); + const auto originalContent = original(content); + const auto containedOriginal = m_typeResolver->containedType(originalContent); if (m_typeResolver->equals( - m_typeResolver->genericType(containedOriginal), original.storedType())) { + m_typeResolver->genericType(containedOriginal), originalContent.storedType())) { // The original type doesn't need any wrapping. - return original; + return originalContent; } else if (m_typeResolver->equals(contained, containedOriginal)) { - if (original.isConversion()) { + if (originalContent.isConversion()) { // The original conversion origins are more accurate - return original.storedIn(content.storedType()); + return originalContent.storedIn(content.storedType()); } } else if (m_typeResolver->canHold(contained, containedOriginal)) { - return original.storedIn(content.storedType()); + return originalContent.storedIn(content.storedType()); } return content; @@ -3599,7 +3598,7 @@ void QQmlJSCodeGenerator::generateCompareOperation(int lhs, const QString &cppOp const auto lhsType = registerType(lhs); const QQmlJSScope::ConstPtr compareType = m_typeResolver->isNumeric(lhsType) && m_typeResolver->isNumeric(m_state.accumulatorIn()) - ? m_typeResolver->merge(lhsType, m_state.accumulatorIn()).storedType() + ? m_typeResolver->merge(lhsType.storedType(), m_state.accumulatorIn().storedType()) : m_typeResolver->jsPrimitiveType(); m_body += conversion( @@ -3638,7 +3637,7 @@ void QQmlJSCodeGenerator::generateArithmeticOperation( Q_ASSERT(m_error->isValid() || !lhs.isEmpty()); Q_ASSERT(m_error->isValid() || !rhs.isEmpty()); - const QQmlJSRegisterContent originalOut = m_typeResolver->original(m_state.accumulatorOut()); + const QQmlJSRegisterContent originalOut = original(m_state.accumulatorOut()); m_body += m_state.accumulatorVariableOut; m_body += u" = "_s; const QString explicitCast @@ -3656,7 +3655,7 @@ void QQmlJSCodeGenerator::generateArithmeticConstOperation(int rhsConst, const Q generateArithmeticOperation( conversion(m_state.accumulatorIn(), m_state.readAccumulator(), consumedAccumulatorVariableIn()), - conversion(m_typeResolver->globalType(m_typeResolver->int32Type()), + conversion(global(m_typeResolver->int32Type()), m_state.readAccumulator(), QString::number(rhsConst)), cppOperator); } @@ -3664,7 +3663,7 @@ void QQmlJSCodeGenerator::generateArithmeticConstOperation(int rhsConst, const Q void QQmlJSCodeGenerator::generateUnaryOperation(const QString &cppOperator) { const auto var = conversion(m_state.accumulatorIn(), - m_typeResolver->original(m_state.readAccumulator()), + original(m_state.readAccumulator()), consumedAccumulatorVariableIn()); if (var == m_state.accumulatorVariableOut) { @@ -3672,8 +3671,8 @@ void QQmlJSCodeGenerator::generateUnaryOperation(const QString &cppOperator) return; } - const auto original = m_typeResolver->original(m_state.accumulatorOut()); - if (m_state.accumulatorOut() == original) { + const auto originalResult = original(m_state.accumulatorOut()); + if (m_state.accumulatorOut() == originalResult) { m_body += m_state.accumulatorVariableOut + u" = "_s + var + u";\n"_s; m_body += m_state.accumulatorVariableOut + u" = "_s + cppOperator + m_state.accumulatorVariableOut + u";\n"_s; @@ -3681,7 +3680,7 @@ void QQmlJSCodeGenerator::generateUnaryOperation(const QString &cppOperator) } m_body += m_state.accumulatorVariableOut + u" = "_s + conversion( - original, m_state.accumulatorOut(), cppOperator + var) + u";\n"_s; + originalResult, m_state.accumulatorOut(), cppOperator + var) + u";\n"_s; } void QQmlJSCodeGenerator::generateInPlaceOperation(const QString &cppOperator) @@ -3699,8 +3698,8 @@ void QQmlJSCodeGenerator::generateInPlaceOperation(const QString &cppOperator) const QString var = conversion(m_state.accumulatorIn(), m_state.readAccumulator(), consumedAccumulatorVariableIn()); - const auto original = m_typeResolver->original(m_state.accumulatorOut()); - if (m_state.accumulatorOut() == original) { + const auto originalResult = original(m_state.accumulatorOut()); + if (m_state.accumulatorOut() == originalResult) { m_body += m_state.accumulatorVariableOut + u" = "_s + var + u";\n"_s; m_body += cppOperator + m_state.accumulatorVariableOut + u";\n"_s; return; @@ -3709,7 +3708,7 @@ void QQmlJSCodeGenerator::generateInPlaceOperation(const QString &cppOperator) m_body += u"{\n"_s; m_body += u"auto converted = "_s + var + u";\n"_s; m_body += m_state.accumulatorVariableOut + u" = "_s + conversion( - original, m_state.accumulatorOut(), u'(' + originalResult, m_state.accumulatorOut(), u'(' + cppOperator + u"converted)"_s) + u";\n"_s; m_body += u"}\n"_s; } @@ -4024,7 +4023,7 @@ QString QQmlJSCodeGenerator::convertStored( return variable; const auto isBoolOrNumber = [&](const QQmlJSScope::ConstPtr &type) { - return m_typeResolver->isNumeric(m_typeResolver->globalType(type)) + return m_typeResolver->isNumeric(type) || m_typeResolver->equals(type, m_typeResolver->boolType()) || type->scopeType() == QQmlSA::ScopeType::EnumScope; }; @@ -4259,9 +4258,7 @@ QString QQmlJSCodeGenerator::convertContained(const QQmlJSRegisterContent &from, input = variable; argPointer = contentPointer(from, u"arg"_s); } else { - const QQmlJSRegisterContent argument - = m_typeResolver->globalType(argumentType) - .storedIn(m_typeResolver->genericType(argumentType)); + const QQmlJSRegisterContent argument = global(argumentType); input = conversion(from, argument, variable); argPointer = contentPointer(argument, u"arg"_s); } @@ -4274,7 +4271,7 @@ QString QQmlJSCodeGenerator::convertContained(const QQmlJSRegisterContent &from, + u", "_s + argPointer + u"); }()"_s; } - const auto originalFrom = m_typeResolver->original(from); + const auto originalFrom = original(from); const auto containedOriginalFrom = m_typeResolver->containedType(originalFrom); if (!m_typeResolver->equals(containedFrom, containedOriginalFrom) && m_typeResolver->canHold(containedFrom, containedOriginalFrom)) { @@ -4320,7 +4317,7 @@ QQmlJSCodeGenerator::AccumulatorConverter::AccumulatorConverter(QQmlJSCodeGenera const bool storable = isTypeStorable(resolver, origStored); generator->m_state.accumulatorVariableOut = storable ? u"retrieved"_s : QString(); - generator->m_state.setRegister(Accumulator, resolver->original(accumulatorOut)); + generator->m_state.setRegister(Accumulator, generator->original(accumulatorOut)); generator->m_body += u"{\n"_s; if (storable) { generator->m_body += origStored->augmentedInternalName() + u' ' diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h index 50c3923760..86ce2ff6d9 100644 --- a/src/qmlcompiler/qqmljscodegenerator_p.h +++ b/src/qmlcompiler/qqmljscodegenerator_p.h @@ -230,7 +230,9 @@ protected: // we can convert by stored type. return convertStored(from, to.storedType(), variable); } else { - return convertContained(m_typeResolver->globalType(from), to, variable); + return convertContained( + m_typeResolver->globalType(from).storedIn(m_typeResolver->storedType(from)), + to, variable); } } @@ -335,6 +337,22 @@ private: const QQmlJSScope::ConstPtr &required, const QQmlJSRegisterContent &actual, const QString &variable, const QString &errorMessage); + QQmlJSRegisterContent original(const QQmlJSRegisterContent &tracked) + { + const QQmlJSRegisterContent restored = m_typeResolver->original(tracked); + return restored.storedIn(m_typeResolver->originalType(tracked.storedType())); + } + + QQmlJSRegisterContent global(const QQmlJSScope::ConstPtr &contained) + { + return m_typeResolver->globalType(contained).storedIn(contained); + } + + QQmlJSRegisterContent builtin(const QQmlJSScope::ConstPtr &contained) + { + return m_typeResolver->builtinType(contained).storedIn(contained); + } + bool registerIsStoredIn( const QQmlJSRegisterContent ®, const QQmlJSScope::ConstPtr &type) const { diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp index 908ef4fe79..2fd893ca2a 100644 --- a/src/qmlcompiler/qqmljscompiler.cpp +++ b/src/qmlcompiler/qqmljscompiler.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -775,8 +776,13 @@ QQmlJSAotFunction QQmlJSAotCompiler::doCompile( if (error->isValid()) return compileError(); + QQmlJSStorageInitializer initializer( + m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations); + passResult = initializer.run(function, error); + // Generalize all arguments, registers, and the return type. - QQmlJSStorageGeneralizer generalizer(m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations); + QQmlJSStorageGeneralizer generalizer( + m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations); passResult = generalizer.run(function, error); if (error->isValid()) return compileError(); diff --git a/src/qmlcompiler/qqmljslintercodegen.cpp b/src/qmlcompiler/qqmljslintercodegen.cpp index 175f7ee1e0..60fc9cb5ad 100644 --- a/src/qmlcompiler/qqmljslintercodegen.cpp +++ b/src/qmlcompiler/qqmljslintercodegen.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -91,6 +92,12 @@ bool QQmlJSLinterCodegen::analyzeFunction(const QV4::Compiler::Context *context, shadowCheck.run(function, error); } + if (!error->isValid()) { + QQmlJSStorageInitializer initializer(m_unitGenerator, &m_typeResolver, m_logger, + basicBlocks, annotations); + initializer.run(function, error); + } + if (!error->isValid()) { QQmlJSStorageGeneralizer generalizer(m_unitGenerator, &m_typeResolver, m_logger, basicBlocks, annotations); diff --git a/src/qmlcompiler/qqmljsoptimizations.cpp b/src/qmlcompiler/qqmljsoptimizations.cpp index 000d255251..2f55980155 100644 --- a/src/qmlcompiler/qqmljsoptimizations.cpp +++ b/src/qmlcompiler/qqmljsoptimizations.cpp @@ -84,11 +84,7 @@ void QQmlJSOptimizations::populateReaderLocations() it->second.changedRegister = QQmlJSRegisterContent(); } else { // void the output, rather than deleting it. We still need its variant. - bool adjusted = m_typeResolver->adjustTrackedType( - it->second.changedRegister.storedType(), m_typeResolver->voidType()); - Q_ASSERT(adjusted); // Can always convert to void - - adjusted = m_typeResolver->adjustTrackedType( + const bool adjusted = m_typeResolver->adjustTrackedType( m_typeResolver->containedType(it->second.changedRegister), m_typeResolver->voidType()); Q_ASSERT(adjusted); // Can always convert to void @@ -315,13 +311,6 @@ void QQmlJSOptimizations::adjustTypes() } }; - const auto transformRegister = [&](const QQmlJSRegisterContent &content) { - const QQmlJSScope::ConstPtr conversion - = m_typeResolver->storedType(m_typeResolver->containedType(content)); - if (!m_typeResolver->adjustTrackedType(content.storedType(), conversion)) - setError(adjustErrorMessage(content.storedType(), conversion)); - }; - // Handle the array definitions first. // Changing the array type changes the expected element types. auto adjustArray = [&](int instructionOffset, int mode) { @@ -354,9 +343,6 @@ void QQmlJSOptimizations::adjustTypes() || !m_typeResolver->equals(contained, m_typeResolver->realType())) { if (!m_typeResolver->adjustTrackedType(contained, valueType)) setError(adjustErrorMessage(contained, valueType)); - - // We still need to adjust the stored type, too. - transformRegister(content); } } @@ -412,9 +398,6 @@ void QQmlJSOptimizations::adjustTypes() const QQmlJSScope::ConstPtr contained = m_typeResolver->containedType(content); if (!m_typeResolver->adjustTrackedType(contained, propType)) setError(adjustErrorMessage(contained, propType)); - - // We still need to adjust the stored type, too. - transformRegister(content); } // The others cannot be adjusted. We don't know their names, yet. @@ -456,9 +439,6 @@ void QQmlJSOptimizations::adjustTypes() NewVirtualRegisters newRegisters; for (auto i = m_annotations.begin(), iEnd = m_annotations.end(); i != iEnd; ++i) { - if (i->second.changedRegisterIndex != InvalidRegister) - transformRegister(i->second.changedRegister); - for (auto conversion = i->second.typeConversions.begin(), conversionEnd = i->second.typeConversions.end(); conversion != conversionEnd; ++conversion) { @@ -475,7 +455,6 @@ void QQmlJSOptimizations::adjustTypes() if (!m_typeResolver->adjustTrackedType(conversionResult, newResult)) setError(adjustErrorMessage(conversionResult, newResult)); } - transformRegister(content); newRegisters.appendOrdered(conversion); } i->second.typeConversions = newRegisters.take(); diff --git a/src/qmlcompiler/qqmljsregistercontent.cpp b/src/qmlcompiler/qqmljsregistercontent.cpp index fd197bc54f..b7a3b9a79f 100644 --- a/src/qmlcompiler/qqmljsregistercontent.cpp +++ b/src/qmlcompiler/qqmljsregistercontent.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "qqmljsregistercontent_p.h" -#include "qqmljstyperesolver_p.h" QT_BEGIN_NAMESPACE @@ -121,82 +120,59 @@ QQmlJSScope::ConstPtr QQmlJSRegisterContent::containedType() const Q_UNREACHABLE_RETURN({}); } -QQmlJSRegisterContent QQmlJSRegisterContent::create(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSScope::ConstPtr &type, - int resultLookupIndex, - QQmlJSRegisterContent::ContentVariant variant, - const QQmlJSScope::ConstPtr &scope) +QQmlJSRegisterContent QQmlJSRegisterContent::create( + const QQmlJSScope::ConstPtr &type, int resultLookupIndex, + QQmlJSRegisterContent::ContentVariant variant, const QQmlJSScope::ConstPtr &scope) { - QQmlJSRegisterContent result(storedType, scope, variant); + QQmlJSRegisterContent result(scope, variant); result.m_content = std::make_pair(type, resultLookupIndex); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSMetaProperty &property, - int baseLookupIndex, int resultLookupIndex, - QQmlJSRegisterContent::ContentVariant variant, - const QQmlJSScope::ConstPtr &scope) +QQmlJSRegisterContent QQmlJSRegisterContent::create( + const QQmlJSMetaProperty &property, int baseLookupIndex, int resultLookupIndex, + QQmlJSRegisterContent::ContentVariant variant, const QQmlJSScope::ConstPtr &scope) { - QQmlJSRegisterContent result(storedType, scope, variant); + QQmlJSRegisterContent result(scope, variant); result.m_content = PropertyLookup { property, baseLookupIndex, resultLookupIndex}; return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSMetaEnum &enumeration, - const QString &enumMember, - QQmlJSRegisterContent::ContentVariant variant, - const QQmlJSScope::ConstPtr &scope) +QQmlJSRegisterContent QQmlJSRegisterContent::create( + const QQmlJSMetaEnum &enumeration, const QString &enumMember, + QQmlJSRegisterContent::ContentVariant variant, const QQmlJSScope::ConstPtr &scope) { - QQmlJSRegisterContent result(storedType, scope, variant); + QQmlJSRegisterContent result(scope, variant); result.m_content = std::make_pair(enumeration, enumMember); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create(const QQmlJSScope::ConstPtr &storedType, - const QList &methods, - QQmlJSRegisterContent::ContentVariant variant, - const QQmlJSScope::ConstPtr &scope) +QQmlJSRegisterContent QQmlJSRegisterContent::create( + const QList &methods, const QQmlJSScope::ConstPtr &methodType, + QQmlJSRegisterContent::ContentVariant variant, const QQmlJSScope::ConstPtr &scope) { // Methods can only be stored in QJSValue. - Q_ASSERT(storedType->internalName() == u"QJSValue"_s); - QQmlJSRegisterContent result(storedType, scope, variant); - result.m_content = std::make_pair(methods, storedType); + Q_ASSERT(methodType->internalName() == u"QJSValue"_s); + QQmlJSRegisterContent result(scope, variant); + result.m_content = std::make_pair(methods, methodType); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create(const QQmlJSScope::ConstPtr &storedType, - uint importNamespaceStringId, - QQmlJSRegisterContent::ContentVariant variant, - const QQmlJSScope::ConstPtr &scope) +QQmlJSRegisterContent QQmlJSRegisterContent::create( + uint importNamespaceStringId, const QQmlJSScope::ConstPtr &importNamespaceType, + QQmlJSRegisterContent::ContentVariant variant, const QQmlJSScope::ConstPtr &scope) { - QQmlJSRegisterContent result(storedType, scope, variant); - switch (variant) { - case ScopeModulePrefix: - // We don't store scope module prefixes - result.m_content = std::make_pair(importNamespaceStringId, storedType); - break; - case ObjectModulePrefix: - // We need to pass the original object through. - result.m_content = std::make_pair(importNamespaceStringId, scope); - break; - default: - Q_UNREACHABLE(); - break; - } - + QQmlJSRegisterContent result(scope, variant); + result.m_content = std::make_pair(importNamespaceStringId, importNamespaceType); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create(const QQmlJSScope::ConstPtr &storedType, - const QList &origins, - const QQmlJSScope::ConstPtr &conversion, - const QQmlJSScope::ConstPtr &conversionScope, - ContentVariant variant, - const QQmlJSScope::ConstPtr &scope) +QQmlJSRegisterContent QQmlJSRegisterContent::create( + const QList &origins, const QQmlJSScope::ConstPtr &conversion, + const QQmlJSScope::ConstPtr &conversionScope, ContentVariant variant, + const QQmlJSScope::ConstPtr &scope) { - QQmlJSRegisterContent result(storedType, scope, variant); + QQmlJSRegisterContent result(scope, variant); result.m_content = ConvertedTypes { origins, conversion, conversionScope }; return result; } diff --git a/src/qmlcompiler/qqmljsregistercontent_p.h b/src/qmlcompiler/qqmljsregistercontent_p.h index be171f7308..f1d3cc70d6 100644 --- a/src/qmlcompiler/qqmljsregistercontent_p.h +++ b/src/qmlcompiler/qqmljsregistercontent_p.h @@ -186,33 +186,30 @@ public: Q_UNREACHABLE_RETURN(seed); } - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSScope::ConstPtr &type, + static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &type, int resultLookupIndex, ContentVariant variant, const QQmlJSScope::ConstPtr &scope = {}); - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSMetaProperty &property, + static QQmlJSRegisterContent create(const QQmlJSMetaProperty &property, int baseLookupIndex, int resultLookupIndex, ContentVariant variant, const QQmlJSScope::ConstPtr &scope); - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSMetaEnum &enumeration, + static QQmlJSRegisterContent create(const QQmlJSMetaEnum &enumeration, const QString &enumMember, ContentVariant variant, const QQmlJSScope::ConstPtr &scope); - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, - const QList &methods, + static QQmlJSRegisterContent create(const QList &methods, + const QQmlJSScope::ConstPtr &methodType, ContentVariant variant, const QQmlJSScope::ConstPtr &scope); - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, - uint importNamespaceStringId, ContentVariant variant, + static QQmlJSRegisterContent create(uint importNamespaceStringId, + const QQmlJSScope::ConstPtr &importNamespaceType, + ContentVariant variant, const QQmlJSScope::ConstPtr &scope = {}); - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, - const QList &origins, + static QQmlJSRegisterContent create(const QList &origins, const QQmlJSScope::ConstPtr &conversion, const QQmlJSScope::ConstPtr &conversionScope, ContentVariant variant, @@ -292,9 +289,8 @@ private: ConvertedTypes >; - QQmlJSRegisterContent(const QQmlJSScope::ConstPtr &storedType, - const QQmlJSScope::ConstPtr &scope, ContentVariant variant) - : m_storedType(storedType), m_scope(scope), m_variant(variant) + QQmlJSRegisterContent(const QQmlJSScope::ConstPtr &scope, ContentVariant variant) + : m_scope(scope), m_variant(variant) { } diff --git a/src/qmlcompiler/qqmljsshadowcheck.cpp b/src/qmlcompiler/qqmljsshadowcheck.cpp index b12074c9de..c226d3dead 100644 --- a/src/qmlcompiler/qqmljsshadowcheck.cpp +++ b/src/qmlcompiler/qqmljsshadowcheck.cpp @@ -192,8 +192,6 @@ QQmlJSShadowCheck::Shadowability QQmlJSShadowCheck::checkShadowing( InstructionAnnotation ¤tAnnotation = m_annotations[currentInstructionOffset()]; if (currentAnnotation.changedRegisterIndex != InvalidRegister) { - m_typeResolver->adjustOriginalType( - currentAnnotation.changedRegister.storedType(), varType); m_typeResolver->adjustOriginalType( m_typeResolver->containedType(currentAnnotation.changedRegister), varType); m_adjustedTypes.insert(currentAnnotation.changedRegister); diff --git a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp index 937c35ddcd..3ba709b21f 100644 --- a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp +++ b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp @@ -22,6 +22,7 @@ QT_BEGIN_NAMESPACE QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageGeneralizer::run(Function *function, QQmlJS::DiagnosticMessage *error) { + m_function = function; m_error = error; if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) { diff --git a/src/qmlcompiler/qqmljsstorageinitializer.cpp b/src/qmlcompiler/qqmljsstorageinitializer.cpp new file mode 100644 index 0000000000..b0f7d1a49f --- /dev/null +++ b/src/qmlcompiler/qqmljsstorageinitializer.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "qqmljsstorageinitializer_p.h" + +QT_BEGIN_NAMESPACE + +/*! + * \internal + * \class QQmlJSStorageInitializer + * + * The QQmlJSStorageInitializer is a compile pass that initializes the storage + * for all register contents. + * + * QQmlJSStorageInitializer does not have to use the byte code at all but + * operates only on the annotations and the function description. + */ + +QQmlJSCompilePass::BlocksAndAnnotations +QQmlJSStorageInitializer::run(Function *function, QQmlJS::DiagnosticMessage *error) +{ + m_function = function; + m_error = error; + + if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) { + if (const QQmlJSScope::ConstPtr stored + = m_typeResolver->storedType(returnType.containedType())) { + returnType = returnType.storedIn(m_typeResolver->trackedType(stored)); + } else { + setError(QStringLiteral("Cannot store the return type %1.") + .arg(returnType.containedType()->internalName())); + return {}; + } + } + + const auto storeRegister = [&](QQmlJSRegisterContent &content) { + if (!content.isValid()) + return; + + const QQmlJSScope::ConstPtr original + = m_typeResolver->originalType(content.containedType()); + const QQmlJSScope::ConstPtr originalStored = m_typeResolver->storedType(original); + const QQmlJSScope::ConstPtr originalTracked = m_typeResolver->trackedType(originalStored); + content = content.storedIn(originalTracked); + + const QQmlJSScope::ConstPtr adjustedStored + = m_typeResolver->storedType(content.containedType()); + + if (!m_typeResolver->adjustTrackedType(originalTracked, adjustedStored)) { + setError(QStringLiteral("Cannot adjust stored type for %1.") + .arg(content.containedType()->internalName())); + } + }; + + const auto storeRegisters = [&](VirtualRegisters ®isters) { + for (auto j = registers.begin(), jEnd = registers.end(); j != jEnd; ++j) + storeRegister(j.value().content); + }; + + storeRegister(function->qmlScope); + + for (QQmlJSRegisterContent &argument : function->argumentTypes) { + Q_ASSERT(argument.isValid()); + storeRegister(argument); + } + + for (QQmlJSRegisterContent &argument : function->registerTypes) { + Q_ASSERT(argument.isValid()); + storeRegister(argument); + } + + for (auto i = m_annotations.begin(), iEnd = m_annotations.end(); i != iEnd; ++i) { + storeRegister(i->second.changedRegister); + storeRegisters(i->second.typeConversions); + storeRegisters(i->second.readRegisters); + } + + return { std::move(m_basicBlocks), std::move(m_annotations) }; +} + +QT_END_NAMESPACE diff --git a/src/qmlcompiler/qqmljsstorageinitializer_p.h b/src/qmlcompiler/qqmljsstorageinitializer_p.h new file mode 100644 index 0000000000..0644807543 --- /dev/null +++ b/src/qmlcompiler/qqmljsstorageinitializer_p.h @@ -0,0 +1,40 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef QQMLJSSTORAGEINITIALIZER_P_H +#define QQMLJSSTORAGEINITIALIZER_P_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 + +QT_BEGIN_NAMESPACE + +class Q_QMLCOMPILER_EXPORT QQmlJSStorageInitializer : public QQmlJSCompilePass +{ +public: + QQmlJSStorageInitializer(const QV4::Compiler::JSUnitGenerator *jsUnitGenerator, + const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger, + BasicBlocks basicBlocks, InstructionAnnotations annotations) + : QQmlJSCompilePass(jsUnitGenerator, typeResolver, logger, basicBlocks, annotations) + {} + + BlocksAndAnnotations run(Function *function, QQmlJS::DiagnosticMessage *error); + +protected: + // We don't have to use the byte code here. We only transform the instruction annotations. + Verdict startInstruction(QV4::Moth::Instr::Type) override { return SkipInstruction; } + void endInstruction(QV4::Moth::Instr::Type) override {} +}; + +QT_END_NAMESPACE + +#endif // QQMLJSSTORAGEINITIALIZER_P_H diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 502890e786..8366fa023a 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -575,7 +575,7 @@ void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index) if (!m_state.accumulatorOut().isValid() && m_typeResolver->isPrefix(name)) { const QQmlJSRegisterContent inType = m_typeResolver->globalType(qmlScope); setAccumulator(QQmlJSRegisterContent::create( - m_typeResolver->voidType(), nameIndex, QQmlJSRegisterContent::ScopeModulePrefix, + nameIndex, m_typeResolver->voidType(), QQmlJSRegisterContent::ScopeModulePrefix, m_typeResolver->containedType(inType))); return; } @@ -833,8 +833,8 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName, Q_ASSERT(m_state.accumulatorIn().isValid()); addReadAccumulator(m_state.accumulatorIn()); setAccumulator(QQmlJSRegisterContent::create( - m_state.accumulatorIn().storedType(), m_jsUnitGenerator->getStringId(propertyName), + m_state.accumulatorIn().containedType(), QQmlJSRegisterContent::ObjectModulePrefix, m_typeResolver->containedType(m_state.accumulatorIn()))); return; @@ -929,7 +929,7 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName, prop.setType(m_typeResolver->realType()); setAccumulator( QQmlJSRegisterContent::create( - m_typeResolver->realType(), prop, m_state.accumulatorIn().resultLookupIndex(), lookupIndex, + prop, m_state.accumulatorIn().resultLookupIndex(), lookupIndex, QQmlJSRegisterContent::GenericObjectProperty, mathObject) ); @@ -1058,7 +1058,7 @@ void QQmlJSTypePropagator::generate_StoreProperty(int nameIndex, int base) const QQmlJSScope::ConstPtr varType = m_typeResolver->varType(); const QQmlJSRegisterContent readType = m_typeResolver->canHoldUndefined(m_state.accumulatorIn()) - ? property.storedIn(varType).castTo(varType) + ? property.castTo(varType) : std::move(property); addReadAccumulator(readType); addReadRegister(base, callBase); diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 8d987d5130..30b83a2424 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -406,35 +406,35 @@ QQmlJSRegisterContent QQmlJSTypeResolver::transformed( { if (origin.isType()) { return QQmlJSRegisterContent::create( - (this->*op)(origin.storedType()), (this->*op)(origin.type()), - origin.resultLookupIndex(), origin.variant(), (this->*op)(origin.scopeType())); + (this->*op)(origin.type()), origin.resultLookupIndex(), origin.variant(), + (this->*op)(origin.scopeType())); } if (origin.isProperty()) { QQmlJSMetaProperty prop = origin.property(); prop.setType((this->*op)(prop.type())); return QQmlJSRegisterContent::create( - (this->*op)(origin.storedType()), prop, origin.baseLookupIndex(), - origin.resultLookupIndex(), origin.variant(), (this->*op)(origin.scopeType())); + prop, origin.baseLookupIndex(), origin.resultLookupIndex(), origin.variant(), + (this->*op)(origin.scopeType())); } if (origin.isEnumeration()) { QQmlJSMetaEnum enumeration = origin.enumeration(); enumeration.setType((this->*op)(enumeration.type())); return QQmlJSRegisterContent::create( - (this->*op)(origin.storedType()), enumeration, origin.enumMember(), - origin.variant(), (this->*op)(origin.scopeType())); + enumeration, origin.enumMember(), origin.variant(), + (this->*op)(origin.scopeType())); } if (origin.isMethod()) { return QQmlJSRegisterContent::create( - (this->*op)(origin.storedType()), origin.method(), origin.variant(), + origin.method(), (this->*op)(origin.methodType()), origin.variant(), (this->*op)(origin.scopeType())); } if (origin.isImportNamespace()) { return QQmlJSRegisterContent::create( - (this->*op)(origin.storedType()), origin.importNamespace(), + origin.importNamespace(), (this->*op)(origin.importNamespaceType()), origin.variant(), (this->*op)(origin.scopeType())); } @@ -453,7 +453,6 @@ QQmlJSRegisterContent QQmlJSTypeResolver::transformed( } return QQmlJSRegisterContent::create( - (this->*op)(origin.storedType()), transformedOrigins, (this->*op)(origin.conversionResult()), (this->*op)(origin.conversionResultScope()), @@ -495,13 +494,13 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName( if (type->isSingleton()) { return QQmlJSRegisterContent::create( - storedType(type), type, QQmlJSRegisterContent::InvalidLookupIndex, + type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Singleton, scopeType); } if (type->isScript()) { return QQmlJSRegisterContent::create( - storedType(type), type, QQmlJSRegisterContent::InvalidLookupIndex, + type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Script, scopeType); } @@ -521,7 +520,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName( // mode, we will figure this out using the scope type and access any enums of the // plain type directly. In indirect mode, we can use enum lookups. return QQmlJSRegisterContent::create( - storedType(attached), attached, QQmlJSRegisterContent::InvalidLookupIndex, + attached, QQmlJSRegisterContent::InvalidLookupIndex, hasObjectModulePrefix ? QQmlJSRegisterContent::ObjectAttached : QQmlJSRegisterContent::ScopeAttached, type); @@ -536,13 +535,13 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName( // Store it as QMetaObject. // This only works with namespaces and object types. return QQmlJSRegisterContent::create( - metaObjectType(), metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex, + metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::MetaType, type); case QQmlJSScope::AccessSemantics::Sequence: case QQmlJSScope::AccessSemantics::Value: if (canAddressValueTypes()) { return QQmlJSRegisterContent::create( - metaObjectType(), metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex, + metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::MetaType, type); } // Else this is not actually a type reference. You cannot get the metaobject @@ -746,7 +745,6 @@ QQmlJSRegisterContent QQmlJSTypeResolver::merge(const QQmlJSRegisterContent &a, origins.erase(erase, origins.end()); return QQmlJSRegisterContent::create( - merge(a.storedType(), b.storedType()), origins, merge(containedType(a), containedType(b)), merge(aResultScope, bResultScope), @@ -988,13 +986,13 @@ QQmlJSRegisterContent QQmlJSTypeResolver::builtinType(const QQmlJSScope::ConstPt { Q_ASSERT(storedType(type) == type); return QQmlJSRegisterContent::create( - type, type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Builtin); + type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Builtin); } QQmlJSRegisterContent QQmlJSTypeResolver::globalType(const QQmlJSScope::ConstPtr &type) const { return QQmlJSRegisterContent::create( - storedType(type), type, QQmlJSRegisterContent::InvalidLookupIndex, + type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Unknown); } @@ -1152,8 +1150,8 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent { const QQmlJSScope::ConstPtr contained = containedType(scope); if (QQmlJSScope::ConstPtr identified = m_objectsById.scope(name, contained, options)) { - return QQmlJSRegisterContent::create(storedType(identified), identified, lookupIndex, - QQmlJSRegisterContent::ObjectById, contained); + return QQmlJSRegisterContent::create( + identified, lookupIndex, QQmlJSRegisterContent::ObjectById, contained); } if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) { @@ -1170,8 +1168,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent prop.setType(resolveParentProperty(name, base, prop.type())); result = QQmlJSRegisterContent::create( - storedType(prop.type()), prop, - QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, + prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, scopeContentVariant(mode, false), contained); return true; } @@ -1187,8 +1184,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent if (methods.isEmpty()) return false; result = QQmlJSRegisterContent::create( - jsValueType(), methods, scopeContentVariant(mode, true), - contained); + methods, jsValueType(), scopeContentVariant(mode, true), contained); return true; } @@ -1206,13 +1202,12 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent if (m_jsGlobalObject->hasProperty(name)) { return QQmlJSRegisterContent::create( - jsValueType(), m_jsGlobalObject->property(name), - QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, - QQmlJSRegisterContent::JavaScriptGlobal, m_jsGlobalObject); + m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex, + lookupIndex, QQmlJSRegisterContent::JavaScriptGlobal, m_jsGlobalObject); } else if (m_jsGlobalObject->hasMethod(name)) { - return QQmlJSRegisterContent::create(jsValueType(), m_jsGlobalObject->methods(name), - QQmlJSRegisterContent::JavaScriptGlobal, - m_jsGlobalObject); + return QQmlJSRegisterContent::create( + m_jsGlobalObject->methods(name), jsValueType(), + QQmlJSRegisterContent::JavaScriptGlobal, m_jsGlobalObject); } return {}; @@ -1245,7 +1240,7 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS for (const auto &enumeration : enums) { if ((enumeration.isScoped() || enumeration.isQml()) && enumeration.name() == name) { *result = QQmlJSRegisterContent::create( - storedType(enumeration.type()), enumeration, QString(), + enumeration, QString(), inExtension ? QQmlJSRegisterContent::ExtensionObjectEnum : QQmlJSRegisterContent::ObjectEnum, scope); @@ -1254,7 +1249,7 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS if (!enumeration.isScoped() && enumeration.hasKey(name)) { *result = QQmlJSRegisterContent::create( - storedType(enumeration.type()), enumeration, name, + enumeration, name, inExtension ? QQmlJSRegisterContent::ExtensionObjectEnum : QQmlJSRegisterContent::ObjectEnum, scope); @@ -1523,7 +1518,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::lengthProperty( prop.setType(sizeType()); prop.setIsWritable(isWritable); return QQmlJSRegisterContent::create( - sizeType(), prop, QQmlJSRegisterContent::InvalidLookupIndex, + prop, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Builtin, scope); } @@ -1544,7 +1539,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setType(varType()); prop.setIsWritable(true); return QQmlJSRegisterContent::create( - varType(), prop, baseLookupIndex, resultLookupIndex, + prop, baseLookupIndex, resultLookupIndex, QQmlJSRegisterContent::GenericObjectProperty, type); } @@ -1555,7 +1550,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setType(jsValueType()); prop.setIsWritable(true); return QQmlJSRegisterContent::create( - jsValueType(), prop, baseLookupIndex, resultLookupIndex, + prop, baseLookupIndex, resultLookupIndex, QQmlJSRegisterContent::GenericObjectProperty, type); } @@ -1570,7 +1565,6 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( if (scope->hasOwnProperty(name)) { const auto prop = scope->ownProperty(name); result = QQmlJSRegisterContent::create( - storedType(prop.type()), prop, baseLookupIndex, resultLookupIndex, mode == QQmlJSScope::NotExtension ? QQmlJSRegisterContent::ObjectProperty @@ -1582,7 +1576,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( if (scope->hasOwnMethod(name)) { const auto methods = scope->ownMethods(name); result = QQmlJSRegisterContent::create( - jsValueType(), methods, + methods, jsValueType(), mode == QQmlJSScope::NotExtension ? QQmlJSRegisterContent::ObjectMethod : QQmlJSRegisterContent::ExtensionObjectMethod, @@ -1608,9 +1602,9 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setType(jsValueType()); prop.setIsWritable(!(ownIdentifier.value().isConst)); - return QQmlJSRegisterContent::create(jsValueType(), prop, baseLookupIndex, - resultLookupIndex, - QQmlJSRegisterContent::JavaScriptObject, scope); + return QQmlJSRegisterContent::create( + prop, baseLookupIndex, resultLookupIndex, + QQmlJSRegisterContent::JavaScriptObject, scope); } } @@ -1628,8 +1622,8 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( return {}; } else { return QQmlJSRegisterContent::create( - storedType(attached), attached, resultLookupIndex, - QQmlJSRegisterContent::ObjectAttached, attachedBase); + attached, resultLookupIndex, QQmlJSRegisterContent::ObjectAttached, + attachedBase); } } } @@ -1671,8 +1665,8 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( const auto enumeration = type.enumeration(); if (!type.enumMember().isEmpty() || !enumeration.hasKey(name)) return {}; - return QQmlJSRegisterContent::create(storedType(enumeration.type()), enumeration, name, - QQmlJSRegisterContent::ObjectEnum, type.scopeType()); + return QQmlJSRegisterContent::create( + enumeration, name, QQmlJSRegisterContent::ObjectEnum, type.scopeType()); } if (type.isMethod()) { QQmlJSMetaProperty prop; @@ -1681,7 +1675,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setType(jsValueType()); prop.setIsWritable(true); return QQmlJSRegisterContent::create( - jsValueType(), prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, + prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, QQmlJSRegisterContent::GenericObjectProperty, jsValueType()); } if (type.isImportNamespace()) { @@ -1770,7 +1764,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::valueType(const QQmlJSRegisterContent property.setType(value); return QQmlJSRegisterContent::create( - storedType(value), property, QQmlJSRegisterContent::InvalidLookupIndex, + property, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ListValue, scope); } @@ -1781,7 +1775,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::returnType( Q_ASSERT(variant == QQmlJSRegisterContent::MethodReturnValue || variant == QQmlJSRegisterContent::JavaScriptReturnValue); return QQmlJSRegisterContent::create( - storedType(type), type, QQmlJSRegisterContent::InvalidLookupIndex, variant, scope); + type, QQmlJSRegisterContent::InvalidLookupIndex, variant, scope); } QQmlJSRegisterContent QQmlJSTypeResolver::iteratorPointer( @@ -1803,7 +1797,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::iteratorPointer( prop.setTypeName(iteratorPointer->internalName()); prop.setType(iteratorPointer); return QQmlJSRegisterContent::create( - storedType(iteratorPointer), prop, lookupIndex, + prop, lookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ListIterator, listContained); } @@ -1868,20 +1862,20 @@ QQmlJSRegisterContent QQmlJSTypeResolver::convert( { if (from.isConversion()) { return QQmlJSRegisterContent::create( - to.storedType(), from.conversionOrigins(), containedType(to), + from.conversionOrigins(), containedType(to), to.scopeType() ? to.scopeType() : from.conversionResultScope(), from.variant(), from.scopeType()); } return QQmlJSRegisterContent::create( - to.storedType(), QList{containedType(from)}, + QList{containedType(from)}, containedType(to), to.scopeType(), from.variant(), from.scopeType()); } QQmlJSRegisterContent QQmlJSTypeResolver::cast( const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const { - return from.castTo(to).storedIn(storedType(to)); + return from.castTo(to); } QQmlJSScope::ConstPtr QQmlJSTypeResolver::comparableType(const QQmlJSScope::ConstPtr &type) const diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 02b0ea69d2..5ccdb7be75 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -1374,8 +1374,7 @@ void TestQmllint::compilerWarnings_data() QTest::newRow("shadowable") << QStringLiteral("shadowable.qml") - << Result { { Message {QStringLiteral( - "with type NotSoSimple (stored as QQuickItem) can be shadowed") } } } + << Result { { Message {QStringLiteral("with type NotSoSimple can be shadowed") } } } << true; QTest::newRow("tooFewParameters") << QStringLiteral("tooFewParams.qml") @@ -1411,20 +1410,20 @@ void TestQmllint::compilerWarnings_data() << QStringLiteral("returnTypeAnnotation_component.qml") << Result{ { { "Could not compile function comp: function without return type " "annotation returns (component in" }, - { "returnTypeAnnotation_component.qml)::c with type Comp (stored as " - "QQuickItem). This may prevent proper compilation to Cpp." } } } + { "returnTypeAnnotation_component.qml)::c with type Comp. " + "This may prevent proper compilation to Cpp." } } } << true; QTest::newRow("returnTypeAnnotation-enum") << QStringLiteral("returnTypeAnnotation_enum.qml") << Result{ { { "Could not compile function enumeration: function without return type " - "annotation returns QQuickText::HAlignment::AlignRight (stored as int). " + "annotation returns QQuickText::HAlignment::AlignRight. " "This may prevent proper compilation to Cpp." } } } << true; QTest::newRow("returnTypeAnnotation-method") << QStringLiteral("returnTypeAnnotation_method.qml") << Result{ { { "Could not compile function method: function without return type " "annotation returns (component in " }, // Don't check the build folder path - { "returnTypeAnnotation_method.qml)::f(...) (stored as QJSValue). This may " + { "returnTypeAnnotation_method.qml)::f(...). This may " "prevent proper compilation to Cpp." } } } << true; QTest::newRow("returnTypeAnnotation-property") diff --git a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp index 4dacc17f94..05e0b2870a 100644 --- a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp +++ b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp @@ -355,9 +355,9 @@ void tst_qqmljsscope::descriptiveNameOfNull() property.setPropertyName(u"foo"_s); property.setTypeName(u"baz"_s); QQmlJSRegisterContent unscoped = QQmlJSRegisterContent::create( - stored, property, QQmlJSRegisterContent::InvalidLookupIndex, + property, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeProperty, - QQmlJSScope::ConstPtr()); + QQmlJSScope::ConstPtr()).storedIn(stored); QCOMPARE(unscoped.descriptiveName(), u"(invalid type)::foo with type baz (stored as bar)"_s); }