From 980c6e7e967d4ad2870a9444c245fb054fdcfeea Mon Sep 17 00:00:00 2001
From: Hecate2 <2474101468@qq.com>
Date: Wed, 15 Jan 2025 10:44:01 +0800
Subject: [PATCH 1/4] fix break in try-catch-finally
---
.../MethodConvert/Statement/BreakStatement.cs | 31 +++-
.../Statement/CommonForEachStatement.cs | 16 ++
.../MethodConvert/Statement/DoStatement.cs | 4 +
.../MethodConvert/Statement/ForStatement.cs | 4 +
.../Statement/LabeledStatement.cs | 1 +
.../MethodConvert/Statement/Statement.cs | 45 +++++
.../Statement/SwitchStatement.cs | 4 +
.../MethodConvert/Statement/TryStatement.cs | 6 +
.../MethodConvert/Statement/WhileStatement.cs | 4 +
.../Analysers/InstructionCoverage.cs | 10 +-
.../Contract_Break.cs | 57 +++++++
.../TestingArtifacts/Contract_Assert.cs | 12 +-
.../TestingArtifacts/Contract_Break.cs | 156 ++++++++++++++++++
.../TestingArtifacts/Contract_TryCatch.cs | 49 +++---
.../UnitTest_Break.cs | 16 ++
15 files changed, 376 insertions(+), 39 deletions(-)
create mode 100644 tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
create mode 100644 tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
create mode 100644 tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs
index 1339bef1a..7c1299fba 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs
@@ -44,10 +44,33 @@ internal partial class MethodConvert
private void ConvertBreakStatement(BreakStatementSyntax syntax)
{
using (InsertSequencePoint(syntax))
- if (_tryStack.TryPeek(out ExceptionHandling? result) && result.BreakTargetCount == 0)
- Jump(OpCode.ENDTRY_L, _breakTargets.Peek());
- else
- Jump(OpCode.JMP_L, _breakTargets.Peek());
+ {
+ int nestedTryWithFinally = 0;
+ foreach (StatementContext sc in _generalStatementStack)
+ {
+ if (sc.BreakTarget != null)
+ {
+ if (nestedTryWithFinally == 0)
+ Jump(OpCode.JMP_L, sc.BreakTarget);
+ else
+ Jump(OpCode.ENDTRY_L, sc.BreakTarget);
+ return;
+ }
+ if (sc.StatementSyntax is TryStatementSyntax && sc.FinallyTarget != null)
+ {
+ if (nestedTryWithFinally > 0)
+ throw new CompilationException(sc.StatementSyntax, DiagnosticId.SyntaxNotSupported, "Neo VM does not support `break` from multi-layered nested try-catch with finally.");
+ if (sc.TryState != ExceptionHandlingState.Finally)
+ nestedTryWithFinally++;
+ else // Not likely to happen. C# syntax analyzer should forbid break in finally
+ throw new CompilationException(sc.StatementSyntax, DiagnosticId.SyntaxNotSupported, "Cannot break in finally.");
+ }
+ }
+ // break is not handled
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Cannot find what to break. " +
+ $"If not syntax error, this is probably a compiler bug. " +
+ $"Check whether the compiler is leaving out a push into {nameof(_generalStatementStack)}.");
+ }
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs
index 82a4a9670..dea86ada5 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs
@@ -73,6 +73,8 @@ private void ConvertIteratorForEachStatement(SemanticModel model, ForEachStateme
byte elementIndex = AddLocalVariable(elementSymbol);
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
using (InsertSequencePoint(syntax.ForEachKeyword))
{
ConvertExpression(model, syntax.Expression);
@@ -97,6 +99,8 @@ private void ConvertIteratorForEachStatement(SemanticModel model, ForEachStateme
RemoveLocalVariable(elementSymbol);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
///
@@ -151,6 +155,8 @@ private void ConvertIteratorForEachVariableStatement(SemanticModel model, ForEac
byte iteratorIndex = AddAnonymousVariable();
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
using (InsertSequencePoint(syntax.ForEachKeyword))
{
ConvertExpression(model, syntax.Expression);
@@ -190,6 +196,8 @@ private void ConvertIteratorForEachVariableStatement(SemanticModel model, ForEac
RemoveLocalVariable(symbol);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
///
@@ -220,6 +228,8 @@ private void ConvertArrayForEachStatement(SemanticModel model, ForEachStatementS
byte elementIndex = AddLocalVariable(elementSymbol);
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
using (InsertSequencePoint(syntax.ForEachKeyword))
{
ConvertExpression(model, syntax.Expression);
@@ -255,6 +265,8 @@ private void ConvertArrayForEachStatement(SemanticModel model, ForEachStatementS
RemoveLocalVariable(elementSymbol);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
///
@@ -284,6 +296,8 @@ private void ConvertArrayForEachVariableStatement(SemanticModel model, ForEachVa
byte iIndex = AddAnonymousVariable();
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
using (InsertSequencePoint(syntax.ForEachKeyword))
{
ConvertExpression(model, syntax.Expression);
@@ -334,6 +348,8 @@ private void ConvertArrayForEachVariableStatement(SemanticModel model, ForEachVa
RemoveLocalVariable(symbol);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs
index 5cfd50795..61ef83c92 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs
@@ -48,6 +48,8 @@ private void ConvertDoStatement(SemanticModel model, DoStatementSyntax syntax)
JumpTarget breakTarget = new();
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
startTarget.Instruction = AddInstruction(OpCode.NOP);
ConvertStatement(model, syntax.Statement);
continueTarget.Instruction = AddInstruction(OpCode.NOP);
@@ -56,6 +58,8 @@ private void ConvertDoStatement(SemanticModel model, DoStatementSyntax syntax)
breakTarget.Instruction = AddInstruction(OpCode.NOP);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs
index 2b844ed13..bcb344c5b 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs
@@ -62,6 +62,8 @@ private void ConvertForStatement(SemanticModel model, ForStatementSyntax syntax)
JumpTarget breakTarget = new();
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
foreach (var (variable, symbol) in variables)
{
byte variableIndex = AddLocalVariable(symbol);
@@ -99,6 +101,8 @@ private void ConvertForStatement(SemanticModel model, ForStatementSyntax syntax)
RemoveLocalVariable(symbol);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs
index 4f1855111..4a94710f3 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs
@@ -51,6 +51,7 @@ private void ConvertLabeledStatement(SemanticModel model, LabeledStatementSyntax
instruction.OpCode = OpCode.JMP_L;
target.Instruction = AddInstruction(OpCode.NOP);
ConvertStatement(model, syntax.Statement);
+ //_generalStatementStack.Peek().AddLabel(symbol, target);
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
index 5923bd5e6..bc1ddf548 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
@@ -10,11 +10,56 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Neo.VM;
+using System.Collections.Generic;
namespace Neo.Compiler
{
internal partial class MethodConvert
{
+ ///
+ /// Store the contexts of goto, break, continue targets
+ ///
+ internal class StatementContext(StatementSyntax statementSyntax,
+ JumpTarget? breakTarget = null, JumpTarget? continueTarget = null,
+ ExceptionHandlingState? tryState = null,
+ JumpTarget? catchTarget = null, JumpTarget? finallyTarget = null, JumpTarget? endFinallyTarget = null,
+ Dictionary? gotoLabels = null,
+ Dictionary? switchLabels = null
+ //StatementSyntax? parentStatement = null,
+ //HashSet? childrenStatements = null
+ )
+ {
+ public readonly StatementSyntax StatementSyntax = statementSyntax;
+ public readonly JumpTarget? BreakTarget = breakTarget;
+ public readonly JumpTarget? ContinueTarget = continueTarget;
+ public /*readonly*/ ExceptionHandlingState? TryState = tryState;
+ public readonly JumpTarget? CatchTarget = catchTarget;
+ public readonly JumpTarget? FinallyTarget = finallyTarget;
+ public readonly JumpTarget? EndFinallyTarget = endFinallyTarget;
+ public /*readonly*/ Dictionary? GotoLabels = gotoLabels;
+ public /*readonly*/ Dictionary? SwitchLabels = switchLabels;
+ //public readonly StatementSyntax? ParentStatement = parentStatement;
+ //public readonly HashSet? ChildrenStatements = childrenStatements;
+
+ public bool AddLabel(ILabelSymbol label, JumpTarget target)
+ {
+ if (GotoLabels == null)
+ GotoLabels = [];
+ return GotoLabels.TryAdd(label, target);
+ }
+ public bool AddLabel(SwitchLabelSyntax label, JumpTarget target)
+ {
+ if (SwitchLabels == null)
+ SwitchLabels = [];
+ return SwitchLabels.TryAdd(label, target);
+ }
+ public bool ContainsLabel(ILabelSymbol label) => GotoLabels is not null && GotoLabels.ContainsKey(label);
+ public bool ContainsLabel(SwitchLabelSyntax label) => SwitchLabels is not null && SwitchLabels.ContainsKey(label);
+ }
+
+ private readonly Stack _generalStatementStack = new();
+
private void ConvertStatement(SemanticModel model, StatementSyntax statement)
{
switch (statement)
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs
index 0070053c2..d62585e92 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs
@@ -57,6 +57,8 @@ private void ConvertSwitchStatement(SemanticModel model, SwitchStatementSyntax s
JumpTarget breakTarget = new();
byte anonymousIndex = AddAnonymousVariable();
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, switchLabels: labels.ToDictionary());
+ _generalStatementStack.Push(sc);
using (InsertSequencePoint(syntax.Expression))
{
ConvertExpression(model, syntax.Expression);
@@ -111,6 +113,8 @@ private void ConvertSwitchStatement(SemanticModel model, SwitchStatementSyntax s
breakTarget.Instruction = AddInstruction(OpCode.NOP);
PopSwitchLabels();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs
index b65d24582..020dc6a30 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs
@@ -53,6 +53,8 @@ private void ConvertTryStatement(SemanticModel model, TryStatementSyntax syntax)
JumpTarget catchTarget = new();
JumpTarget finallyTarget = new();
JumpTarget endTarget = new();
+ StatementContext sc = new(syntax, catchTarget: catchTarget, finallyTarget: finallyTarget, endFinallyTarget: endTarget, tryState: ExceptionHandlingState.Try);
+ _generalStatementStack.Push(sc);
AddInstruction(new Instruction { OpCode = OpCode.TRY_L, Target = catchTarget, Target2 = finallyTarget });
_tryStack.Push(new ExceptionHandling { State = ExceptionHandlingState.Try });
ConvertStatement(model, syntax.Block);
@@ -65,6 +67,7 @@ private void ConvertTryStatement(SemanticModel model, TryStatementSyntax syntax)
if (catchClause.Filter is not null)
throw new CompilationException(catchClause.Filter, DiagnosticId.CatchFilter, $"Unsupported syntax: {catchClause.Filter}");
_tryStack.Peek().State = ExceptionHandlingState.Catch;
+ sc.TryState = ExceptionHandlingState.Catch;
ILocalSymbol? exceptionSymbol = null;
byte exceptionIndex;
if (catchClause.Declaration is null)
@@ -92,12 +95,15 @@ private void ConvertTryStatement(SemanticModel model, TryStatementSyntax syntax)
if (syntax.Finally is not null)
{
_tryStack.Peek().State = ExceptionHandlingState.Finally;
+ sc.TryState = ExceptionHandlingState.Finally;
finallyTarget.Instruction = AddInstruction(OpCode.NOP);
ConvertStatement(model, syntax.Finally.Block);
AddInstruction(OpCode.ENDFINALLY);
}
endTarget.Instruction = AddInstruction(OpCode.NOP);
_tryStack.Pop();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs
index 6daeeff07..9c226a86b 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs
@@ -45,6 +45,8 @@ private void ConvertWhileStatement(SemanticModel model, WhileStatementSyntax syn
JumpTarget breakTarget = new();
PushContinueTarget(continueTarget);
PushBreakTarget(breakTarget);
+ StatementContext sc = new(syntax, breakTarget: breakTarget, continueTarget: continueTarget);
+ _generalStatementStack.Push(sc);
continueTarget.Instruction = AddInstruction(OpCode.NOP);
using (InsertSequencePoint(syntax.Condition))
{
@@ -56,6 +58,8 @@ private void ConvertWhileStatement(SemanticModel model, WhileStatementSyntax syn
breakTarget.Instruction = AddInstruction(OpCode.NOP);
PopContinueTarget();
PopBreakTarget();
+ if (_generalStatementStack.Pop() != sc)
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/Optimizer/Analysers/InstructionCoverage.cs b/src/Neo.Compiler.CSharp/Optimizer/Analysers/InstructionCoverage.cs
index 6fd146dc4..171127a59 100644
--- a/src/Neo.Compiler.CSharp/Optimizer/Analysers/InstructionCoverage.cs
+++ b/src/Neo.Compiler.CSharp/Optimizer/Analysers/InstructionCoverage.cs
@@ -30,7 +30,7 @@ public enum TryType
FINALLY = 1 << 3,
}
- [DebuggerDisplay("{catchAddr}, {finallyAddr}, {tryStateType}, {continueAfterFinally}")]
+ [DebuggerDisplay("{catchAddr}, {finallyAddr}, {tryType}, {continueAfterFinally}")]
public struct TryState
{
public int catchAddr { get; init; }
@@ -248,7 +248,7 @@ public BranchType CoverInstruction(int addr, Stack? tryStack = null,
if (continueAfterFinally)
return coveredMap[entranceAddr] = CoverInstruction(finallyAddr, tryStack, jumpFromBasicBlockEntranceAddr: entranceAddr);
// FINALLY is OK, but throwed in previous TRY (without catch) or CATCH
- return BranchType.THROW; // Do not set coveredMap[entranceAddr] = BranchType.THROW;
+ return value; // Do not set coveredMap[entranceAddr] = BranchType.THROW;
}
//if (instruction.OpCode != OpCode.NOP)
{
@@ -274,7 +274,8 @@ public BranchType CoverInstruction(int addr, Stack? tryStack = null,
returnedType = BranchType.ABORT;
foreach (int callaTarget in pushaTargets.Keys)
{
- BranchType singleCallaResult = CoverInstruction(callaTarget, tryStack, jumpFromBasicBlockEntranceAddr: entranceAddr);
+ // Use `tryStack: null` to avoid using current try stack in a deeper call stack
+ BranchType singleCallaResult = CoverInstruction(callaTarget, tryStack: null, jumpFromBasicBlockEntranceAddr: entranceAddr);
if (singleCallaResult < returnedType)
returnedType = singleCallaResult;
// TODO: if a PUSHA cannot be covered, do not add it as a CALLA target
@@ -283,7 +284,8 @@ public BranchType CoverInstruction(int addr, Stack? tryStack = null,
else
{
int callTarget = ComputeJumpTarget(addr, instruction);
- returnedType = CoverInstruction(callTarget, tryStack, jumpFromBasicBlockEntranceAddr: entranceAddr);
+ // Use `tryStack: null` to avoid using current try stack in a deeper call stack
+ returnedType = CoverInstruction(callTarget, tryStack: null, jumpFromBasicBlockEntranceAddr: entranceAddr);
}
if (returnedType == BranchType.OK)
return coveredMap[entranceAddr] = CoverInstruction(addr + instruction.Size, tryStack, continueFromBasicBlockEntranceAddr: entranceAddr);
diff --git a/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs b/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
new file mode 100644
index 000000000..9ff7792af
--- /dev/null
+++ b/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
@@ -0,0 +1,57 @@
+using Neo.SmartContract.Framework;
+using Neo.SmartContract.Framework.Attributes;
+using Neo.SmartContract.Framework.Services;
+
+namespace Neo.Compiler.CSharp.TestContracts
+{
+ public class Contract_Break : SmartContract.Framework.SmartContract
+ {
+ public static void BreakInTryCatch()
+ {
+ Storage.Put("\xff\x00", "\x00");
+ foreach (object i in Storage.Find("\xff"))
+ try { break; }
+ finally { Storage.Put("\xff\x00", "\x01"); }
+ ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x01");
+ foreach (object i in Storage.Find("\xff"))
+ try { throw new System.Exception(); }
+ catch
+ {
+ do { break; }
+ while (true);
+ Storage.Put("\xff\x00", "\x00");
+ break; // break foreach; should execute finally
+ }
+ finally
+ {
+ ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x00");
+ foreach (int _ in new int[] { 0, 1, 2 })
+ {
+ Storage.Put("\xff\x00", "\x02");
+ break;
+ }
+ }
+ ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x02");
+ foreach (object i in Storage.Find("\xff"))
+ try
+ {
+ for (int j = 0; j < 3;)
+ break;
+ throw new System.Exception();
+ }
+ catch
+ {
+ int j = 0;
+ while (j < 3)
+ break;
+ break; // foreach; should execute finally
+ }
+ finally
+ {
+ ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x02");
+ Storage.Put("\xff\x00", "\x03");
+ }
+ ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x03");
+ }
+ }
+}
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Assert.cs b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Assert.cs
index 62bcccb86..4b462439f 100644
--- a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Assert.cs
+++ b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Assert.cs
@@ -15,7 +15,7 @@ public abstract class Contract_Assert(Neo.SmartContract.Testing.SmartContractIni
///
/// Optimization: "All"
///
- public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhXAQAQcAg5EXAJOQBkcGhAVwEAEHA063ARcGhAVwIAEHA7CA003HA9CnERcD0FEnA/aEBXAgAQcDsRFxFwDAlleGNlcHRpb246cTS2cD0FEnA/aEBXAgAQcDsHDBFwPQBxEnA9ADSbQDbfjGM="));
+ public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGtXAQAQcAg5EXAJOQBkcGhAVwEAEHA063ARcGhAVwIAEHA7CA003HA9CnERcD0FEnA/aEBXAgAQcDsRFxFwDAlleGNlcHRpb246cTS2cD0FEnA/aEBXAgAQcDsHDBFwPQtxEnA9BjSbcD9oQKrgmAI="));
#endregion
@@ -73,19 +73,23 @@ public abstract class Contract_Assert(Neo.SmartContract.Testing.SmartContractIni
/// Unsafe method
///
///
- /// Script: VwIAEHA7BwwRcD0AcRJwPQA0mw==
+ /// Script: VwIAEHA7BwwRcD0LcRJwPQY0m3A/aEA=
/// INITSLOT 0200 [64 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC0 [2 datoshi]
/// TRY 070C [4 datoshi]
/// PUSH1 [1 datoshi]
/// STLOC0 [2 datoshi]
- /// ENDTRY 00 [4 datoshi]
+ /// ENDTRY 0B [4 datoshi]
/// STLOC1 [2 datoshi]
/// PUSH2 [1 datoshi]
/// STLOC0 [2 datoshi]
- /// ENDTRY 00 [4 datoshi]
+ /// ENDTRY 06 [4 datoshi]
/// CALL 9B [512 datoshi]
+ /// STLOC0 [2 datoshi]
+ /// ENDFINALLY [4 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// RET [0 datoshi]
///
[DisplayName("testAssertInFinally")]
public abstract BigInteger? TestAssertInFinally();
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
new file mode 100644
index 000000000..306a105ff
--- /dev/null
+++ b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
@@ -0,0 +1,156 @@
+using Neo.Cryptography.ECC;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Numerics;
+
+namespace Neo.SmartContract.Testing;
+
+public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInitialize initialize) : Neo.SmartContract.Testing.SmartContract(initialize), IContractInfo
+{
+ #region Compiled data
+
+ public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Break"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""breakInTryCatch"",""parameters"":[],""returntype"":""Void"",""offset"":0,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
+
+ ///
+ /// Optimization: "All"
+ ///
+ public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1DAVcGAAwBAAwC/wA1CgEAABAMAf81EQEAAHAiG2hB81S/HXE7AAU9FwwBAQwC/wA15gAAAD9oQZwI7Zwk4QwC/wA19AAAAAwBAZc5EAwB/zXWAAAAcCJWaEHzVL8dcTsPHgwJZXhjZXB0aW9uOnIMAQAMAv8ANaAAAAA9OQwC/wA1tQAAAAwBAJc5EhEQE8BKcspzEHQiEWpsznUMAQIMAv8ANHMiBmxrMO8/aEGcCO2cJKYMAv8ANH4MAQKXORAMAf80Y3AiPGhB81S/HXE7FR4QcmoTtUUMCWV4Y2VwdGlvbjpyEHNrE7VFPR8MAv8ANEUMAQKXOQwBAwwC/wA0Fz9oQZwI7ZwkwAwC/wA0KAwBA5c5QFcAAnl4QZv2Z85B5j8YhEBXAAJ5eEH2tGviQd8wuJpAVwABeEH2tGviQZJd6DFAEImfDw=="));
+
+ #endregion
+
+ #region Unsafe methods
+
+ ///
+ /// Unsafe method
+ ///
+ ///
+ /// Script: VwYADAEADAL/ADUKAQAAEAwB/zURAQAAcCIbaEHzVL8dcTsABT0XDAEBDAL/ADXmAAAAP2hBnAjtnCThDAL/ADX0AAAADAEBlzkQDAH/NdYAAABwIlZoQfNUvx1xOw8eDAlleGNlcHRpb246cgwBAAwC/wA1oAAAAD05DAL/ADW1AAAADAEAlzkSERATwEpyynMQdCIRamzOdQwBAgwC/wA0cyIGbGsw7z9oQZwI7ZwkpgwC/wA0fgwBApc5EAwB/zRjcCI8aEHzVL8dcTsVHhByahO1RQwJZXhjZXB0aW9uOnIQc2sTtUU9HwwC/wA0RQwBApc5DAEDDAL/ADQXP2hBnAjtnCTADAL/ADQoDAEDlzlA
+ /// INITSLOT 0600 [64 datoshi]
+ /// PUSHDATA1 00 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL_L 0A010000 [512 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// PUSHDATA1 FF '?' [8 datoshi]
+ /// CALL_L 11010000 [512 datoshi]
+ /// STLOC0 [2 datoshi]
+ /// JMP 1B [2 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// SYSCALL F354BF1D 'System.Iterator.Value' [16 datoshi]
+ /// STLOC1 [2 datoshi]
+ /// TRY 0005 [4 datoshi]
+ /// ENDTRY 17 [4 datoshi]
+ /// PUSHDATA1 01 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL_L E6000000 [512 datoshi]
+ /// ENDFINALLY [4 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
+ /// JMPIF E1 [2 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL_L F4000000 [512 datoshi]
+ /// PUSHDATA1 01 [8 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// PUSHDATA1 FF '?' [8 datoshi]
+ /// CALL_L D6000000 [512 datoshi]
+ /// STLOC0 [2 datoshi]
+ /// JMP 56 [2 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// SYSCALL F354BF1D 'System.Iterator.Value' [16 datoshi]
+ /// STLOC1 [2 datoshi]
+ /// TRY 0F1E [4 datoshi]
+ /// PUSHDATA1 657863657074696F6E 'exception' [8 datoshi]
+ /// THROW [512 datoshi]
+ /// STLOC2 [2 datoshi]
+ /// PUSHDATA1 00 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL_L A0000000 [512 datoshi]
+ /// ENDTRY 39 [4 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL_L B5000000 [512 datoshi]
+ /// PUSHDATA1 00 [8 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// PUSH2 [1 datoshi]
+ /// PUSH1 [1 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// PUSH3 [1 datoshi]
+ /// PACK [2048 datoshi]
+ /// DUP [2 datoshi]
+ /// STLOC2 [2 datoshi]
+ /// SIZE [4 datoshi]
+ /// STLOC3 [2 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// STLOC4 [2 datoshi]
+ /// JMP 11 [2 datoshi]
+ /// LDLOC2 [2 datoshi]
+ /// LDLOC4 [2 datoshi]
+ /// PICKITEM [64 datoshi]
+ /// STLOC5 [2 datoshi]
+ /// PUSHDATA1 02 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 73 [512 datoshi]
+ /// JMP 06 [2 datoshi]
+ /// LDLOC4 [2 datoshi]
+ /// LDLOC3 [2 datoshi]
+ /// JMPLT EF [2 datoshi]
+ /// ENDFINALLY [4 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
+ /// JMPIF A6 [2 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 7E [512 datoshi]
+ /// PUSHDATA1 02 [8 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// PUSHDATA1 FF '?' [8 datoshi]
+ /// CALL 63 [512 datoshi]
+ /// STLOC0 [2 datoshi]
+ /// JMP 3C [2 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// SYSCALL F354BF1D 'System.Iterator.Value' [16 datoshi]
+ /// STLOC1 [2 datoshi]
+ /// TRY 151E [4 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// STLOC2 [2 datoshi]
+ /// LDLOC2 [2 datoshi]
+ /// PUSH3 [1 datoshi]
+ /// LT [8 datoshi]
+ /// DROP [2 datoshi]
+ /// PUSHDATA1 657863657074696F6E 'exception' [8 datoshi]
+ /// THROW [512 datoshi]
+ /// STLOC2 [2 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// STLOC3 [2 datoshi]
+ /// LDLOC3 [2 datoshi]
+ /// PUSH3 [1 datoshi]
+ /// LT [8 datoshi]
+ /// DROP [2 datoshi]
+ /// ENDTRY 1F [4 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 45 [512 datoshi]
+ /// PUSHDATA1 02 [8 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// PUSHDATA1 03 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 17 [512 datoshi]
+ /// ENDFINALLY [4 datoshi]
+ /// LDLOC0 [2 datoshi]
+ /// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
+ /// JMPIF C0 [2 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 28 [512 datoshi]
+ /// PUSHDATA1 03 [8 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// RET [0 datoshi]
+ ///
+ [DisplayName("breakInTryCatch")]
+ public abstract void BreakInTryCatch();
+
+ #endregion
+}
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_TryCatch.cs b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_TryCatch.cs
index 6fe6a998c..7c3e4a49b 100644
--- a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_TryCatch.cs
+++ b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_TryCatch.cs
@@ -10,12 +10,12 @@ public abstract class Contract_TryCatch(Neo.SmartContract.Testing.SmartContractI
{
#region Compiled data
- public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_TryCatch"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""try01"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":0,""safe"":false},{""name"":""try02"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":92,""safe"":false},{""name"":""try03"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":101,""safe"":false},{""name"":""tryNest"",""parameters"":[{""name"":""throwInTry"",""type"":""Boolean""},{""name"":""throwInCatch"",""type"":""Boolean""},{""name"":""throwInFinally"",""type"":""Boolean""},{""name"":""enterOuterCatch"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":196,""safe"":false},{""name"":""throwInCatch"",""parameters"":[{""name"":""throwInTry"",""type"":""Boolean""},{""name"":""throwInCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":346,""safe"":false},{""name"":""tryFinally"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":403,""safe"":false},{""name"":""tryFinallyAndRethrow"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":487,""safe"":false},{""name"":""tryCatch"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":565,""safe"":false},{""name"":""tryWithTwoFinally"",""parameters"":[{""name"":""throwInInner"",""type"":""Boolean""},{""name"":""throwInOuter"",""type"":""Boolean""},{""name"":""enterInnerCatch"",""type"":""Boolean""},{""name"":""enterOuterCatch"",""type"":""Boolean""},{""name"":""enterInnerFinally"",""type"":""Boolean""},{""name"":""enterOuterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":645,""safe"":false},{""name"":""tryecpointCast"",""parameters"":[{""name"":""useInvalidECpoint"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":969,""safe"":false},{""name"":""tryvalidByteString2Ecpoint"",""parameters"":[{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1106,""safe"":false},{""name"":""tryinvalidByteArray2UInt160"",""parameters"":[{""name"":""useInvalidECpoint"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1230,""safe"":false},{""name"":""tryvalidByteArray2UInt160"",""parameters"":[{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1354,""safe"":false},{""name"":""tryinvalidByteArray2UInt256"",""parameters"":[{""name"":""useInvalidECpoint"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1465,""safe"":false},{""name"":""tryvalidByteArray2UInt256"",""parameters"":[{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1599,""safe"":false},{""name"":""tryNULL2Ecpoint_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":1711,""safe"":false},{""name"":""tryNULL2Uint160_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":1870,""safe"":false},{""name"":""tryNULL2Uint256_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":2029,""safe"":false},{""name"":""tryNULL2Bytestring_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":2188,""safe"":false},{""name"":""throwCall"",""parameters"":[],""returntype"":""Any"",""offset"":184,""safe"":false},{""name"":""tryUncatchableException"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":2336,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
+ public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_TryCatch"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""try01"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":0,""safe"":false},{""name"":""try02"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":92,""safe"":false},{""name"":""try03"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":101,""safe"":false},{""name"":""tryNest"",""parameters"":[{""name"":""throwInTry"",""type"":""Boolean""},{""name"":""throwInCatch"",""type"":""Boolean""},{""name"":""throwInFinally"",""type"":""Boolean""},{""name"":""enterOuterCatch"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":195,""safe"":false},{""name"":""throwInCatch"",""parameters"":[{""name"":""throwInTry"",""type"":""Boolean""},{""name"":""throwInCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":343,""safe"":false},{""name"":""tryFinally"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":400,""safe"":false},{""name"":""tryFinallyAndRethrow"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":484,""safe"":false},{""name"":""tryCatch"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":561,""safe"":false},{""name"":""tryWithTwoFinally"",""parameters"":[{""name"":""throwInInner"",""type"":""Boolean""},{""name"":""throwInOuter"",""type"":""Boolean""},{""name"":""enterInnerCatch"",""type"":""Boolean""},{""name"":""enterOuterCatch"",""type"":""Boolean""},{""name"":""enterInnerFinally"",""type"":""Boolean""},{""name"":""enterOuterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":640,""safe"":false},{""name"":""tryecpointCast"",""parameters"":[{""name"":""useInvalidECpoint"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":964,""safe"":false},{""name"":""tryvalidByteString2Ecpoint"",""parameters"":[{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1101,""safe"":false},{""name"":""tryinvalidByteArray2UInt160"",""parameters"":[{""name"":""useInvalidECpoint"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1225,""safe"":false},{""name"":""tryvalidByteArray2UInt160"",""parameters"":[{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1349,""safe"":false},{""name"":""tryinvalidByteArray2UInt256"",""parameters"":[{""name"":""useInvalidECpoint"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1460,""safe"":false},{""name"":""tryvalidByteArray2UInt256"",""parameters"":[{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":1594,""safe"":false},{""name"":""tryNULL2Ecpoint_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":1706,""safe"":false},{""name"":""tryNULL2Uint160_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":1865,""safe"":false},{""name"":""tryNULL2Uint256_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":2024,""safe"":false},{""name"":""tryNULL2Bytestring_1"",""parameters"":[{""name"":""setToNull"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Array"",""offset"":2183,""safe"":false},{""name"":""throwCall"",""parameters"":[],""returntype"":""Any"",""offset"":183,""safe"":false},{""name"":""tryUncatchableException"",""parameters"":[{""name"":""throwException"",""type"":""Boolean""},{""name"":""enterCatch"",""type"":""Boolean""},{""name"":""enterFinally"",""type"":""Boolean""}],""returntype"":""Integer"",""offset"":2331,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
///
/// Optimization: "All"
///
- public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1xCVcCAxBwOxYeEnB4Jg4MCWV4Y2VwdGlvbjo9QXF5JgQTcD05eiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAVwADenl4NJ5AVwIDEHA7DRUScHgmBTRGRT1BcXkmBBNwPTl6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEAMCWV4Y2VwdGlvbjpXAgQQcDtWADsNGBJweCYFNORFPUZxE3B5JgU02UU9O3omBDTRaEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFPz07cXsmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT0CaEBXAgMQcDsWKhFweCYODAlleGNlcHRpb246PRxxEnB5Jg4MCWV4Y2VwdGlvbjo9CHomBBNwPxRwaEBXAQIQcDsAFhJweCYODAlleGNlcHRpb246PTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAQIQcDsAEBJweCYINcT+//9FPTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAgIQcDsQABJweCYINXb+//9FPTtxeSY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFPQJoQFcCBhBwPM8AAAAHAQAAO0d/aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFeCYODAlleGNlcHRpb246PXBxeiY0aBKeSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3A9OHwmNGgTnkoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wP3kmDgwJZXhjZXB0aW9uOj1wcXsmNGgUnkoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wPTh9JjRoFZ5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcD9oQFcCAxBwO0NLEnB4JgwMBgoLDA0ODyIlDCECRwDbLpDZ8CxPn8hiq6ypJyX5W0/dzI1/+lOGk+z0Y6lK2CQJSsoAISgDOnE9QXF5JgQTcD05eiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAVwICEHA7Nj4ScAwhAkcA2y6Q2fAsT5/IYqusqScl+VtP3cyNf/pThpPs9GOpStgkCUrKACEoAzpxPUFxeCYEE3A9OXkmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQFcCAxBwOzY+EnB4JgwMBgoLDA0ODyIYDBR+7hqr62ftHXkdROT1/POukXGocUrYJAlKygAUKAM6cT1BcXkmBBNwPTl6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAgIQcDspMRJwDBR+7hqr62ftHXkdROT1/POukXGocUrYJAlKygAUKAM6cT1BcXgmBBNwPTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAgMQcDtASBJweCYVDAYKCwwNDg9K2CQrSsoAICglOgwg7c+GeRBOwpEaT+Ka19sjKkk+W5kPsdp68Me5iZSMiSVxPUFxeSYEE3A9OXomNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQFcCAhBwOyoyEnAMIO3PhnkQTsKRGk/imtfbIypJPluZD7HaevDHuYmUjIklcT1BcXgmBBNwPTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAwMQcAAhiNsoStgkCUrKACEoAzpxOwwUEnB4JgQLcT16cnkmBBNwPXJ6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEVpcmrYJjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aWgSv0BXAwMQcAAUiNsoStgkCUrKABQoAzpxOwwUEnB4JgQLcT16cnkmBBNwPXJ6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEVpcmrYJjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aWgSv0BXAwMQcAAgiNsoStgkCUrKACAoAzpxOwwUEnB4JgQLcT16cnkmBBNwPXJ6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEVpcmrYJjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aWgSv0BXAwMQcAwDMTIzcTsMFBJweCYEC3E9enJ5JgQTcD1yeiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFaXJq2CY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2loEr9AVwIDEHA7CxMScHgmAzg9QXF5JgQTcD05eiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAqNPIkQ=="));
+ public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1sCVcCAxBwOxYeEnB4Jg4MCWV4Y2VwdGlvbjo9QXF5JgQTcD05eiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAVwADenl4NJ5AVwIDEHA7DBQScHgmBDRFPUFxeSYEE3A9OXomNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQAwJZXhjZXB0aW9uOlcCBBBwO1QAOwwWEnB4JgQ05D1FcRNweSYENNo9O3omBDTTaEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFPz07cXsmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT0CaEBXAgMQcDsWKhFweCYODAlleGNlcHRpb246PRxxEnB5Jg4MCWV4Y2VwdGlvbjo9CHomBBNwPxRwaEBXAQIQcDsAFhJweCYODAlleGNlcHRpb246PTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAQIQcDsADxJweCYHNcb+//89OXkmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQFcCAhBwOw8AEnB4Jgc1ef7//z07cXkmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT0CaEBXAgYQcDzPAAAABwEAADtHf2hKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRXgmDgwJZXhjZXB0aW9uOj1wcXomNGgSnkoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wPTh8JjRoE55KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcD95Jg4MCWV4Y2VwdGlvbjo9cHF7JjRoFJ5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcD04fSY0aBWeSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3A/aEBXAgMQcDtDSxJweCYMDAYKCwwNDg8iJQwhAkcA2y6Q2fAsT5/IYqusqScl+VtP3cyNf/pThpPs9GOpStgkCUrKACEoAzpxPUFxeSYEE3A9OXomNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQFcCAhBwOzY+EnAMIQJHANsukNnwLE+fyGKrrKknJflbT93MjX/6U4aT7PRjqUrYJAlKygAhKAM6cT1BcXgmBBNwPTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAgMQcDs2PhJweCYMDAYKCwwNDg8iGAwUfu4aq+tn7R15HUTk9fzzrpFxqHFK2CQJSsoAFCgDOnE9QXF5JgQTcD05eiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAVwICEHA7KTEScAwUfu4aq+tn7R15HUTk9fzzrpFxqHFK2CQJSsoAFCgDOnE9QXF4JgQTcD05eSY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAVwIDEHA7QEgScHgmFQwGCgsMDQ4PStgkK0rKACAoJToMIO3PhnkQTsKRGk/imtfbIypJPluZD7HaevDHuYmUjIklcT1BcXkmBBNwPTl6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEBXAgIQcDsqMhJwDCDtz4Z5EE7CkRpP4prX2yMqST5bmQ+x2nrwx7mJlIyJJXE9QXF4JgQTcD05eSY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hAVwMDEHAAIYjbKErYJAlKygAhKAM6cTsMFBJweCYEC3E9enJ5JgQTcD1yeiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFaXJq2CY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2loEr9AVwMDEHAAFIjbKErYJAlKygAUKAM6cTsMFBJweCYEC3E9enJ5JgQTcD1yeiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFaXJq2CY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2loEr9AVwMDEHAAIIjbKErYJAlKygAgKAM6cTsMFBJweCYEC3E9enJ5JgQTcD1yeiY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFaXJq2CY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2loEr9AVwMDEHAMAzEyM3E7DBQScHgmBAtxPXpyeSYEE3A9cnomNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRWlyatgmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9paBK/QFcCAxBwOwsTEnB4JgM4PUFxeSYEE3A9OXomNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQM+f6pI="));
#endregion
@@ -138,17 +138,16 @@ public abstract class Contract_TryCatch(Neo.SmartContract.Testing.SmartContractI
/// Unsafe method
///
///
- /// Script: VwIDEHA7DRUScHgmBTRGRT1BcXkmBBNwPTl6JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEA=
+ /// Script: VwIDEHA7DBQScHgmBDRFPUFxeSYEE3A9OXomNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT9oQA==
/// INITSLOT 0203 [64 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC0 [2 datoshi]
- /// TRY 0D15 [4 datoshi]
+ /// TRY 0C14 [4 datoshi]
/// PUSH2 [1 datoshi]
/// STLOC0 [2 datoshi]
/// LDARG0 [2 datoshi]
- /// JMPIFNOT 05 [2 datoshi]
- /// CALL 46 [512 datoshi]
- /// DROP [2 datoshi]
+ /// JMPIFNOT 04 [2 datoshi]
+ /// CALL 45 [512 datoshi]
/// ENDTRY 41 [4 datoshi]
/// STLOC1 [2 datoshi]
/// LDARG1 [2 datoshi]
@@ -188,17 +187,16 @@ public abstract class Contract_TryCatch(Neo.SmartContract.Testing.SmartContractI
/// Unsafe method
///
///
- /// Script: VwICEHA7EAAScHgmCDV2/v//RT07cXkmNWhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT0CaEA=
+ /// Script: VwICEHA7DwAScHgmBzV5/v//PTtxeSY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFPQJoQA==
/// INITSLOT 0202 [64 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC0 [2 datoshi]
- /// TRY 1000 [4 datoshi]
+ /// TRY 0F00 [4 datoshi]
/// PUSH2 [1 datoshi]
/// STLOC0 [2 datoshi]
/// LDARG0 [2 datoshi]
- /// JMPIFNOT 08 [2 datoshi]
- /// CALL_L 76FEFFFF [512 datoshi]
- /// DROP [2 datoshi]
+ /// JMPIFNOT 07 [2 datoshi]
+ /// CALL_L 79FEFFFF [512 datoshi]
/// ENDTRY 3B [4 datoshi]
/// STLOC1 [2 datoshi]
/// LDARG1 [2 datoshi]
@@ -337,17 +335,16 @@ public abstract class Contract_TryCatch(Neo.SmartContract.Testing.SmartContractI
/// Unsafe method
///
///
- /// Script: VwECEHA7ABAScHgmCDXE/v//RT05eSY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFP2hA
+ /// Script: VwECEHA7AA8ScHgmBzXG/v//PTl5JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/aEA=
/// INITSLOT 0102 [64 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC0 [2 datoshi]
- /// TRY 0010 [4 datoshi]
+ /// TRY 000F [4 datoshi]
/// PUSH2 [1 datoshi]
/// STLOC0 [2 datoshi]
/// LDARG0 [2 datoshi]
- /// JMPIFNOT 08 [2 datoshi]
- /// CALL_L C4FEFFFF [512 datoshi]
- /// DROP [2 datoshi]
+ /// JMPIFNOT 07 [2 datoshi]
+ /// CALL_L C6FEFFFF [512 datoshi]
/// ENDTRY 39 [4 datoshi]
/// LDARG1 [2 datoshi]
/// JMPIFNOT 35 [2 datoshi]
@@ -500,30 +497,28 @@ public abstract class Contract_TryCatch(Neo.SmartContract.Testing.SmartContractI
/// Unsafe method
///
///
- /// Script: VwIEEHA7VgA7DRgScHgmBTTkRT1GcRNweSYFNNlFPTt6JgQ00WhKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9wRT89O3F7JjVoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU9AmhA
+ /// Script: VwIEEHA7VAA7DBYScHgmBDTkPUVxE3B5JgQ02j07eiYENNNoSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcEU/PTtxeyY1aEqcSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn3BFPQJoQA==
/// INITSLOT 0204 [64 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC0 [2 datoshi]
- /// TRY 5600 [4 datoshi]
- /// TRY 0D18 [4 datoshi]
+ /// TRY 5400 [4 datoshi]
+ /// TRY 0C16 [4 datoshi]
/// PUSH2 [1 datoshi]
/// STLOC0 [2 datoshi]
/// LDARG0 [2 datoshi]
- /// JMPIFNOT 05 [2 datoshi]
+ /// JMPIFNOT 04 [2 datoshi]
/// CALL E4 [512 datoshi]
- /// DROP [2 datoshi]
- /// ENDTRY 46 [4 datoshi]
+ /// ENDTRY 45 [4 datoshi]
/// STLOC1 [2 datoshi]
/// PUSH3 [1 datoshi]
/// STLOC0 [2 datoshi]
/// LDARG1 [2 datoshi]
- /// JMPIFNOT 05 [2 datoshi]
- /// CALL D9 [512 datoshi]
- /// DROP [2 datoshi]
+ /// JMPIFNOT 04 [2 datoshi]
+ /// CALL DA [512 datoshi]
/// ENDTRY 3B [4 datoshi]
/// LDARG2 [2 datoshi]
/// JMPIFNOT 04 [2 datoshi]
- /// CALL D1 [512 datoshi]
+ /// CALL D3 [512 datoshi]
/// LDLOC0 [2 datoshi]
/// DUP [2 datoshi]
/// INC [4 datoshi]
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs b/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs
new file mode 100644
index 000000000..f76a24893
--- /dev/null
+++ b/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs
@@ -0,0 +1,16 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.SmartContract.Testing;
+using System.Collections.Generic;
+
+namespace Neo.Compiler.CSharp.UnitTests
+{
+ [TestClass]
+ public class UnitTest_Break : DebugAndTestBase
+ {
+ [TestMethod]
+ public void TestBreakInTry()
+ {
+ Contract.BreakInTryCatch();
+ }
+ }
+}
From 1eceb0065c4edb2e2d42c8649399f265e6346969 Mon Sep 17 00:00:00 2001
From: Hecate2 <2474101468@qq.com>
Date: Thu, 16 Jan 2025 12:46:46 +0800
Subject: [PATCH 2/4] break from multiple try
---
.../MethodConvert/Statement/BreakStatement.cs | 47 ++++++-----
.../Statement/CommonForEachStatement.cs | 8 +-
.../MethodConvert/Statement/DoStatement.cs | 2 +-
.../MethodConvert/Statement/ForStatement.cs | 2 +-
.../MethodConvert/Statement/Statement.cs | 28 ++++++-
.../Statement/SwitchStatement.cs | 2 +-
.../MethodConvert/Statement/TryStatement.cs | 12 ++-
.../MethodConvert/Statement/WhileStatement.cs | 2 +-
.../Contract_Break.cs | 24 ++++--
.../TestingArtifacts/Contract_Break.cs | 81 +++++++++++++------
10 files changed, 146 insertions(+), 62 deletions(-)
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs
index 7c1299fba..3c0ca34a2 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/BreakStatement.cs
@@ -10,6 +10,8 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Neo.VM;
+using System.Collections.Generic;
+using System.Linq;
namespace Neo.Compiler
{
@@ -45,31 +47,36 @@ private void ConvertBreakStatement(BreakStatementSyntax syntax)
{
using (InsertSequencePoint(syntax))
{
- int nestedTryWithFinally = 0;
+ JumpTarget? breakTarget = null;
+ List visitedTry = []; // from shallow to deep
foreach (StatementContext sc in _generalStatementStack)
- {
+ {// start from the deepest context
+ // find the final break target
if (sc.BreakTarget != null)
{
- if (nestedTryWithFinally == 0)
- Jump(OpCode.JMP_L, sc.BreakTarget);
- else
- Jump(OpCode.ENDTRY_L, sc.BreakTarget);
- return;
- }
- if (sc.StatementSyntax is TryStatementSyntax && sc.FinallyTarget != null)
- {
- if (nestedTryWithFinally > 0)
- throw new CompilationException(sc.StatementSyntax, DiagnosticId.SyntaxNotSupported, "Neo VM does not support `break` from multi-layered nested try-catch with finally.");
- if (sc.TryState != ExceptionHandlingState.Finally)
- nestedTryWithFinally++;
- else // Not likely to happen. C# syntax analyzer should forbid break in finally
- throw new CompilationException(sc.StatementSyntax, DiagnosticId.SyntaxNotSupported, "Cannot break in finally.");
+ breakTarget = sc.BreakTarget;
+ break;
}
+ // stage the try stacks on the way
+ if (sc.StatementSyntax is TryStatementSyntax)
+ visitedTry.Add(sc);
}
- // break is not handled
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Cannot find what to break. " +
- $"If not syntax error, this is probably a compiler bug. " +
- $"Check whether the compiler is leaving out a push into {nameof(_generalStatementStack)}.");
+ if (breakTarget == null)
+ // break is not handled
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Cannot find what to break. " +
+ $"If not syntax error, this is probably a compiler bug. " +
+ $"Check whether the compiler is leaving out a push into {nameof(_generalStatementStack)}.");
+
+ foreach (StatementContext sc in visitedTry)
+ // start from the most external try
+ // internal try should ENDTRY, targeting the correct external break target
+ breakTarget = sc.AddEndTry(breakTarget);
+
+ Jump(OpCode.JMP_L, breakTarget);
+ // We could use ENDTRY if current statement calling `break` is a try statement,
+ // but this job can be done by the optimizer
+ // Note that, do not Jump(OpCode.ENDTRY_L, breakTarget) here,
+ // because the breakTarget here is already an ENDTRY_L for current try stack.
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs
index dea86ada5..c4c2237ce 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/CommonForEachStatement.cs
@@ -100,7 +100,7 @@ private void ConvertIteratorForEachStatement(SemanticModel model, ForEachStateme
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
///
@@ -197,7 +197,7 @@ private void ConvertIteratorForEachVariableStatement(SemanticModel model, ForEac
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
///
@@ -266,7 +266,7 @@ private void ConvertArrayForEachStatement(SemanticModel model, ForEachStatementS
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
///
@@ -349,7 +349,7 @@ private void ConvertArrayForEachVariableStatement(SemanticModel model, ForEachVa
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs
index 61ef83c92..bd2057aa2 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/DoStatement.cs
@@ -59,7 +59,7 @@ private void ConvertDoStatement(SemanticModel model, DoStatementSyntax syntax)
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs
index bcb344c5b..ae47e9abc 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/ForStatement.cs
@@ -102,7 +102,7 @@ private void ConvertForStatement(SemanticModel model, ForStatementSyntax syntax)
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
index bc1ddf548..1997e0657 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
@@ -11,7 +11,9 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Neo.VM;
+using Org.BouncyCastle.Asn1.X509;
using System.Collections.Generic;
+using System.Linq;
namespace Neo.Compiler
{
@@ -39,19 +41,37 @@ internal class StatementContext(StatementSyntax statementSyntax,
public readonly JumpTarget? EndFinallyTarget = endFinallyTarget;
public /*readonly*/ Dictionary? GotoLabels = gotoLabels;
public /*readonly*/ Dictionary? SwitchLabels = switchLabels;
+ // handles `break`, `continue` and `goto` in multi-layered nested try with finally
+ // key: target of this ENDTRY
+ // value: this ENDTRY
+ public Dictionary? AdditionalEndTryTargetToInstruction { get; protected set; } = null;
//public readonly StatementSyntax? ParentStatement = parentStatement;
//public readonly HashSet? ChildrenStatements = childrenStatements;
+ /// Jump target of this added ENDTRY
+ /// The added ENDTRY
+ ///
+ public JumpTarget AddEndTry(JumpTarget target)
+ {
+ if (StatementSyntax is not TryStatementSyntax)
+ throw new CompilationException(StatementSyntax, DiagnosticId.SyntaxNotSupported, $"Can only append ENDTRY for TryStatement. Got {typeof(StatementSyntax)} {StatementSyntax}. This is a compiler bug.");
+ AdditionalEndTryTargetToInstruction ??= [];
+ if (AdditionalEndTryTargetToInstruction.TryGetValue(target, out JumpTarget? existingEndTry))
+ return existingEndTry;
+ Instruction i = new() { OpCode = OpCode.ENDTRY_L, Target = target };
+ existingEndTry = new JumpTarget() { Instruction = i };
+ AdditionalEndTryTargetToInstruction.Add(target, existingEndTry);
+ return existingEndTry;
+ }
+
public bool AddLabel(ILabelSymbol label, JumpTarget target)
{
- if (GotoLabels == null)
- GotoLabels = [];
+ GotoLabels ??= [];
return GotoLabels.TryAdd(label, target);
}
public bool AddLabel(SwitchLabelSyntax label, JumpTarget target)
{
- if (SwitchLabels == null)
- SwitchLabels = [];
+ SwitchLabels ??= [];
return SwitchLabels.TryAdd(label, target);
}
public bool ContainsLabel(ILabelSymbol label) => GotoLabels is not null && GotoLabels.ContainsKey(label);
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs
index d62585e92..52f985782 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/SwitchStatement.cs
@@ -114,7 +114,7 @@ private void ConvertSwitchStatement(SemanticModel model, SwitchStatementSyntax s
PopSwitchLabels();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs
index 020dc6a30..6f19b30c3 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/TryStatement.cs
@@ -59,6 +59,11 @@ private void ConvertTryStatement(SemanticModel model, TryStatementSyntax syntax)
_tryStack.Push(new ExceptionHandling { State = ExceptionHandlingState.Try });
ConvertStatement(model, syntax.Block);
Jump(OpCode.ENDTRY_L, endTarget);
+ if (syntax.Catches.Count == 0 && sc.AdditionalEndTryTargetToInstruction != null)
+ // handles `break`, `continue` and `goto` in multi-layered nested try with finally
+ foreach (JumpTarget i in sc.AdditionalEndTryTargetToInstruction.Values)
+ AddInstruction(i.Instruction!);
+
if (syntax.Catches.Count > 1)
throw new CompilationException(syntax.Catches[1], DiagnosticId.MultiplyCatches, "Only support one single catch.");
if (syntax.Catches.Count > 0)
@@ -86,6 +91,11 @@ private void ConvertTryStatement(SemanticModel model, TryStatementSyntax syntax)
_exceptionStack.Push(exceptionIndex);
ConvertStatement(model, catchClause.Block);
Jump(OpCode.ENDTRY_L, endTarget);
+ if (sc.AdditionalEndTryTargetToInstruction != null)
+ // handles `break`, `continue` and `goto` in multi-layered nested try with finally
+ foreach (JumpTarget i in sc.AdditionalEndTryTargetToInstruction.Values)
+ AddInstruction(i.Instruction!);
+
if (exceptionSymbol is null)
RemoveAnonymousVariable(exceptionIndex);
else
@@ -103,7 +113,7 @@ private void ConvertTryStatement(SemanticModel model, TryStatementSyntax syntax)
endTarget.Instruction = AddInstruction(OpCode.NOP);
_tryStack.Pop();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs
index 9c226a86b..2643515cd 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/WhileStatement.cs
@@ -59,7 +59,7 @@ private void ConvertWhileStatement(SemanticModel model, WhileStatementSyntax syn
PopContinueTarget();
PopBreakTarget();
if (_generalStatementStack.Pop() != sc)
- throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside.");
+ throw new CompilationException(syntax, DiagnosticId.SyntaxNotSupported, $"Bad statement stack handling inside. This is a compiler bug.");
}
}
}
diff --git a/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs b/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
index 9ff7792af..25134c1ba 100644
--- a/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
+++ b/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
@@ -14,13 +14,17 @@ public static void BreakInTryCatch()
finally { Storage.Put("\xff\x00", "\x01"); }
ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x01");
foreach (object i in Storage.Find("\xff"))
- try { throw new System.Exception(); }
+ try
+ {
+ for (int j = 0; j < 3;)
+ throw new System.Exception();
+ }
catch
{
do { break; }
while (true);
- Storage.Put("\xff\x00", "\x00");
- break; // break foreach; should execute finally
+ try { break; } // break foreach; should execute finally
+ finally { Storage.Put("\xff\x00", "\x00"); }
}
finally
{
@@ -37,14 +41,24 @@ public static void BreakInTryCatch()
{
for (int j = 0; j < 3;)
break;
- throw new System.Exception();
}
catch
{
int j = 0;
while (j < 3)
break;
- break; // foreach; should execute finally
+ ExecutionEngine.Assert(j == 0);
+ try
+ {
+ Storage.Put("\xff\x00", "\x03");
+ throw;
+ }
+ catch { break; } // foreach; should execute finally
+ finally
+ {
+ ExecutionEngine.Assert(Storage.Get("\xff\x00")! == "\x03");
+ Storage.Put("\xff\x00", "\x02");
+ }
}
finally
{
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
index 306a105ff..ac164ec9a 100644
--- a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
+++ b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
@@ -15,7 +15,7 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
///
/// Optimization: "All"
///
- public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1DAVcGAAwBAAwC/wA1CgEAABAMAf81EQEAAHAiG2hB81S/HXE7AAU9FwwBAQwC/wA15gAAAD9oQZwI7Zwk4QwC/wA19AAAAAwBAZc5EAwB/zXWAAAAcCJWaEHzVL8dcTsPHgwJZXhjZXB0aW9uOnIMAQAMAv8ANaAAAAA9OQwC/wA1tQAAAAwBAJc5EhEQE8BKcspzEHQiEWpsznUMAQIMAv8ANHMiBmxrMO8/aEGcCO2cJKYMAv8ANH4MAQKXORAMAf80Y3AiPGhB81S/HXE7FR4QcmoTtUUMCWV4Y2VwdGlvbjpyEHNrE7VFPR8MAv8ANEUMAQKXOQwBAwwC/wA0Fz9oQZwI7ZwkwAwC/wA0KAwBA5c5QFcAAnl4QZv2Z85B5j8YhEBXAAJ5eEH2tGviQd8wuJpAVwABeEH2tGviQZJd6DFAEImfDw=="));
+ public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP2BAVcGAAwBAAwC/wA1SAEAABAMAf81TwEAAHAiG2hB81S/HXE7AAU9FwwBAQwC/wA1JAEAAD9oQZwI7Zwk4QwC/wA1MgEAAAwBAZc5EAwB/zUUAQAAcCJsaEHzVL8dcTsaMRByIg4MCWV4Y2VwdGlvbjpqE7Uk8T1LcjsAByIRPUsMAQAMAv8ANcwAAAA/PfEMAv8ANeAAAAAMAQCXORIREBPASnLKcxB0IhRqbM51DAECDAL/ADWeAAAAIgZsazDsP2hBnAjtnCSQDAL/ADWmAAAADAEClzkQDAH/NYgAAABwIl5oQfNUvx1xOwtAEHJqE7VFPUxyEHNrE7VFaxCXOTsOEwwBAwwC/wA0SWo6dCIZPTYMAv8ANFwMAQOXOQwBAgwC/wA0Lj896QwC/wA0RQwBApc5DAEDDAL/ADQXP2hBnAjtnCSeDAL/ADQoDAEDlzlAVwACeXhBm/ZnzkHmPxiEQFcAAnl4Qfa0a+JB3zC4mkBXAAF4Qfa0a+JBkl3oMUB6sNlU"));
#endregion
@@ -25,14 +25,14 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// Unsafe method
///
///
- /// Script: VwYADAEADAL/ADUKAQAAEAwB/zURAQAAcCIbaEHzVL8dcTsABT0XDAEBDAL/ADXmAAAAP2hBnAjtnCThDAL/ADX0AAAADAEBlzkQDAH/NdYAAABwIlZoQfNUvx1xOw8eDAlleGNlcHRpb246cgwBAAwC/wA1oAAAAD05DAL/ADW1AAAADAEAlzkSERATwEpyynMQdCIRamzOdQwBAgwC/wA0cyIGbGsw7z9oQZwI7ZwkpgwC/wA0fgwBApc5EAwB/zRjcCI8aEHzVL8dcTsVHhByahO1RQwJZXhjZXB0aW9uOnIQc2sTtUU9HwwC/wA0RQwBApc5DAEDDAL/ADQXP2hBnAjtnCTADAL/ADQoDAEDlzlA
+ /// Script: VwYADAEADAL/ADVIAQAAEAwB/zVPAQAAcCIbaEHzVL8dcTsABT0XDAEBDAL/ADUkAQAAP2hBnAjtnCThDAL/ADUyAQAADAEBlzkQDAH/NRQBAABwImxoQfNUvx1xOxoxEHIiDgwJZXhjZXB0aW9uOmoTtSTxPUtyOwAHIhE9SwwBAAwC/wA1zAAAAD898QwC/wA14AAAAAwBAJc5EhEQE8BKcspzEHQiFGpsznUMAQIMAv8ANZ4AAAAiBmxrMOw/aEGcCO2cJJAMAv8ANaYAAAAMAQKXORAMAf81iAAAAHAiXmhB81S/HXE7C0AQcmoTtUU9THIQc2sTtUVrEJc5Ow4TDAEDDAL/ADRJajp0Ihk9NgwC/wA0XAwBA5c5DAECDAL/ADQuPz3pDAL/ADRFDAEClzkMAQMMAv8ANBc/aEGcCO2cJJ4MAv8ANCgMAQOXOUA=
/// INITSLOT 0600 [64 datoshi]
/// PUSHDATA1 00 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L 0A010000 [512 datoshi]
+ /// CALL_L 48010000 [512 datoshi]
/// PUSH0 [1 datoshi]
/// PUSHDATA1 FF '?' [8 datoshi]
- /// CALL_L 11010000 [512 datoshi]
+ /// CALL_L 4F010000 [512 datoshi]
/// STLOC0 [2 datoshi]
/// JMP 1B [2 datoshi]
/// LDLOC0 [2 datoshi]
@@ -42,34 +42,46 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// ENDTRY 17 [4 datoshi]
/// PUSHDATA1 01 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L E6000000 [512 datoshi]
+ /// CALL_L 24010000 [512 datoshi]
/// ENDFINALLY [4 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
/// JMPIF E1 [2 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L F4000000 [512 datoshi]
+ /// CALL_L 32010000 [512 datoshi]
/// PUSHDATA1 01 [8 datoshi]
/// EQUAL [32 datoshi]
/// ASSERT [1 datoshi]
/// PUSH0 [1 datoshi]
/// PUSHDATA1 FF '?' [8 datoshi]
- /// CALL_L D6000000 [512 datoshi]
+ /// CALL_L 14010000 [512 datoshi]
/// STLOC0 [2 datoshi]
- /// JMP 56 [2 datoshi]
+ /// JMP 6C [2 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL F354BF1D 'System.Iterator.Value' [16 datoshi]
/// STLOC1 [2 datoshi]
- /// TRY 0F1E [4 datoshi]
+ /// TRY 1A31 [4 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// STLOC2 [2 datoshi]
+ /// JMP 0E [2 datoshi]
/// PUSHDATA1 657863657074696F6E 'exception' [8 datoshi]
/// THROW [512 datoshi]
+ /// LDLOC2 [2 datoshi]
+ /// PUSH3 [1 datoshi]
+ /// LT [8 datoshi]
+ /// JMPIF F1 [2 datoshi]
+ /// ENDTRY 4B [4 datoshi]
/// STLOC2 [2 datoshi]
+ /// TRY 0007 [4 datoshi]
+ /// JMP 11 [2 datoshi]
+ /// ENDTRY 4B [4 datoshi]
/// PUSHDATA1 00 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L A0000000 [512 datoshi]
- /// ENDTRY 39 [4 datoshi]
+ /// CALL_L CC000000 [512 datoshi]
+ /// ENDFINALLY [4 datoshi]
+ /// ENDTRY F1 [4 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L B5000000 [512 datoshi]
+ /// CALL_L E0000000 [512 datoshi]
/// PUSHDATA1 00 [8 datoshi]
/// EQUAL [32 datoshi]
/// ASSERT [1 datoshi]
@@ -84,44 +96,43 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// STLOC3 [2 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC4 [2 datoshi]
- /// JMP 11 [2 datoshi]
+ /// JMP 14 [2 datoshi]
/// LDLOC2 [2 datoshi]
/// LDLOC4 [2 datoshi]
/// PICKITEM [64 datoshi]
/// STLOC5 [2 datoshi]
/// PUSHDATA1 02 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL 73 [512 datoshi]
+ /// CALL_L 9E000000 [512 datoshi]
/// JMP 06 [2 datoshi]
/// LDLOC4 [2 datoshi]
/// LDLOC3 [2 datoshi]
- /// JMPLT EF [2 datoshi]
+ /// JMPLT EC [2 datoshi]
/// ENDFINALLY [4 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
- /// JMPIF A6 [2 datoshi]
+ /// JMPIF 90 [2 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL 7E [512 datoshi]
+ /// CALL_L A6000000 [512 datoshi]
/// PUSHDATA1 02 [8 datoshi]
/// EQUAL [32 datoshi]
/// ASSERT [1 datoshi]
/// PUSH0 [1 datoshi]
/// PUSHDATA1 FF '?' [8 datoshi]
- /// CALL 63 [512 datoshi]
+ /// CALL_L 88000000 [512 datoshi]
/// STLOC0 [2 datoshi]
- /// JMP 3C [2 datoshi]
+ /// JMP 5E [2 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL F354BF1D 'System.Iterator.Value' [16 datoshi]
/// STLOC1 [2 datoshi]
- /// TRY 151E [4 datoshi]
+ /// TRY 0B40 [4 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC2 [2 datoshi]
/// LDLOC2 [2 datoshi]
/// PUSH3 [1 datoshi]
/// LT [8 datoshi]
/// DROP [2 datoshi]
- /// PUSHDATA1 657863657074696F6E 'exception' [8 datoshi]
- /// THROW [512 datoshi]
+ /// ENDTRY 4C [4 datoshi]
/// STLOC2 [2 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC3 [2 datoshi]
@@ -129,7 +140,29 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// PUSH3 [1 datoshi]
/// LT [8 datoshi]
/// DROP [2 datoshi]
- /// ENDTRY 1F [4 datoshi]
+ /// LDLOC3 [2 datoshi]
+ /// PUSH0 [1 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// TRY 0E13 [4 datoshi]
+ /// PUSHDATA1 03 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 49 [512 datoshi]
+ /// LDLOC2 [2 datoshi]
+ /// THROW [512 datoshi]
+ /// STLOC4 [2 datoshi]
+ /// JMP 19 [2 datoshi]
+ /// ENDTRY 36 [4 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 5C [512 datoshi]
+ /// PUSHDATA1 03 [8 datoshi]
+ /// EQUAL [32 datoshi]
+ /// ASSERT [1 datoshi]
+ /// PUSHDATA1 02 [8 datoshi]
+ /// PUSHDATA1 FF00 [8 datoshi]
+ /// CALL 2E [512 datoshi]
+ /// ENDFINALLY [4 datoshi]
+ /// ENDTRY E9 [4 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
/// CALL 45 [512 datoshi]
/// PUSHDATA1 02 [8 datoshi]
@@ -141,7 +174,7 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// ENDFINALLY [4 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
- /// JMPIF C0 [2 datoshi]
+ /// JMPIF 9E [2 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
/// CALL 28 [512 datoshi]
/// PUSHDATA1 03 [8 datoshi]
From e0ed16dc8c50bb7b848097a71ac5358db644b92c Mon Sep 17 00:00:00 2001
From: Hecate2 <2474101468@qq.com>
Date: Thu, 16 Jan 2025 16:39:48 +0800
Subject: [PATCH 3/4] remove comments
---
.../MethodConvert/Statement/LabeledStatement.cs | 1 -
.../MethodConvert/Statement/Statement.cs | 12 +++---------
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs
index 4a94710f3..4f1855111 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/LabeledStatement.cs
@@ -51,7 +51,6 @@ private void ConvertLabeledStatement(SemanticModel model, LabeledStatementSyntax
instruction.OpCode = OpCode.JMP_L;
target.Instruction = AddInstruction(OpCode.NOP);
ConvertStatement(model, syntax.Statement);
- //_generalStatementStack.Peek().AddLabel(symbol, target);
}
}
}
diff --git a/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs b/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
index 1997e0657..5f013fde5 100644
--- a/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
+++ b/src/Neo.Compiler.CSharp/MethodConvert/Statement/Statement.cs
@@ -11,9 +11,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Neo.VM;
-using Org.BouncyCastle.Asn1.X509;
using System.Collections.Generic;
-using System.Linq;
namespace Neo.Compiler
{
@@ -28,25 +26,21 @@ internal class StatementContext(StatementSyntax statementSyntax,
JumpTarget? catchTarget = null, JumpTarget? finallyTarget = null, JumpTarget? endFinallyTarget = null,
Dictionary? gotoLabels = null,
Dictionary? switchLabels = null
- //StatementSyntax? parentStatement = null,
- //HashSet? childrenStatements = null
)
{
public readonly StatementSyntax StatementSyntax = statementSyntax;
public readonly JumpTarget? BreakTarget = breakTarget;
public readonly JumpTarget? ContinueTarget = continueTarget;
- public /*readonly*/ ExceptionHandlingState? TryState = tryState;
+ public ExceptionHandlingState? TryState = tryState;
public readonly JumpTarget? CatchTarget = catchTarget;
public readonly JumpTarget? FinallyTarget = finallyTarget;
public readonly JumpTarget? EndFinallyTarget = endFinallyTarget;
- public /*readonly*/ Dictionary? GotoLabels = gotoLabels;
- public /*readonly*/ Dictionary? SwitchLabels = switchLabels;
+ public Dictionary? GotoLabels = gotoLabels;
+ public Dictionary? SwitchLabels = switchLabels;
// handles `break`, `continue` and `goto` in multi-layered nested try with finally
// key: target of this ENDTRY
// value: this ENDTRY
public Dictionary? AdditionalEndTryTargetToInstruction { get; protected set; } = null;
- //public readonly StatementSyntax? ParentStatement = parentStatement;
- //public readonly HashSet? ChildrenStatements = childrenStatements;
/// Jump target of this added ENDTRY
/// The added ENDTRY
From 4dca04572a8292806918a49f9d0b52dbbbcf7193 Mon Sep 17 00:00:00 2001
From: Hecate2 <2474101468@qq.com>
Date: Thu, 16 Jan 2025 16:48:52 +0800
Subject: [PATCH 4/4] control exception in test
---
.../Contract_Break.cs | 4 +-
.../TestingArtifacts/Contract_Break.cs | 40 ++++++++++---------
.../UnitTest_Break.cs | 3 +-
3 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs b/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
index 25134c1ba..7da9fe9fb 100644
--- a/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
+++ b/tests/Neo.Compiler.CSharp.TestContracts/Contract_Break.cs
@@ -6,7 +6,7 @@ namespace Neo.Compiler.CSharp.TestContracts
{
public class Contract_Break : SmartContract.Framework.SmartContract
{
- public static void BreakInTryCatch()
+ public static void BreakInTryCatch(bool exception)
{
Storage.Put("\xff\x00", "\x00");
foreach (object i in Storage.Find("\xff"))
@@ -41,6 +41,8 @@ public static void BreakInTryCatch()
{
for (int j = 0; j < 3;)
break;
+ if (exception)
+ throw new System.Exception();
}
catch
{
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
index ac164ec9a..155585a34 100644
--- a/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
+++ b/tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_Break.cs
@@ -10,12 +10,12 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
{
#region Compiled data
- public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Break"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""breakInTryCatch"",""parameters"":[],""returntype"":""Void"",""offset"":0,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
+ public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Break"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""breakInTryCatch"",""parameters"":[{""name"":""exception"",""type"":""Boolean""}],""returntype"":""Void"",""offset"":0,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
///
/// Optimization: "All"
///
- public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP2BAVcGAAwBAAwC/wA1SAEAABAMAf81TwEAAHAiG2hB81S/HXE7AAU9FwwBAQwC/wA1JAEAAD9oQZwI7Zwk4QwC/wA1MgEAAAwBAZc5EAwB/zUUAQAAcCJsaEHzVL8dcTsaMRByIg4MCWV4Y2VwdGlvbjpqE7Uk8T1LcjsAByIRPUsMAQAMAv8ANcwAAAA/PfEMAv8ANeAAAAAMAQCXORIREBPASnLKcxB0IhRqbM51DAECDAL/ADWeAAAAIgZsazDsP2hBnAjtnCSQDAL/ADWmAAAADAEClzkQDAH/NYgAAABwIl5oQfNUvx1xOwtAEHJqE7VFPUxyEHNrE7VFaxCXOTsOEwwBAwwC/wA0SWo6dCIZPTYMAv8ANFwMAQOXOQwBAgwC/wA0Lj896QwC/wA0RQwBApc5DAEDDAL/ADQXP2hBnAjtnCSeDAL/ADQoDAEDlzlAVwACeXhBm/ZnzkHmPxiEQFcAAnl4Qfa0a+JB3zC4mkBXAAF4Qfa0a+JBkl3oMUB6sNlU"));
+ public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP2QAVcGAQwBAAwC/wA1VwEAABAMAf81XgEAAHAiG2hB81S/HXE7AAU9FwwBAQwC/wA1MwEAAD9oQZwI7Zwk4QwC/wA1QQEAAAwBAZc5EAwB/zUjAQAAcCJsaEHzVL8dcTsaMRByIg4MCWV4Y2VwdGlvbjpqE7Uk8T1LcjsAByIRPUsMAQAMAv8ANdsAAAA/PfEMAv8ANe8AAAAMAQCXORIREBPASnLKcxB0IhRqbM51DAECDAL/ADWtAAAAIgZsazDsP2hBnAjtnCSQDAL/ADW1AAAADAEClzkQDAH/NZcAAABwIm1oQfNUvx1xOxpPEHJqE7VFeCYODAlleGNlcHRpb246PUxyEHNrE7VFaxCXOTsOEwwBAwwC/wA0SWo6dCIZPTYMAv8ANFwMAQOXOQwBAgwC/wA0Lj896QwC/wA0RQwBApc5DAEDDAL/ADQXP2hBnAjtnCSPDAL/ADQoDAEDlzlAVwACeXhBm/ZnzkHmPxiEQFcAAnl4Qfa0a+JB3zC4mkBXAAF4Qfa0a+JBkl3oMUCP84XP"));
#endregion
@@ -25,14 +25,14 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// Unsafe method
///
///
- /// Script: VwYADAEADAL/ADVIAQAAEAwB/zVPAQAAcCIbaEHzVL8dcTsABT0XDAEBDAL/ADUkAQAAP2hBnAjtnCThDAL/ADUyAQAADAEBlzkQDAH/NRQBAABwImxoQfNUvx1xOxoxEHIiDgwJZXhjZXB0aW9uOmoTtSTxPUtyOwAHIhE9SwwBAAwC/wA1zAAAAD898QwC/wA14AAAAAwBAJc5EhEQE8BKcspzEHQiFGpsznUMAQIMAv8ANZ4AAAAiBmxrMOw/aEGcCO2cJJAMAv8ANaYAAAAMAQKXORAMAf81iAAAAHAiXmhB81S/HXE7C0AQcmoTtUU9THIQc2sTtUVrEJc5Ow4TDAEDDAL/ADRJajp0Ihk9NgwC/wA0XAwBA5c5DAECDAL/ADQuPz3pDAL/ADRFDAEClzkMAQMMAv8ANBc/aEGcCO2cJJ4MAv8ANCgMAQOXOUA=
- /// INITSLOT 0600 [64 datoshi]
+ /// Script: VwYBDAEADAL/ADVXAQAAEAwB/zVeAQAAcCIbaEHzVL8dcTsABT0XDAEBDAL/ADUzAQAAP2hBnAjtnCThDAL/ADVBAQAADAEBlzkQDAH/NSMBAABwImxoQfNUvx1xOxoxEHIiDgwJZXhjZXB0aW9uOmoTtSTxPUtyOwAHIhE9SwwBAAwC/wA12wAAAD898QwC/wA17wAAAAwBAJc5EhEQE8BKcspzEHQiFGpsznUMAQIMAv8ANa0AAAAiBmxrMOw/aEGcCO2cJJAMAv8ANbUAAAAMAQKXORAMAf81lwAAAHAibWhB81S/HXE7Gk8QcmoTtUV4Jg4MCWV4Y2VwdGlvbjo9THIQc2sTtUVrEJc5Ow4TDAEDDAL/ADRJajp0Ihk9NgwC/wA0XAwBA5c5DAECDAL/ADQuPz3pDAL/ADRFDAEClzkMAQMMAv8ANBc/aEGcCO2cJI8MAv8ANCgMAQOXOUA=
+ /// INITSLOT 0601 [64 datoshi]
/// PUSHDATA1 00 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L 48010000 [512 datoshi]
+ /// CALL_L 57010000 [512 datoshi]
/// PUSH0 [1 datoshi]
/// PUSHDATA1 FF '?' [8 datoshi]
- /// CALL_L 4F010000 [512 datoshi]
+ /// CALL_L 5E010000 [512 datoshi]
/// STLOC0 [2 datoshi]
/// JMP 1B [2 datoshi]
/// LDLOC0 [2 datoshi]
@@ -42,19 +42,19 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// ENDTRY 17 [4 datoshi]
/// PUSHDATA1 01 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L 24010000 [512 datoshi]
+ /// CALL_L 33010000 [512 datoshi]
/// ENDFINALLY [4 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
/// JMPIF E1 [2 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L 32010000 [512 datoshi]
+ /// CALL_L 41010000 [512 datoshi]
/// PUSHDATA1 01 [8 datoshi]
/// EQUAL [32 datoshi]
/// ASSERT [1 datoshi]
/// PUSH0 [1 datoshi]
/// PUSHDATA1 FF '?' [8 datoshi]
- /// CALL_L 14010000 [512 datoshi]
+ /// CALL_L 23010000 [512 datoshi]
/// STLOC0 [2 datoshi]
/// JMP 6C [2 datoshi]
/// LDLOC0 [2 datoshi]
@@ -77,11 +77,11 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// ENDTRY 4B [4 datoshi]
/// PUSHDATA1 00 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L CC000000 [512 datoshi]
+ /// CALL_L DB000000 [512 datoshi]
/// ENDFINALLY [4 datoshi]
/// ENDTRY F1 [4 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L E0000000 [512 datoshi]
+ /// CALL_L EF000000 [512 datoshi]
/// PUSHDATA1 00 [8 datoshi]
/// EQUAL [32 datoshi]
/// ASSERT [1 datoshi]
@@ -103,7 +103,7 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// STLOC5 [2 datoshi]
/// PUSHDATA1 02 [8 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L 9E000000 [512 datoshi]
+ /// CALL_L AD000000 [512 datoshi]
/// JMP 06 [2 datoshi]
/// LDLOC4 [2 datoshi]
/// LDLOC3 [2 datoshi]
@@ -113,25 +113,29 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
/// JMPIF 90 [2 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
- /// CALL_L A6000000 [512 datoshi]
+ /// CALL_L B5000000 [512 datoshi]
/// PUSHDATA1 02 [8 datoshi]
/// EQUAL [32 datoshi]
/// ASSERT [1 datoshi]
/// PUSH0 [1 datoshi]
/// PUSHDATA1 FF '?' [8 datoshi]
- /// CALL_L 88000000 [512 datoshi]
+ /// CALL_L 97000000 [512 datoshi]
/// STLOC0 [2 datoshi]
- /// JMP 5E [2 datoshi]
+ /// JMP 6D [2 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL F354BF1D 'System.Iterator.Value' [16 datoshi]
/// STLOC1 [2 datoshi]
- /// TRY 0B40 [4 datoshi]
+ /// TRY 1A4F [4 datoshi]
/// PUSH0 [1 datoshi]
/// STLOC2 [2 datoshi]
/// LDLOC2 [2 datoshi]
/// PUSH3 [1 datoshi]
/// LT [8 datoshi]
/// DROP [2 datoshi]
+ /// LDARG0 [2 datoshi]
+ /// JMPIFNOT 0E [2 datoshi]
+ /// PUSHDATA1 657863657074696F6E 'exception' [8 datoshi]
+ /// THROW [512 datoshi]
/// ENDTRY 4C [4 datoshi]
/// STLOC2 [2 datoshi]
/// PUSH0 [1 datoshi]
@@ -174,7 +178,7 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// ENDFINALLY [4 datoshi]
/// LDLOC0 [2 datoshi]
/// SYSCALL 9C08ED9C 'System.Iterator.Next' [32768 datoshi]
- /// JMPIF 9E [2 datoshi]
+ /// JMPIF 8F [2 datoshi]
/// PUSHDATA1 FF00 [8 datoshi]
/// CALL 28 [512 datoshi]
/// PUSHDATA1 03 [8 datoshi]
@@ -183,7 +187,7 @@ public abstract class Contract_Break(Neo.SmartContract.Testing.SmartContractInit
/// RET [0 datoshi]
///
[DisplayName("breakInTryCatch")]
- public abstract void BreakInTryCatch();
+ public abstract void BreakInTryCatch(bool? exception);
#endregion
}
diff --git a/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs b/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs
index f76a24893..042d1f5e4 100644
--- a/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs
+++ b/tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Break.cs
@@ -10,7 +10,8 @@ public class UnitTest_Break : DebugAndTestBase
[TestMethod]
public void TestBreakInTry()
{
- Contract.BreakInTryCatch();
+ Contract.BreakInTryCatch(true);
+ Contract.BreakInTryCatch(false);
}
}
}