diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-09-05 14:56:24 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-09-07 10:31:53 +0000 |
commit | 15bdbd89639c29f88db1798de66066a4a95759c0 (patch) | |
tree | fd06324c900c9eb662f3f64cb1d1f1d45186ecb3 /src/qml/compiler/qv4compilercontrolflow_p.h | |
parent | 06e3ff28bb52500ae45f0c174ff8cd746593855c (diff) |
Fix exception handling while destructuring
When an exception happens during destructuring, IteratorClose
needs to be called, unless the exception happened inside the
IteratorNext call (in that case the iterator is assumed to be
invalid and we shouldn't call close on it).
Implement this, by ensuring that we set the done return variable
of IteratorNext to true whenever IteratorNext throws an exception.
IteratorClose will check the done state and not do anything in that
case.
Change-Id: I73a27f855f2c4d3134b8cc8980e64bf797d03886
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compilercontrolflow_p.h')
-rw-r--r-- | src/qml/compiler/qv4compilercontrolflow_p.h | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h index 1884b33588..e7f3a18a6d 100644 --- a/src/qml/compiler/qv4compilercontrolflow_p.h +++ b/src/qml/compiler/qv4compilercontrolflow_p.h @@ -188,33 +188,42 @@ struct ControlFlowUnwind : public ControlFlow } }; -struct ControlFlowLoop : public ControlFlowUnwind +struct ControlFlowUnwindCleanup : public ControlFlowUnwind { - QString loopLabel; - BytecodeGenerator::Label *breakLabel = nullptr; - BytecodeGenerator::Label *continueLabel = nullptr; - std::function<void()> unwind = nullptr; + std::function<void()> cleanup = nullptr; - ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel = nullptr, std::function<void()> unwind = nullptr) - : ControlFlowUnwind(cg, Loop), loopLabel(ControlFlow::loopLabel()), breakLabel(breakLabel), continueLabel(continueLabel), unwind(unwind) + ControlFlowUnwindCleanup(Codegen *cg, std::function<void()> cleanup, Type type = Block) + : ControlFlowUnwind(cg, type), cleanup(cleanup) { - if (unwind != nullptr) { + if (cleanup) { setupUnwindHandler(); generator()->setUnwindHandler(&unwindLabel); } } - ~ControlFlowLoop() { - if (unwind != nullptr) { + ~ControlFlowUnwindCleanup() { + if (cleanup) { unwindLabel.link(); generator()->setUnwindHandler(parentUnwindHandler()); - unwind(); + cleanup(); emitUnwindHandler(); } } bool requiresUnwind() override { - return unwind != nullptr; + return cleanup != nullptr; + } +}; + +struct ControlFlowLoop : public ControlFlowUnwindCleanup +{ + QString loopLabel; + BytecodeGenerator::Label *breakLabel = nullptr; + BytecodeGenerator::Label *continueLabel = nullptr; + + ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel = nullptr, std::function<void()> cleanup = nullptr) + : ControlFlowUnwindCleanup(cg, cleanup, Loop), loopLabel(ControlFlow::loopLabel()), breakLabel(breakLabel), continueLabel(continueLabel) + { } BytecodeGenerator::Label getUnwindTarget(UnwindType type, const QString &label) override { |