aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/common/qqmljsdiagnosticmessage_p.h5
-rw-r--r--src/qmlcompiler/qqmljsbasicblocks_p.h5
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp29
-rw-r--r--src/qmlcompiler/qqmljscodegenerator_p.h6
-rw-r--r--src/qmlcompiler/qqmljscompilepass_p.h21
-rw-r--r--src/qmlcompiler/qqmljscompiler.cpp122
-rw-r--r--src/qmlcompiler/qqmljscompiler_p.h8
-rw-r--r--src/qmlcompiler/qqmljsfunctioninitializer.cpp36
-rw-r--r--src/qmlcompiler/qqmljsfunctioninitializer_p.h13
-rw-r--r--src/qmlcompiler/qqmljslintercodegen.cpp84
-rw-r--r--src/qmlcompiler/qqmljslintercodegen_p.h7
-rw-r--r--src/qmlcompiler/qqmljsoptimizations.cpp20
-rw-r--r--src/qmlcompiler/qqmljsoptimizations_p.h7
-rw-r--r--src/qmlcompiler/qqmljsshadowcheck.cpp6
-rw-r--r--src/qmlcompiler/qqmljsshadowcheck_p.h7
-rw-r--r--src/qmlcompiler/qqmljsstoragegeneralizer.cpp6
-rw-r--r--src/qmlcompiler/qqmljsstoragegeneralizer_p.h7
-rw-r--r--src/qmlcompiler/qqmljsstorageinitializer.cpp8
-rw-r--r--src/qmlcompiler/qqmljsstorageinitializer_p.h7
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp102
-rw-r--r--src/qmlcompiler/qqmljstypepropagator_p.h5
21 files changed, 264 insertions, 247 deletions
diff --git a/src/qml/common/qqmljsdiagnosticmessage_p.h b/src/qml/common/qqmljsdiagnosticmessage_p.h
index 0e7adbc3be..06c4015bf5 100644
--- a/src/qml/common/qqmljsdiagnosticmessage_p.h
+++ b/src/qml/common/qqmljsdiagnosticmessage_p.h
@@ -41,11 +41,6 @@ struct DiagnosticMessage
{
return type == QtWarningMsg;
}
-
- bool isValid() const
- {
- return !message.isEmpty();
- }
};
} // namespace QQmlJS
diff --git a/src/qmlcompiler/qqmljsbasicblocks_p.h b/src/qmlcompiler/qqmljsbasicblocks_p.h
index a443d422ea..a26e0120f9 100644
--- a/src/qmlcompiler/qqmljsbasicblocks_p.h
+++ b/src/qmlcompiler/qqmljsbasicblocks_p.h
@@ -26,8 +26,9 @@ class Q_QMLCOMPILER_EXPORT QQmlJSBasicBlocks : public QQmlJSCompilePass
public:
QQmlJSBasicBlocks(const QV4::Compiler::Context *context,
const QV4::Compiler::JSUnitGenerator *unitGenerator,
- const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger)
- : QQmlJSCompilePass(unitGenerator, typeResolver, logger), m_context{ context }
+ const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
+ QList<QQmlJS::DiagnosticMessage> *errors)
+ : QQmlJSCompilePass(unitGenerator, typeResolver, logger, errors), m_context{ context }
{
}
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index df855d429b..cb0ccddef4 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -55,9 +55,11 @@ QString QQmlJSCodeGenerator::castTargetName(const QQmlJSScope::ConstPtr &type) c
QQmlJSCodeGenerator::QQmlJSCodeGenerator(const QV4::Compiler::Context *compilerContext,
const QV4::Compiler::JSUnitGenerator *unitGenerator,
const QQmlJSTypeResolver *typeResolver,
- QQmlJSLogger *logger, BasicBlocks basicBlocks,
+ QQmlJSLogger *logger,
+ QList<QQmlJS::DiagnosticMessage> *errors,
+ BasicBlocks basicBlocks,
InstructionAnnotations annotations)
- : QQmlJSCompilePass(unitGenerator, typeResolver, logger, basicBlocks, annotations)
+ : QQmlJSCompilePass(unitGenerator, typeResolver, logger, errors, basicBlocks, annotations)
, m_context(compilerContext)
{}
@@ -126,12 +128,9 @@ QString QQmlJSCodeGenerator::metaType(const QQmlJSScope::ConstPtr &type)
: metaTypeFromName(type);
}
-QQmlJSAotFunction QQmlJSCodeGenerator::run(const Function *function,
- QQmlJS::DiagnosticMessage *error,
- bool basicBlocksValidationFailed)
+QQmlJSAotFunction QQmlJSCodeGenerator::run(const Function *function, bool basicBlocksValidationFailed)
{
m_function = function;
- m_error = error;
QHash<int, int> numRegisterVariablesPerIndex;
@@ -2423,7 +2422,7 @@ void QQmlJSCodeGenerator::generate_Construct(int func, int argc, int argv)
registerType(argv).storedType(), m_typeResolver->sizeType(),
consumedRegisterVariable(argv))
+ u");\n"_s;
- } else if (!m_error->isValid()) {
+ } else if (m_errors->isEmpty()) {
generateArrayInitializer(argc, argv);
}
return;
@@ -2672,7 +2671,7 @@ void QQmlJSCodeGenerator::generate_DefineArray(int argc, int args)
INJECT_TRACE_INFO(generate_DefineArray);
rejectIfBadArray();
- if (!m_error->isValid())
+ if (m_errors->isEmpty())
generateArrayInitializer(argc, args);
}
@@ -3247,8 +3246,8 @@ void QQmlJSCodeGenerator::generate_Exp(int lhs)
m_state.accumulatorIn(), m_state.readAccumulator(),
consumedAccumulatorVariableIn());
- Q_ASSERT(m_error->isValid() || !lhsString.isEmpty());
- Q_ASSERT(m_error->isValid() || !rhsString.isEmpty());
+ Q_ASSERT(!m_errors->isEmpty() || !lhsString.isEmpty());
+ Q_ASSERT(!m_errors->isEmpty() || !rhsString.isEmpty());
const QQmlJSRegisterContent originalOut = original(m_state.accumulatorOut());
m_body += m_state.accumulatorVariableOut + u" = "_s;
@@ -3280,8 +3279,8 @@ void QQmlJSCodeGenerator::generate_Mod(int lhs)
const auto rhsVar = convertStored(
m_state.accumulatorIn().storedType(), m_typeResolver->jsPrimitiveType(),
consumedAccumulatorVariableIn());
- Q_ASSERT(m_error->isValid() || !lhsVar.isEmpty());
- Q_ASSERT(m_error->isValid() || !rhsVar.isEmpty());
+ Q_ASSERT(!m_errors->isEmpty() || !lhsVar.isEmpty());
+ Q_ASSERT(!m_errors->isEmpty() || !rhsVar.isEmpty());
m_body += m_state.accumulatorVariableOut;
m_body += u" = "_s;
@@ -3641,8 +3640,8 @@ void QQmlJSCodeGenerator::generateShiftOperation(int lhs, const QString &cppOper
void QQmlJSCodeGenerator::generateArithmeticOperation(
const QString &lhs, const QString &rhs, const QString &cppOperator)
{
- Q_ASSERT(m_error->isValid() || !lhs.isEmpty());
- Q_ASSERT(m_error->isValid() || !rhs.isEmpty());
+ Q_ASSERT(!m_errors->isEmpty() || !lhs.isEmpty());
+ Q_ASSERT(!m_errors->isEmpty() || !rhs.isEmpty());
const QQmlJSRegisterContent originalOut = original(m_state.accumulatorOut());
m_body += m_state.accumulatorVariableOut;
@@ -4301,7 +4300,7 @@ QString QQmlJSCodeGenerator::convertContained(const QQmlJSRegisterContent &from,
void QQmlJSCodeGenerator::reject(const QString &thing)
{
- setError(u"Cannot generate efficient code for %1"_s.arg(thing));
+ addError(u"Cannot generate efficient code for %1"_s.arg(thing));
}
QQmlJSCodeGenerator::AccumulatorConverter::AccumulatorConverter(QQmlJSCodeGenerator *generator)
diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h
index ffa2c80975..b04663e6c6 100644
--- a/src/qmlcompiler/qqmljscodegenerator_p.h
+++ b/src/qmlcompiler/qqmljscodegenerator_p.h
@@ -33,11 +33,11 @@ public:
QQmlJSCodeGenerator(const QV4::Compiler::Context *compilerContext,
const QV4::Compiler::JSUnitGenerator *unitGenerator,
const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
- BasicBlocks basicBlocks, InstructionAnnotations annotations);
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks,
+ InstructionAnnotations annotations);
~QQmlJSCodeGenerator() = default;
- QQmlJSAotFunction run(const Function *function, QQmlJS::DiagnosticMessage *error,
- bool basicBlocksValidationFailed);
+ QQmlJSAotFunction run(const Function *function, bool basicBlocksValidationFailed);
protected:
struct CodegenState : public State
diff --git a/src/qmlcompiler/qqmljscompilepass_p.h b/src/qmlcompiler/qqmljscompilepass_p.h
index d396efa4de..ce3935ddd7 100644
--- a/src/qmlcompiler/qqmljscompilepass_p.h
+++ b/src/qmlcompiler/qqmljscompilepass_p.h
@@ -264,10 +264,12 @@ public:
QQmlJSCompilePass(const QV4::Compiler::JSUnitGenerator *jsUnitGenerator,
const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
- BasicBlocks basicBlocks = {}, InstructionAnnotations annotations = {})
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks = {},
+ InstructionAnnotations annotations = {})
: m_jsUnitGenerator(jsUnitGenerator)
, m_typeResolver(typeResolver)
, m_logger(logger)
+ , m_errors(errors)
, m_basicBlocks(basicBlocks)
, m_annotations(annotations)
{}
@@ -278,9 +280,9 @@ protected:
QQmlJSLogger *m_logger = nullptr;
const Function *m_function = nullptr;
+ QList<QQmlJS::DiagnosticMessage> *m_errors;
BasicBlocks m_basicBlocks;
InstructionAnnotations m_annotations;
- QQmlJS::DiagnosticMessage *m_error = nullptr;
int firstRegisterIndex() const
{
@@ -369,18 +371,17 @@ protected:
return sourceLocation(currentInstructionOffset());
}
- void setError(const QString &message, int instructionOffset)
+ void addError(const QString &message, int instructionOffset)
{
- Q_ASSERT(m_error);
- if (m_error->isValid())
- return;
- m_error->message = message;
- m_error->loc = sourceLocation(instructionOffset);
+ QQmlJS::DiagnosticMessage diagnostic;
+ diagnostic.message = message;
+ diagnostic.loc = sourceLocation(instructionOffset);
+ m_errors->append(diagnostic);
}
- void setError(const QString &message)
+ void addError(const QString &message)
{
- setError(message, currentInstructionOffset());
+ addError(message, currentInstructionOffset());
}
static bool instructionManipulatesContext(QV4::Moth::Instr::Type type)
diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp
index d55140f964..fa438ad650 100644
--- a/src/qmlcompiler/qqmljscompiler.cpp
+++ b/src/qmlcompiler/qqmljscompiler.cpp
@@ -272,7 +272,7 @@ bool qCompileQmlFile(QmlIR::Document &irDocument, const QString &inputFileName,
std::sort(bindingsAndFunctions.begin(), bindingsAndFunctions.end());
std::for_each(bindingsAndFunctions.begin(), bindingsAndFunctions.end(),
[&](const BindingOrFunction &bindingOrFunction) {
- std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> result;
+ std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>> result;
if (const auto *binding = bindingOrFunction.binding()) {
switch (binding->type()) {
case QmlIR::Binding::Type_AttachedProperty:
@@ -313,12 +313,13 @@ bool qCompileQmlFile(QmlIR::Document &irDocument, const QString &inputFileName,
Q_ASSERT(innerContext);
qCDebug(lcAotCompiler) << "Compiling signal handler for"
<< irDocument.stringAt(binding->propertyNameIndex);
- std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> innerResult
+ std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>> innerResult
= aotCompiler->compileBinding(innerContext, *binding, inner);
-
- if (auto *error = std::get_if<QQmlJS::DiagnosticMessage>(&innerResult)) {
- qCDebug(lcAotCompiler) << "Compilation failed:"
- << diagnosticErrorMessage(inputFileName, *error);
+ if (auto *errors = std::get_if<QList<QQmlJS::DiagnosticMessage>>(&innerResult)) {
+ for (const auto &error : *errors) {
+ qCDebug(lcAotCompiler) << "Compilation failed:"
+ << diagnosticErrorMessage(inputFileName, error);
+ }
} else if (auto *func = std::get_if<QQmlJSAotFunction>(&innerResult)) {
qCDebug(lcAotCompiler) << "Generated code:" << func->code;
aotFunctionsByIndex[innerContext->functionIndex] = *func;
@@ -343,9 +344,11 @@ bool qCompileQmlFile(QmlIR::Document &irDocument, const QString &inputFileName,
Q_UNREACHABLE();
}
- if (auto *error = std::get_if<QQmlJS::DiagnosticMessage>(&result)) {
- qCDebug(lcAotCompiler) << "Compilation failed:"
- << diagnosticErrorMessage(inputFileName, *error);
+ if (auto *errors = std::get_if<QList<QQmlJS::DiagnosticMessage>>(&result)) {
+ for (const auto &error : *errors) {
+ qCDebug(lcAotCompiler) << "Compilation failed:"
+ << diagnosticErrorMessage(inputFileName, error);
+ }
} else if (auto *func = std::get_if<QQmlJSAotFunction>(&result)) {
qCDebug(lcAotCompiler) << "Generated code:" << func->code;
aotFunctionsByIndex[object->runtimeFunctionIndices[bindingOrFunction.index()]] =
@@ -671,27 +674,30 @@ QQmlJS::DiagnosticMessage QQmlJSAotCompiler::diagnose(
};
}
-std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> QQmlJSAotCompiler::compileBinding(
+std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>> QQmlJSAotCompiler::compileBinding(
const QV4::Compiler::Context *context, const QmlIR::Binding &irBinding,
QQmlJS::AST::Node *astNode)
{
QQmlJSFunctionInitializer initializer(
&m_typeResolver, m_currentObject->location, m_currentScope->location);
- QQmlJS::DiagnosticMessage error;
+ QList<QQmlJS::DiagnosticMessage> errors;
const QString name = m_document->stringAt(irBinding.propertyNameIndex);
QQmlJSCompilePass::Function function = initializer.run(
- context, name, astNode, irBinding, &error);
+ context, name, astNode, irBinding, &errors);
const QQmlJSAotFunction aotFunction = doCompileAndRecordAotStats(
- context, &function, &error, name, astNode->firstSourceLocation());
-
- if (error.isValid()) {
- // If it's a signal and the function just returns a closure, it's harmless.
- // Otherwise promote the message to warning level.
- return diagnose(error.message,
- (function.isSignalHandler && error.type == QtDebugMsg)
- ? QtDebugMsg
- : QtWarningMsg,
- error.loc);
+ context, &function, &errors, name, astNode->firstSourceLocation());
+
+ if (!errors.isEmpty()) {
+ for (auto &error : errors) {
+ // If it's a signal and the function just returns a closure, it's harmless.
+ // Otherwise promote the message to warning level.
+ error = diagnose(error.message,
+ (function.isSignalHandler && error.type == QtDebugMsg)
+ ? QtDebugMsg :
+ QtWarningMsg,
+ error.loc);
+ }
+ return errors;
}
qCDebug(lcAotCompiler()) << "includes:" << aotFunction.includes;
@@ -699,18 +705,21 @@ std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> QQmlJSAotCompiler::co
return aotFunction;
}
-std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> QQmlJSAotCompiler::compileFunction(
+std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>> QQmlJSAotCompiler::compileFunction(
const QV4::Compiler::Context *context, const QString &name, QQmlJS::AST::Node *astNode)
{
QQmlJSFunctionInitializer initializer(
&m_typeResolver, m_currentObject->location, m_currentScope->location);
- QQmlJS::DiagnosticMessage error;
- QQmlJSCompilePass::Function function = initializer.run(context, name, astNode, &error);
+ QList<QQmlJS::DiagnosticMessage> errors;
+ QQmlJSCompilePass::Function function = initializer.run(context, name, astNode, &errors);
const QQmlJSAotFunction aotFunction = doCompileAndRecordAotStats(
- context, &function, &error, name, astNode->firstSourceLocation());
+ context, &function, &errors, name, astNode->firstSourceLocation());
- if (error.isValid())
- return diagnose(error.message, QtWarningMsg, error.loc);
+ if (!errors.isEmpty()) {
+ for (auto &error : errors)
+ error = diagnose(error.message, QtWarningMsg, error.loc);
+ return errors;
+ }
qCDebug(lcAotCompiler()) << "includes:" << aotFunction.includes;
qCDebug(lcAotCompiler()) << "binding code:" << aotFunction.code;
@@ -744,70 +753,71 @@ QQmlJSAotFunction QQmlJSAotCompiler::globalCode() const
QQmlJSAotFunction QQmlJSAotCompiler::doCompile(
const QV4::Compiler::Context *context, QQmlJSCompilePass::Function *function,
- QQmlJS::DiagnosticMessage *error)
+ QList<QQmlJS::DiagnosticMessage> *errors)
{
const auto compileError = [&]() {
- Q_ASSERT(error->isValid());
- error->type = context->returnsClosure ? QtDebugMsg : QtWarningMsg;
+ const auto type = context->returnsClosure ? QtDebugMsg : QtWarningMsg;
+ for (auto &error : *errors)
+ error.type = type;
return QQmlJSAotFunction();
};
- if (error->isValid())
+ if (!errors->isEmpty())
return compileError();
bool basicBlocksValidationFailed = false;
- QQmlJSBasicBlocks basicBlocks(context, m_unitGenerator, &m_typeResolver, m_logger);
+ QQmlJSBasicBlocks basicBlocks(context, m_unitGenerator, &m_typeResolver, m_logger, errors);
auto passResult = basicBlocks.run(function, m_flags, basicBlocksValidationFailed);
auto &[blocks, annotations] = passResult;
- QQmlJSTypePropagator propagator(m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations);
- passResult = propagator.run(function, error);
- if (error->isValid())
+ QQmlJSTypePropagator propagator(m_unitGenerator, &m_typeResolver, m_logger, errors, blocks, annotations);
+ passResult = propagator.run(function);
+ if (!errors->isEmpty())
return compileError();
- QQmlJSShadowCheck shadowCheck(m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations);
- passResult = shadowCheck.run(function, error);
- if (error->isValid())
+ QQmlJSShadowCheck shadowCheck(m_unitGenerator, &m_typeResolver, m_logger, errors, blocks, annotations);
+ passResult = shadowCheck.run(function);
+ if (!errors->isEmpty())
return compileError();
- QQmlJSOptimizations optimizer(m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations,
+ QQmlJSOptimizations optimizer(m_unitGenerator, &m_typeResolver, m_logger, errors, blocks, annotations,
basicBlocks.objectAndArrayDefinitions());
- passResult = optimizer.run(function, error);
- if (error->isValid())
+ passResult = optimizer.run(function);
+ if (!errors->isEmpty())
return compileError();
QQmlJSStorageInitializer initializer(
- m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations);
- passResult = initializer.run(function, error);
+ m_unitGenerator, &m_typeResolver, m_logger, errors, blocks, annotations);
+ passResult = initializer.run(function);
// Generalize all arguments, registers, and the return type.
QQmlJSStorageGeneralizer generalizer(
- m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations);
- passResult = generalizer.run(function, error);
- if (error->isValid())
+ m_unitGenerator, &m_typeResolver, m_logger, errors, blocks, annotations);
+ passResult = generalizer.run(function);
+ if (!errors->isEmpty())
return compileError();
- QQmlJSCodeGenerator codegen(context, m_unitGenerator, &m_typeResolver, m_logger, blocks, annotations);
- QQmlJSAotFunction result = codegen.run(function, error, basicBlocksValidationFailed);
- return error->isValid() ? compileError() : result;
+ QQmlJSCodeGenerator codegen(context, m_unitGenerator, &m_typeResolver, m_logger, errors, blocks, annotations);
+ QQmlJSAotFunction result = codegen.run(function, basicBlocksValidationFailed);
+ return !errors->isEmpty() ? compileError() : result;
}
-QQmlJSAotFunction QQmlJSAotCompiler::doCompileAndRecordAotStats(
- const QV4::Compiler::Context *context, QQmlJSCompilePass::Function *function,
- QQmlJS::DiagnosticMessage *error, const QString &name, QQmlJS::SourceLocation location)
+QQmlJSAotFunction QQmlJSAotCompiler::doCompileAndRecordAotStats(const QV4::Compiler::Context *context, QQmlJSCompilePass::Function *function,
+ QList<QQmlJS::DiagnosticMessage> *errors, const QString &name,
+ QQmlJS::SourceLocation location)
{
auto t1 = std::chrono::high_resolution_clock::now();
- QQmlJSAotFunction result = doCompile(context, function, error);
+ QQmlJSAotFunction result = doCompile(context, function, errors);
auto t2 = std::chrono::high_resolution_clock::now();
if (QQmlJS::QQmlJSAotCompilerStats::recordAotStats()) {
QQmlJS::AotStatsEntry entry;
entry.codegenDuration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
entry.functionName = name;
- entry.errorMessage = error->message;
+ entry.errorMessage = errors->isEmpty() ? u""_s : errors->first().message;
entry.line = location.startLine;
entry.column = location.startColumn;
- entry.codegenSuccessful = !error->isValid();
+ entry.codegenSuccessful = errors->isEmpty();
QQmlJS::QQmlJSAotCompilerStats::addEntry(
function->qmlScope.containedType()->filePath(), entry);
}
diff --git a/src/qmlcompiler/qqmljscompiler_p.h b/src/qmlcompiler/qqmljscompiler_p.h
index 94cf71b884..2e08834eca 100644
--- a/src/qmlcompiler/qqmljscompiler_p.h
+++ b/src/qmlcompiler/qqmljscompiler_p.h
@@ -70,10 +70,10 @@ public:
virtual void setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document *document);
virtual void setScope(const QmlIR::Object *object, const QmlIR::Object *scope);
- virtual std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> compileBinding(
+ virtual std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>> compileBinding(
const QV4::Compiler::Context *context, const QmlIR::Binding &irBinding,
QQmlJS::AST::Node *astNode);
- virtual std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> compileFunction(
+ virtual std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>> compileFunction(
const QV4::Compiler::Context *context, const QString &name, QQmlJS::AST::Node *astNode);
virtual QQmlJSAotFunction globalCode() const;
@@ -100,10 +100,10 @@ protected:
private:
QQmlJSAotFunction doCompile(const QV4::Compiler::Context *context,
QQmlJSCompilePass::Function *function,
- QQmlJS::DiagnosticMessage *error);
+ QList<QQmlJS::DiagnosticMessage> *error);
QQmlJSAotFunction doCompileAndRecordAotStats(const QV4::Compiler::Context *context,
QQmlJSCompilePass::Function *function,
- QQmlJS::DiagnosticMessage *error,
+ QList<QQmlJS::DiagnosticMessage> *erros,
const QString &name,
QQmlJS::SourceLocation location);
};
diff --git a/src/qmlcompiler/qqmljsfunctioninitializer.cpp b/src/qmlcompiler/qqmljsfunctioninitializer.cpp
index 1c90167691..5d0b32a5af 100644
--- a/src/qmlcompiler/qqmljsfunctioninitializer.cpp
+++ b/src/qmlcompiler/qqmljsfunctioninitializer.cpp
@@ -55,12 +55,14 @@ static QString bindingTypeDescription(QmlIR::Binding::Type type)
void QQmlJSFunctionInitializer::populateSignature(
const QV4::Compiler::Context *context, QQmlJS::AST::FunctionExpression *ast,
- QQmlJSCompilePass::Function *function, QQmlJS::DiagnosticMessage *error)
+ QQmlJSCompilePass::Function *function, QList<QQmlJS::DiagnosticMessage> *errors)
{
const auto signatureError = [&](const QString &message) {
- error->type = QtWarningMsg;
- error->loc = ast->firstSourceLocation();
- error->message = message;
+ QQmlJS::DiagnosticMessage error;
+ error.type = QtWarningMsg;
+ error.loc = ast->firstSourceLocation();
+ error.message = message;
+ *errors << error;
function->isFullyTyped = false;
};
@@ -143,13 +145,9 @@ void QQmlJSFunctionInitializer::populateSignature(
static void diagnose(
const QString &message, QtMsgType type, const QQmlJS::SourceLocation &location,
- QQmlJS::DiagnosticMessage *error)
+ QList<QQmlJS::DiagnosticMessage> *errors)
{
- *error = QQmlJS::DiagnosticMessage{
- message,
- type,
- location
- };
+ *errors << QQmlJS::DiagnosticMessage{ message, type, location };
}
QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
@@ -157,7 +155,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
const QString &propertyName,
QQmlJS::AST::Node *astNode,
const QmlIR::Binding &irBinding,
- QQmlJS::DiagnosticMessage *error)
+ QList<QQmlJS::DiagnosticMessage> *errors)
{
QQmlJS::SourceLocation bindingLocation;
bindingLocation.startLine = irBinding.location.line();
@@ -169,7 +167,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
if (irBinding.type() != QmlIR::Binding::Type_Script) {
diagnose(u"Binding is not a script binding, but %1."_s.arg(
bindingTypeDescription(QmlIR::Binding::Type(quint32(irBinding.type())))),
- QtDebugMsg, bindingLocation, error);
+ QtDebugMsg, bindingLocation, errors);
}
function.isProperty = m_objectType->hasProperty(propertyName);
@@ -193,7 +191,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
if (type.isNull()) {
diagnose(u"Cannot resolve the argument type %1."_s.arg(
arguments[i].typeName()),
- QtDebugMsg, bindingLocation, error);
+ QtDebugMsg, bindingLocation, errors);
function.argumentTypes.append(
m_typeResolver->tracked(
m_typeResolver->globalType(m_typeResolver->varType())));
@@ -208,7 +206,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
if (!function.isSignalHandler) {
diagnose(u"Could not compile signal handler for %1: The signal does not exist"_s.arg(
*signalName),
- QtWarningMsg, bindingLocation, error);
+ QtWarningMsg, bindingLocation, errors);
}
}
}
@@ -218,7 +216,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
if (!function.isProperty) {
diagnose(u"Could not compile binding for %1: The property does not exist"_s.arg(
propertyName),
- QtWarningMsg, bindingLocation, error);
+ QtWarningMsg, bindingLocation, errors);
}
const auto property = m_objectType->property(propertyName);
@@ -235,7 +233,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
// most commonly used to enable generalized grouped properties.
message += u" You may want use ID-based grouped properties here.";
}
- diagnose(message, QtWarningMsg, bindingLocation, error);
+ diagnose(message, QtWarningMsg, bindingLocation, errors);
}
if (!property.bindable().isEmpty() && !property.isPrivate())
@@ -262,14 +260,14 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
ast->rbraceToken = astNode->lastSourceLocation();
}
- populateSignature(context, ast, &function, error);
+ populateSignature(context, ast, &function, errors);
return function;
}
QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
const QV4::Compiler::Context *context,
const QString &functionName, QQmlJS::AST::Node *astNode,
- QQmlJS::DiagnosticMessage *error)
+ QList<QQmlJS::DiagnosticMessage> *errors)
{
Q_UNUSED(functionName);
@@ -279,7 +277,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
auto ast = astNode->asFunctionDefinition();
Q_ASSERT(ast);
- populateSignature(context, ast, &function, error);
+ populateSignature(context, ast, &function, errors);
return function;
}
diff --git a/src/qmlcompiler/qqmljsfunctioninitializer_p.h b/src/qmlcompiler/qqmljsfunctioninitializer_p.h
index 424959a4fa..68f55a25ff 100644
--- a/src/qmlcompiler/qqmljsfunctioninitializer_p.h
+++ b/src/qmlcompiler/qqmljsfunctioninitializer_p.h
@@ -31,20 +31,19 @@ public:
, m_objectType(typeResolver->scopeForLocation(objectLocation))
{}
- QQmlJSCompilePass::Function run(
- const QV4::Compiler::Context *context,
- const QString &propertyName, QQmlJS::AST::Node *astNode,
- const QmlIR::Binding &irBinding,
- QQmlJS::DiagnosticMessage *error);
+ QQmlJSCompilePass::Function run(const QV4::Compiler::Context *context,
+ const QString &propertyName, QQmlJS::AST::Node *astNode,
+ const QmlIR::Binding &irBinding,
+ QList<QQmlJS::DiagnosticMessage> *errors);
QQmlJSCompilePass::Function run(
const QV4::Compiler::Context *context,
const QString &functionName, QQmlJS::AST::Node *astNode,
- QQmlJS::DiagnosticMessage *error);
+ QList<QQmlJS::DiagnosticMessage> *errors);
private:
void populateSignature(
const QV4::Compiler::Context *context, QQmlJS::AST::FunctionExpression *ast,
- QQmlJSCompilePass::Function *function, QQmlJS::DiagnosticMessage *error);
+ QQmlJSCompilePass::Function *function, QList<QQmlJS::DiagnosticMessage> *errors);
const QQmlJSTypeResolver *m_typeResolver = nullptr;
const QQmlJSScope::ConstPtr m_scopeType;
diff --git a/src/qmlcompiler/qqmljslintercodegen.cpp b/src/qmlcompiler/qqmljslintercodegen.cpp
index 314c2087e4..e33fe7139b 100644
--- a/src/qmlcompiler/qqmljslintercodegen.cpp
+++ b/src/qmlcompiler/qqmljslintercodegen.cpp
@@ -30,50 +30,56 @@ void QQmlJSLinterCodegen::setDocument(const QmlIR::JSCodeGen *codegen,
m_unitGenerator = &document->jsGenerator;
}
-std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage>
+std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>>
QQmlJSLinterCodegen::compileBinding(const QV4::Compiler::Context *context,
const QmlIR::Binding &irBinding, QQmlJS::AST::Node *astNode)
{
QQmlJSFunctionInitializer initializer(
&m_typeResolver, m_currentObject->location, m_currentScope->location);
- QQmlJS::DiagnosticMessage initializationError;
+ QList<QQmlJS::DiagnosticMessage> initializationErrors;
const QString name = m_document->stringAt(irBinding.propertyNameIndex);
QQmlJSCompilePass::Function function =
- initializer.run(context, name, astNode, irBinding, &initializationError);
- if (initializationError.isValid())
- diagnose(initializationError.message, initializationError.type, initializationError.loc);
+ initializer.run(context, name, astNode, irBinding, &initializationErrors);
+ for (const auto &error : initializationErrors)
+ diagnose(error.message, error.type, error.loc);
- QQmlJS::DiagnosticMessage analyzeError;
- if (!analyzeFunction(context, &function, &analyzeError)) {
+ QList<QQmlJS::DiagnosticMessage> analyzeErrors;
+ if (!analyzeFunction(context, &function, &analyzeErrors)) {
// If it's a signal and the function just returns a closure, it's harmless.
// Otherwise promote the message to warning level.
- return diagnose(u"Could not compile binding for %1: %2"_s.arg(name, analyzeError.message),
- (function.isSignalHandler && analyzeError.type == QtDebugMsg)
- ? QtDebugMsg
- : QtWarningMsg,
- analyzeError.loc);
+ for (auto &error : analyzeErrors) {
+ error = diagnose(u"Could not compile binding for %1: %2"_s.arg(name, error.message),
+ (function.isSignalHandler && error.type == QtDebugMsg)
+ ? QtDebugMsg
+ : QtWarningMsg,
+ error.loc);
+ }
+ return analyzeErrors;
}
return QQmlJSAotFunction {};
}
-std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage>
+std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>>
QQmlJSLinterCodegen::compileFunction(const QV4::Compiler::Context *context,
const QString &name, QQmlJS::AST::Node *astNode)
{
- QQmlJS::DiagnosticMessage initializationError;
+ QList<QQmlJS::DiagnosticMessage> initializationErrors;
QQmlJSFunctionInitializer initializer(
&m_typeResolver, m_currentObject->location, m_currentScope->location);
QQmlJSCompilePass::Function function =
- initializer.run(context, name, astNode, &initializationError);
- if (initializationError.isValid())
- diagnose(initializationError.message, initializationError.type, initializationError.loc);
-
- QQmlJS::DiagnosticMessage analyzeError;
- if (!analyzeFunction(context, &function, &analyzeError)) {
- return diagnose(u"Could not compile function %1: %2"_s.arg(name, analyzeError.message),
- QtWarningMsg, analyzeError.loc);
+ initializer.run(context, name, astNode, &initializationErrors);
+ for (const auto &error : initializationErrors)
+ diagnose(error.message, error.type, error.loc);
+
+ QList<QQmlJS::DiagnosticMessage> analyzeErrors;
+ if (!analyzeFunction(context, &function, &analyzeErrors)) {
+ for (auto &error : analyzeErrors) {
+ error = diagnose(u"Could not compile function %1: %2"_s.arg(name, error.message),
+ QtWarningMsg, error.loc);
+ }
+ return analyzeErrors;
}
return QQmlJSAotFunction {};
@@ -88,31 +94,33 @@ void QQmlJSLinterCodegen::setPassManager(QQmlSA::PassManager *passManager)
bool QQmlJSLinterCodegen::analyzeFunction(const QV4::Compiler::Context *context,
QQmlJSCompilePass::Function *function,
- QQmlJS::DiagnosticMessage *error)
+ QList<QQmlJS::DiagnosticMessage> *errors)
{
- QQmlJSTypePropagator propagator(m_unitGenerator, &m_typeResolver, m_logger,
- {}, {}, m_passManager);
- auto [basicBlocks, annotations] = propagator.run(function, error);
- if (!error->isValid()) {
- QQmlJSShadowCheck shadowCheck(m_unitGenerator, &m_typeResolver, m_logger, basicBlocks,
- annotations);
- shadowCheck.run(function, error);
+ QQmlJSTypePropagator propagator(m_unitGenerator, &m_typeResolver, m_logger, errors, {}, {},
+ m_passManager);
+ auto [basicBlocks, annotations] = propagator.run(function);
+ if (errors->isEmpty()) {
+ QQmlJSShadowCheck shadowCheck(m_unitGenerator, &m_typeResolver, m_logger, errors,
+ basicBlocks, annotations);
+ shadowCheck.run(function);
}
- if (!error->isValid()) {
- QQmlJSStorageInitializer initializer(m_unitGenerator, &m_typeResolver, m_logger,
+ if (errors->isEmpty()) {
+ QQmlJSStorageInitializer initializer(m_unitGenerator, &m_typeResolver, m_logger, errors,
basicBlocks, annotations);
- initializer.run(function, error);
+ initializer.run(function);
}
- if (!error->isValid()) {
- QQmlJSStorageGeneralizer generalizer(m_unitGenerator, &m_typeResolver, m_logger,
+ if (errors->isEmpty()) {
+ QQmlJSStorageGeneralizer generalizer(m_unitGenerator, &m_typeResolver, m_logger, errors,
basicBlocks, annotations);
- generalizer.run(function, error);
+ generalizer.run(function);
}
- if (error->isValid()) {
- error->type = context->returnsClosure ? QtDebugMsg : QtWarningMsg;
+ if (!errors->isEmpty()) {
+ QtMsgType type = context->returnsClosure ? QtDebugMsg : QtWarningMsg;
+ for (auto &error : *errors)
+ error.type = type;
return false;
}
diff --git a/src/qmlcompiler/qqmljslintercodegen_p.h b/src/qmlcompiler/qqmljslintercodegen_p.h
index 8c9f601166..f58223034c 100644
--- a/src/qmlcompiler/qqmljslintercodegen_p.h
+++ b/src/qmlcompiler/qqmljslintercodegen_p.h
@@ -42,10 +42,10 @@ public:
const QStringList &qmldirFiles, QQmlJSLogger *logger);
void setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document *document) override;
- std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage>
+ std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>>
compileBinding(const QV4::Compiler::Context *context, const QmlIR::Binding &irBinding,
QQmlJS::AST::Node *astNode) override;
- std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage>
+ std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>>
compileFunction(const QV4::Compiler::Context *context, const QString &name,
QQmlJS::AST::Node *astNode) override;
@@ -64,7 +64,8 @@ private:
QQmlSA::PassManager *m_passManager = nullptr;
bool analyzeFunction(const QV4::Compiler::Context *context,
- QQmlJSCompilePass::Function *function, QQmlJS::DiagnosticMessage *error);
+ QQmlJSCompilePass::Function *function,
+ QList<QQmlJS::DiagnosticMessage> *errors);
};
QT_END_NAMESPACE
diff --git a/src/qmlcompiler/qqmljsoptimizations.cpp b/src/qmlcompiler/qqmljsoptimizations.cpp
index 3fe2d89cf7..0603d6fa42 100644
--- a/src/qmlcompiler/qqmljsoptimizations.cpp
+++ b/src/qmlcompiler/qqmljsoptimizations.cpp
@@ -9,11 +9,9 @@ QT_BEGIN_NAMESPACE
using namespace Qt::Literals::StringLiterals;
-QQmlJSCompilePass::BlocksAndAnnotations QQmlJSOptimizations::run(const Function *function,
- QQmlJS::DiagnosticMessage *error)
+QQmlJSCompilePass::BlocksAndAnnotations QQmlJSOptimizations::run(const Function *function)
{
m_function = function;
- m_error = error;
populateBasicBlocks();
populateReaderLocations();
@@ -329,7 +327,7 @@ void QQmlJSOptimizations::adjustTypes()
return; // Constructed something else.
if (!m_typeResolver->adjustTrackedType(it->trackedTypes[0], it->typeReaders.values()))
- setError(adjustErrorMessage(it->trackedTypes[0], it->typeReaders.values()));
+ addError(adjustErrorMessage(it->trackedTypes[0], it->typeReaders.values()));
// Now we don't adjust the type we store, but rather the type we expect to read. We
// can do this because we've tracked the read type when we defined the array in
@@ -342,7 +340,7 @@ void QQmlJSOptimizations::adjustTypes()
if (mode != ObjectOrArrayDefinition::ArrayConstruct1ArgId
|| !m_typeResolver->equals(contained, m_typeResolver->realType())) {
if (!m_typeResolver->adjustTrackedType(contained, valueType))
- setError(adjustErrorMessage(contained, valueType));
+ addError(adjustErrorMessage(contained, valueType));
}
}
@@ -366,7 +364,7 @@ void QQmlJSOptimizations::adjustTypes()
Q_ASSERT(!annotation.readRegisters.isEmpty());
if (!m_typeResolver->adjustTrackedType(resultType, it->typeReaders.values()))
- setError(adjustErrorMessage(resultType, it->typeReaders.values()));
+ addError(adjustErrorMessage(resultType, it->typeReaders.values()));
if (m_typeResolver->equals(resultType, m_typeResolver->varType())
|| m_typeResolver->equals(resultType, m_typeResolver->variantMapType())) {
@@ -385,19 +383,19 @@ void QQmlJSOptimizations::adjustTypes()
const QString propName = m_jsUnitGenerator->jsClassMember(object.internalClassId, i);
const QQmlJSMetaProperty property = resultType->property(propName);
if (!property.isValid()) {
- setError(resultType->internalName() + QLatin1String(" has no property called ")
+ addError(resultType->internalName() + QLatin1String(" has no property called ")
+ propName);
continue;
}
const QQmlJSScope::ConstPtr propType = property.type();
if (propType.isNull()) {
- setError(QLatin1String("Cannot resolve type of property ") + propName);
+ addError(QLatin1String("Cannot resolve type of property ") + propName);
continue;
}
const QQmlJSRegisterContent content = annotation.readRegisters[object.argv + i].content;
const QQmlJSScope::ConstPtr contained = content.containedType();
if (!m_typeResolver->adjustTrackedType(contained, propType))
- setError(adjustErrorMessage(contained, propType));
+ addError(adjustErrorMessage(contained, propType));
}
// The others cannot be adjusted. We don't know their names, yet.
@@ -433,7 +431,7 @@ void QQmlJSOptimizations::adjustTypes()
continue;
if (!m_typeResolver->adjustTrackedType(it->trackedTypes[0], it->typeReaders.values()))
- setError(adjustErrorMessage(it->trackedTypes[0], it->typeReaders.values()));
+ addError(adjustErrorMessage(it->trackedTypes[0], it->typeReaders.values()));
}
@@ -453,7 +451,7 @@ void QQmlJSOptimizations::adjustTypes()
for (const auto &origin : conversionOrigins)
newResult = m_typeResolver->merge(newResult, origin);
if (!m_typeResolver->adjustTrackedType(conversionResult, newResult))
- setError(adjustErrorMessage(conversionResult, newResult));
+ addError(adjustErrorMessage(conversionResult, newResult));
}
newRegisters.appendOrdered(conversion);
}
diff --git a/src/qmlcompiler/qqmljsoptimizations_p.h b/src/qmlcompiler/qqmljsoptimizations_p.h
index 519975fbe6..16703c16f0 100644
--- a/src/qmlcompiler/qqmljsoptimizations_p.h
+++ b/src/qmlcompiler/qqmljsoptimizations_p.h
@@ -25,16 +25,17 @@ public:
QQmlJSOptimizations(const QV4::Compiler::JSUnitGenerator *unitGenerator,
const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
- BasicBlocks basicBlocks, InstructionAnnotations annotations,
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks,
+ InstructionAnnotations annotations,
QList<ObjectOrArrayDefinition> objectAndArrayDefinitions)
- : QQmlJSCompilePass(unitGenerator, typeResolver, logger, basicBlocks, annotations),
+ : QQmlJSCompilePass(unitGenerator, typeResolver, logger, errors, basicBlocks, annotations),
m_objectAndArrayDefinitions{ objectAndArrayDefinitions }
{
}
~QQmlJSOptimizations() = default;
- BlocksAndAnnotations run(const Function *function, QQmlJS::DiagnosticMessage *error);
+ BlocksAndAnnotations run(const Function *function);
private:
struct RegisterAccess
diff --git a/src/qmlcompiler/qqmljsshadowcheck.cpp b/src/qmlcompiler/qqmljsshadowcheck.cpp
index 29de04e2f1..04efe7331f 100644
--- a/src/qmlcompiler/qqmljsshadowcheck.cpp
+++ b/src/qmlcompiler/qqmljsshadowcheck.cpp
@@ -34,11 +34,9 @@ using namespace Qt::StringLiterals;
* arguments and return types into "var".
*/
-QQmlJSCompilePass::BlocksAndAnnotations QQmlJSShadowCheck::run(const Function *function,
- QQmlJS::DiagnosticMessage *error)
+QQmlJSCompilePass::BlocksAndAnnotations QQmlJSShadowCheck::run(const Function *function)
{
m_function = function;
- m_error = error;
m_state = initialState(function);
decode(m_function->code.constData(), static_cast<uint>(m_function->code.size()));
@@ -237,7 +235,7 @@ QQmlJSShadowCheck::Shadowability QQmlJSShadowCheck::checkBaseType(
{
if (!m_adjustedTypes.contains(baseType))
return NotShadowable;
- setError(u"Cannot use shadowable base type for further lookups: %1"_s.arg(baseType.descriptiveName()));
+ addError(u"Cannot use shadowable base type for further lookups: %1"_s.arg(baseType.descriptiveName()));
return Shadowable;
}
diff --git a/src/qmlcompiler/qqmljsshadowcheck_p.h b/src/qmlcompiler/qqmljsshadowcheck_p.h
index dfa00134cb..9b763351ce 100644
--- a/src/qmlcompiler/qqmljsshadowcheck_p.h
+++ b/src/qmlcompiler/qqmljsshadowcheck_p.h
@@ -23,13 +23,14 @@ class Q_QMLCOMPILER_EXPORT QQmlJSShadowCheck : public QQmlJSCompilePass
public:
QQmlJSShadowCheck(const QV4::Compiler::JSUnitGenerator *jsUnitGenerator,
const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
- BasicBlocks basicBlocks, InstructionAnnotations annotations)
- : QQmlJSCompilePass(jsUnitGenerator, typeResolver, logger, basicBlocks, annotations)
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks,
+ InstructionAnnotations annotations)
+ : QQmlJSCompilePass(jsUnitGenerator, typeResolver, logger, errors, basicBlocks, annotations)
{}
~QQmlJSShadowCheck() = default;
- BlocksAndAnnotations run(const Function *function, QQmlJS::DiagnosticMessage *error);
+ BlocksAndAnnotations run(const Function *function);
private:
struct ResettableStore {
diff --git a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp
index 3ba709b21f..ce9f096ac6 100644
--- a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp
+++ b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp
@@ -19,18 +19,16 @@ QT_BEGIN_NAMESPACE
* operates only on the annotations and the function description.
*/
-QQmlJSCompilePass::BlocksAndAnnotations
-QQmlJSStorageGeneralizer::run(Function *function, QQmlJS::DiagnosticMessage *error)
+QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageGeneralizer::run(Function *function)
{
m_function = function;
- m_error = error;
if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) {
if (QQmlJSScope::ConstPtr stored = m_typeResolver->genericType(
returnType.storedType(), QQmlJSTypeResolver::ComponentIsGeneric::Yes)) {
returnType = returnType.storedIn(stored);
} else {
- setError(QStringLiteral("Cannot store the return type %1.")
+ addError(QStringLiteral("Cannot store the return type %1.")
.arg(returnType.storedType()->internalName()));
return {};
}
diff --git a/src/qmlcompiler/qqmljsstoragegeneralizer_p.h b/src/qmlcompiler/qqmljsstoragegeneralizer_p.h
index 9ef4699fca..83c9275444 100644
--- a/src/qmlcompiler/qqmljsstoragegeneralizer_p.h
+++ b/src/qmlcompiler/qqmljsstoragegeneralizer_p.h
@@ -23,11 +23,12 @@ class Q_QMLCOMPILER_EXPORT QQmlJSStorageGeneralizer : public QQmlJSCompilePass
public:
QQmlJSStorageGeneralizer(const QV4::Compiler::JSUnitGenerator *jsUnitGenerator,
const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
- BasicBlocks basicBlocks, InstructionAnnotations annotations)
- : QQmlJSCompilePass(jsUnitGenerator, typeResolver, logger, basicBlocks, annotations)
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks,
+ InstructionAnnotations annotations)
+ : QQmlJSCompilePass(jsUnitGenerator, typeResolver, logger, errors, basicBlocks, annotations)
{}
- BlocksAndAnnotations run(Function *function, QQmlJS::DiagnosticMessage *error);
+ BlocksAndAnnotations run(Function *function);
protected:
// We don't have to use the byte code here. We only transform the instruction annotations.
diff --git a/src/qmlcompiler/qqmljsstorageinitializer.cpp b/src/qmlcompiler/qqmljsstorageinitializer.cpp
index b0f7d1a49f..27169001f2 100644
--- a/src/qmlcompiler/qqmljsstorageinitializer.cpp
+++ b/src/qmlcompiler/qqmljsstorageinitializer.cpp
@@ -16,18 +16,16 @@ QT_BEGIN_NAMESPACE
* operates only on the annotations and the function description.
*/
-QQmlJSCompilePass::BlocksAndAnnotations
-QQmlJSStorageInitializer::run(Function *function, QQmlJS::DiagnosticMessage *error)
+QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageInitializer::run(Function *function)
{
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.")
+ addError(QStringLiteral("Cannot store the return type %1.")
.arg(returnType.containedType()->internalName()));
return {};
}
@@ -47,7 +45,7 @@ QQmlJSStorageInitializer::run(Function *function, QQmlJS::DiagnosticMessage *err
= m_typeResolver->storedType(content.containedType());
if (!m_typeResolver->adjustTrackedType(originalTracked, adjustedStored)) {
- setError(QStringLiteral("Cannot adjust stored type for %1.")
+ addError(QStringLiteral("Cannot adjust stored type for %1.")
.arg(content.containedType()->internalName()));
}
};
diff --git a/src/qmlcompiler/qqmljsstorageinitializer_p.h b/src/qmlcompiler/qqmljsstorageinitializer_p.h
index 0644807543..08e07aa073 100644
--- a/src/qmlcompiler/qqmljsstorageinitializer_p.h
+++ b/src/qmlcompiler/qqmljsstorageinitializer_p.h
@@ -23,11 +23,12 @@ 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)
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks,
+ InstructionAnnotations annotations)
+ : QQmlJSCompilePass(jsUnitGenerator, typeResolver, logger, errors, basicBlocks, annotations)
{}
- BlocksAndAnnotations run(Function *function, QQmlJS::DiagnosticMessage *error);
+ BlocksAndAnnotations run(Function *function);
protected:
// We don't have to use the byte code here. We only transform the instruction annotations.
diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp
index 0fc8900015..156f11916e 100644
--- a/src/qmlcompiler/qqmljstypepropagator.cpp
+++ b/src/qmlcompiler/qqmljstypepropagator.cpp
@@ -28,25 +28,32 @@ using namespace Qt::StringLiterals;
QQmlJSTypePropagator::QQmlJSTypePropagator(const QV4::Compiler::JSUnitGenerator *unitGenerator,
const QQmlJSTypeResolver *typeResolver,
- QQmlJSLogger *logger, BasicBlocks basicBlocks,
+ QQmlJSLogger *logger,
+ QList<QQmlJS::DiagnosticMessage> *errors,
+ BasicBlocks basicBlocks,
InstructionAnnotations annotations,
QQmlSA::PassManager *passManager)
- : QQmlJSCompilePass(unitGenerator, typeResolver, logger, basicBlocks, annotations),
+ : QQmlJSCompilePass(unitGenerator, typeResolver, logger, errors, basicBlocks, annotations),
m_passManager(passManager)
{
}
-QQmlJSCompilePass::BlocksAndAnnotations QQmlJSTypePropagator::run(
- const Function *function, QQmlJS::DiagnosticMessage *error)
+QQmlJSCompilePass::BlocksAndAnnotations QQmlJSTypePropagator::run(const Function *function)
{
m_function = function;
- m_error = error;
m_returnType = m_function->returnType;
+ QList<QQmlJS::DiagnosticMessage> oldErrors;
+ std::swap(oldErrors, *m_errors);
+ auto restoreErrors = qScopeGuard([&]() {
+ oldErrors << *std::move(m_errors);
+ *m_errors = std::move(oldErrors);
+ });
+
do {
// Reset the error if we need to do another pass
if (m_state.needsMorePasses)
- *m_error = QQmlJS::DiagnosticMessage();
+ m_errors->clear();
m_prevStateAnnotations = m_state.annotations;
m_state = PassState();
@@ -65,7 +72,7 @@ QQmlJSCompilePass::BlocksAndAnnotations QQmlJSTypePropagator::run(
}
#define INSTR_PROLOGUE_NOT_IMPLEMENTED() \
- setError(u"Instruction \"%1\" not implemented"_s.arg(QString::fromUtf8(__func__))); \
+ addError(u"Instruction \"%1\" not implemented"_s.arg(QString::fromUtf8(__func__))); \
return;
#define INSTR_PROLOGUE_NOT_IMPLEMENTED_IGNORE() \
@@ -96,7 +103,7 @@ void QQmlJSTypePropagator::generate_Ret()
m_state.accumulatorIn(), m_typeResolver->voidType())) {
// You can always return undefined.
} else if (!m_returnType.isValid() && m_state.accumulatorIn().isValid()) {
- setError(u"function without return type annotation returns %1. This may prevent proper "_s
+ addError(u"function without return type annotation returns %1. This may prevent proper "_s
u"compilation to Cpp."_s.arg(m_state.accumulatorIn().descriptiveName()));
if (m_function->isFullyTyped) {
@@ -107,7 +114,7 @@ void QQmlJSTypePropagator::generate_Ret()
}
return;
} else if (!canConvertFromTo(m_state.accumulatorIn(), m_returnType)) {
- setError(u"cannot convert from %1 to %2"_s
+ addError(u"cannot convert from %1 to %2"_s
.arg(m_state.accumulatorIn().descriptiveName(),
m_returnType.descriptiveName()));
@@ -263,7 +270,7 @@ void QQmlJSTypePropagator::generate_LoadName(int nameIndex)
const QString name = m_jsUnitGenerator->stringForIndex(nameIndex);
setAccumulator(m_typeResolver->scopedType(m_function->qmlScope, name));
if (!m_state.accumulatorOut().isValid())
- setError(u"Cannot find name "_s + name);
+ addError(u"Cannot find name "_s + name);
}
void QQmlJSTypePropagator::generate_LoadGlobalLookup(int index)
@@ -583,7 +590,7 @@ void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index)
checkDeprecated(qmlScope, name, false);
if (!m_state.accumulatorOut().isValid()) {
- setError(u"Cannot access value for name "_s + name);
+ addError(u"Cannot access value for name "_s + name);
handleUnqualifiedAccess(name, false);
return;
}
@@ -591,7 +598,7 @@ void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index)
const QQmlJSRegisterContent accumulatorOut = m_state.accumulatorOut();
if (accumulatorOut.variant() == QQmlJSRegisterContent::ObjectById
&& !m_typeResolver->genericType(accumulatorOut.containedType())->isReferenceType()) {
- setError(u"Cannot retrieve a non-object type by ID: "_s + name);
+ addError(u"Cannot retrieve a non-object type by ID: "_s + name);
return;
}
@@ -632,7 +639,7 @@ void QQmlJSTypePropagator::generate_StoreNameCommon(int nameIndex)
if (!type.isValid()) {
handleUnqualifiedAccess(name, false);
- setError(u"Cannot find name "_s + name);
+ addError(u"Cannot find name "_s + name);
return;
}
@@ -643,12 +650,12 @@ void QQmlJSTypePropagator::generate_StoreNameCommon(int nameIndex)
// and we lack a better fitting category. We might want to revisit this later.
m_logger->log(message.arg(name), qmlReadOnlyProperty,
getCurrentSourceLocation());
- setError(u"Cannot assign to non-property "_s + name);
+ addError(u"Cannot assign to non-property "_s + name);
return;
}
if (!type.isWritable()) {
- setError(u"Can't assign to read-only property %1"_s.arg(name));
+ addError(u"Can't assign to read-only property %1"_s.arg(name));
m_logger->log(u"Cannot assign to read-only property %1"_s.arg(name), qmlReadOnlyProperty,
getCurrentSourceLocation());
@@ -657,7 +664,7 @@ void QQmlJSTypePropagator::generate_StoreNameCommon(int nameIndex)
}
if (!canConvertFromTo(in, type)) {
- setError(u"cannot convert from %1 to %2"_s
+ addError(u"cannot convert from %1 to %2"_s
.arg(in.descriptiveName(), type.descriptiveName()));
}
@@ -697,7 +704,7 @@ bool QQmlJSTypePropagator::checkForEnumProblems(
getCurrentSourceLocation());
const QString error = u"\"%1\" is not an entry of enum \"%2\"."_s
.arg(propertyName, metaEn.name());
- setError(error);
+ addError(error);
m_logger->log(
error, qmlMissingEnumEntry, getCurrentSourceLocation(), true, true,
fixSuggestion);
@@ -708,7 +715,7 @@ bool QQmlJSTypePropagator::checkForEnumProblems(
if (metaEn.isValid() && !metaEn.isScoped() && !metaEn.isQml()) {
const QString error
= u"You cannot access unscoped enum \"%1\" from here."_s.arg(propertyName);
- setError(error);
+ addError(error);
m_logger->log(error, qmlRestrictedType, getCurrentSourceLocation());
return true;
}
@@ -859,7 +866,7 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName,
if (checkForEnumProblems(m_state.accumulatorIn(), propertyName))
return;
- setError(u"Cannot load property %1 from %2."_s
+ addError(u"Cannot load property %1 from %2."_s
.arg(propertyName, m_state.accumulatorIn().descriptiveName()));
const QString typeName = m_state.accumulatorIn().containedTypeName();
@@ -906,7 +913,7 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName,
}
if (m_state.accumulatorOut().isMethod() && m_state.accumulatorOut().method().size() != 1) {
- setError(u"Cannot determine overloaded method on loadProperty"_s);
+ addError(u"Cannot determine overloaded method on loadProperty"_s);
return;
}
@@ -929,7 +936,7 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName,
if (m_typeResolver->registerContains(
m_state.accumulatorOut(), m_typeResolver->voidType())) {
- setError(u"Type %1 does not have a property %2 for reading"_s
+ addError(u"Type %1 does not have a property %2 for reading"_s
.arg(m_state.accumulatorIn().descriptiveName(), propertyName));
return;
}
@@ -1009,19 +1016,19 @@ void QQmlJSTypePropagator::generate_StoreProperty(int nameIndex, int base)
QQmlJSRegisterContent property = m_typeResolver->memberType(callBase, propertyName);
if (!property.isProperty()) {
- setError(u"Type %1 does not have a property %2 for writing"_s
+ addError(u"Type %1 does not have a property %2 for writing"_s
.arg(callBase.descriptiveName(), propertyName));
return;
}
if (property.containedType().isNull()) {
- setError(u"Cannot determine type for property %1 of type %2"_s.arg(
+ addError(u"Cannot determine type for property %1 of type %2"_s.arg(
propertyName, callBase.descriptiveName()));
return;
}
if (!property.isWritable() && !property.containedType()->isListProperty()) {
- setError(u"Can't assign to read-only property %1"_s.arg(propertyName));
+ addError(u"Can't assign to read-only property %1"_s.arg(propertyName));
m_logger->log(u"Cannot assign to read-only property %1"_s.arg(propertyName),
qmlReadOnlyProperty, getCurrentSourceLocation());
@@ -1030,7 +1037,7 @@ void QQmlJSTypePropagator::generate_StoreProperty(int nameIndex, int base)
}
if (!canConvertFromTo(m_state.accumulatorIn(), property)) {
- setError(u"cannot convert from %1 to %2"_s
+ addError(u"cannot convert from %1 to %2"_s
.arg(m_state.accumulatorIn().descriptiveName(), property.descriptiveName()));
return;
}
@@ -1224,7 +1231,7 @@ void QQmlJSTypePropagator::generate_CallProperty(int nameIndex, int base, int ar
return;
}
- setError(u"Type %1 does not have a property %2 for calling"_s
+ addError(u"Type %1 does not have a property %2 for calling"_s
.arg(callBase.descriptiveName(), propertyName));
if (callBase.isType() && isCallingProperty(callBase.type(), propertyName))
@@ -1432,11 +1439,11 @@ void QQmlJSTypePropagator::propagateCall(
if (methods.size() == 1) {
// Cannot have multiple fuzzy matches if there is only one method
Q_ASSERT(errors.size() == 1);
- setError(errors.first());
+ addError(errors.first());
} else if (errors.size() < methods.size()) {
- setError(u"Multiple matching overrides found. Cannot determine the right one."_s);
+ addError(u"Multiple matching overrides found. Cannot determine the right one."_s);
} else {
- setError(u"No matching override found. Candidates:\n"_s + errors.join(u'\n'));
+ addError(u"No matching override found. Candidates:\n"_s + errors.join(u'\n'));
}
return;
}
@@ -1451,7 +1458,7 @@ void QQmlJSTypePropagator::propagateCall(
: QQmlJSRegisterContent::MethodReturnValue,
scope));
if (!m_state.accumulatorOut().isValid())
- setError(u"Cannot store return type of method %1()."_s.arg(match.methodName()));
+ addError(u"Cannot store return type of method %1()."_s.arg(match.methodName()));
const auto types = match.parameters();
for (int i = 0; i < argc; ++i) {
@@ -1806,10 +1813,10 @@ void QQmlJSTypePropagator::propagateScopeLookupCall(const QString &functionName,
}
}
- setError(u"method %1 cannot be resolved."_s.arg(functionName));
+ addError(u"method %1 cannot be resolved."_s.arg(functionName));
setAccumulator(m_typeResolver->globalType(m_typeResolver->jsValueType()));
- setError(u"Cannot find function '%1'"_s.arg(functionName));
+ addError(u"Cannot find function '%1'"_s.arg(functionName));
handleUnqualifiedAccess(functionName, true);
}
@@ -1946,7 +1953,7 @@ void QQmlJSTypePropagator::generate_UnwindToLabel(int level, int offset)
void QQmlJSTypePropagator::generate_DeadTemporalZoneCheck(int name)
{
const auto fail = [this, name]() {
- setError(u"Cannot statically assert the dead temporal zone check for %1"_s.arg(
+ addError(u"Cannot statically assert the dead temporal zone check for %1"_s.arg(
name ? m_jsUnitGenerator->stringForIndex(name) : u"the anonymous accumulator"_s));
};
@@ -2199,7 +2206,7 @@ void QQmlJSTypePropagator::generate_JumpTrue(int offset)
{
if (!canConvertFromTo(m_state.accumulatorIn(),
m_typeResolver->globalType(m_typeResolver->boolType()))) {
- setError(u"cannot convert from %1 to boolean"_s
+ addError(u"cannot convert from %1 to boolean"_s
.arg(m_state.accumulatorIn().descriptiveName()));
return;
}
@@ -2212,7 +2219,7 @@ void QQmlJSTypePropagator::generate_JumpFalse(int offset)
{
if (!canConvertFromTo(m_state.accumulatorIn(),
m_typeResolver->globalType(m_typeResolver->boolType()))) {
- setError(u"cannot convert from %1 to boolean"_s
+ addError(u"cannot convert from %1 to boolean"_s
.arg(m_state.accumulatorIn().descriptiveName()));
return;
}
@@ -2446,7 +2453,7 @@ void QQmlJSTypePropagator::generate_As(int lhs)
else
output = m_typeResolver->cast(input, outContained);
} else if (!m_typeResolver->canAddressValueTypes()) {
- setError(u"invalid cast from %1 to %2. You can only cast object types."_s
+ addError(u"invalid cast from %1 to %2. You can only cast object types."_s
.arg(input.descriptiveName(), m_state.accumulatorIn().descriptiveName()));
return;
} else {
@@ -2470,7 +2477,7 @@ void QQmlJSTypePropagator::checkConversion(
const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to)
{
if (!canConvertFromTo(from, to)) {
- setError(u"cannot convert from %1 to %2"_s
+ addError(u"cannot convert from %1 to %2"_s
.arg(from.descriptiveName(), to.descriptiveName()));
}
}
@@ -2652,7 +2659,7 @@ void QQmlJSTypePropagator::generate_GetTemplateObject(int index)
QV4::Moth::ByteCodeHandler::Verdict
QQmlJSTypePropagator::startInstruction(QV4::Moth::Instr::Type type)
{
- if (m_error->isValid())
+ if (!m_errors->isEmpty())
return SkipInstruction;
if (m_state.jumpTargets.contains(currentInstructionOffset())) {
@@ -2691,7 +2698,7 @@ QQmlJSTypePropagator::startInstruction(QV4::Moth::Instr::Type type)
auto newType = registerIt.value().content;
if (!newType.isValid()) {
- setError(u"When reached from offset %1, %2 is undefined"_s
+ addError(u"When reached from offset %1, %2 is undefined"_s
.arg(stateToMerge.originatingOffset)
.arg(registerName(registerIndex)));
return SkipInstruction;
@@ -2743,8 +2750,8 @@ void QQmlJSTypePropagator::endInstruction(QV4::Moth::Instr::Type instr)
case QV4::Moth::Instr::Type::DeadTemporalZoneCheck:
case QV4::Moth::Instr::Type::IteratorNext:
case QV4::Moth::Instr::Type::IteratorNextForYieldStar:
- if (m_state.changedRegisterIndex() == Accumulator && !m_error->isValid()) {
- setError(u"Instruction is not expected to populate the accumulator"_s);
+ if (m_state.changedRegisterIndex() == Accumulator && m_errors->isEmpty()) {
+ addError(u"Instruction is not expected to populate the accumulator"_s);
return;
}
break;
@@ -2752,21 +2759,22 @@ void QQmlJSTypePropagator::endInstruction(QV4::Moth::Instr::Type instr)
// If the instruction is expected to produce output, save it in the register set
// for the next instruction.
if ((!m_state.changedRegister().isValid() || m_state.changedRegisterIndex() != Accumulator)
- && !m_error->isValid()) {
- setError(u"Instruction is expected to populate the accumulator"_s);
+ && m_errors->isEmpty()) {
+ addError(u"Instruction is expected to populate the accumulator"_s);
return;
}
}
- if (!(m_error->isValid() && m_error->isError())
- && instr != QV4::Moth::Instr::Type::DeadTemporalZoneCheck) {
+ const auto noError = std::none_of(m_errors->cbegin(), m_errors->cend(),
+ [](const auto &e) { return e.isError(); });
+ if (noError && instr != QV4::Moth::Instr::Type::DeadTemporalZoneCheck) {
// An instruction needs to have side effects or write to another register otherwise it's a
// noop. DeadTemporalZoneCheck is not needed by the compiler and is ignored.
Q_ASSERT(m_state.hasSideEffects() || m_state.changedRegisterIndex() != -1);
}
if (m_state.changedRegisterIndex() != InvalidRegister) {
- Q_ASSERT(m_error->isValid() || m_state.changedRegister().isValid());
+ Q_ASSERT(!m_errors->isEmpty() || m_state.changedRegister().isValid());
VirtualRegister &r = m_state.registers[m_state.changedRegisterIndex()];
r.content = m_state.changedRegister();
r.canMove = false;
@@ -2838,7 +2846,7 @@ QQmlJSRegisterContent QQmlJSTypePropagator::checkedInputRegister(int reg)
if (isArgument(reg))
return argumentType(reg);
- setError(u"Type error: could not infer the type of an expression"_s);
+ addError(u"Type error: could not infer the type of an expression"_s);
return {};
}
return regIt.value().content;
diff --git a/src/qmlcompiler/qqmljstypepropagator_p.h b/src/qmlcompiler/qqmljstypepropagator_p.h
index c9bbeb27cc..c7f0c5e049 100644
--- a/src/qmlcompiler/qqmljstypepropagator_p.h
+++ b/src/qmlcompiler/qqmljstypepropagator_p.h
@@ -28,10 +28,11 @@ struct Q_QMLCOMPILER_EXPORT QQmlJSTypePropagator : public QQmlJSCompilePass
{
QQmlJSTypePropagator(const QV4::Compiler::JSUnitGenerator *unitGenerator,
const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
- BasicBlocks basicBlocks = {}, InstructionAnnotations annotations = {},
+ QList<QQmlJS::DiagnosticMessage> *errors, BasicBlocks basicBlocks = {},
+ InstructionAnnotations annotations = {},
QQmlSA::PassManager *passManager = nullptr);
- BlocksAndAnnotations run(const Function *m_function, QQmlJS::DiagnosticMessage *error);
+ BlocksAndAnnotations run(const Function *m_function);
void generate_Ret() override;
void generate_Debug() override;