This commit is contained in:
Ivan Bondarev 2021-11-21 12:43:55 +01:00
parent daf20fdb99
commit 7e18d092e8
15 changed files with 164 additions and 15 deletions

View file

@ -0,0 +1,9 @@
//!Использование exit, break и continue в блоке finally недопустимо
begin
for var i := 1 to 10 do
try
finally
break;
end;
end.

View file

@ -0,0 +1,9 @@
//!Использование exit, break и continue в блоке finally недопустимо
begin
for var i := 1 to 10 do
try
finally
continue;
end;
end.

View file

@ -0,0 +1,8 @@
//!Использование exit, break и continue в блоке finally недопустимо
begin
try
finally
exit;
end;
end.

View file

@ -0,0 +1,16 @@
//!Использование exit, break и continue в блоке finally недопустимо
begin
var k := 0;
for var i := 1 to 3 do
try
finally
for var j := 1 to 10 do
begin
k := j;
exit;
end;
end;
assert(k = 1);
end.

View file

@ -0,0 +1,16 @@
//!Использование exit, break и continue в блоке finally недопустимо
begin
var k := 0;
for var i := 1 to 3 do
try
finally
for var j := 1 to 10 do
begin
k := j;
continue;
end;
break;
end;
assert(k = 1);
end.

View file

@ -0,0 +1,20 @@
//!Использование exit, break и continue в блоке finally недопустимо
begin
var k := 0;
for var i := 1 to 3 do
try
finally
for var j := 1 to 10 do
begin
try
k := j;
continue;
finally
break;
end;
end;
end;
assert(k = 1);
end.

15
TestSuite/exceptions5.pas Normal file
View file

@ -0,0 +1,15 @@
begin
var k := 0;
for var i := 1 to 3 do
try
finally
for var j := 1 to 10 do
begin
k := j;
break;
end;
end;
assert(k = 1);
end.

View file

@ -649,7 +649,7 @@ namespace TreeConverter.LambdaExpressions.Closure
_visitor.convertion_data_and_alghoritms.check_convert_type_with_inheritance(vdn.type, elemType, _visitor.get_location(_foreach_stmt.identifier));
var fn = new foreach_node(vdn, inWhat, null, _visitor.get_location(_foreach_stmt));
_visitor.context.cycle_stack.push(fn);
_visitor.context.enter_in_cycle(fn);
_visitor.context.loop_var_stack.Push(vdn);
ProcessNode(_foreach_stmt.in_what);
@ -664,7 +664,7 @@ namespace TreeConverter.LambdaExpressions.Closure
_visitor.context.loop_var_stack.Pop();
_visitor.convertion_data_and_alghoritms.statement_list_stack.pop();
_visitor.context.cycle_stack.pop();
_visitor.context.leave_cycle();
_currentTreeNode = _currentTreeNode.ParentNode;
}
@ -727,7 +727,7 @@ namespace TreeConverter.LambdaExpressions.Closure
{
fn.bool_cycle = true;
}
_visitor.context.cycle_stack.push(fn);
_visitor.context.enter_in_cycle(fn);
_visitor.context.loop_var_stack.Push(vdn);
nodesToProcess.Add(_for_node.initial_value);
@ -746,7 +746,7 @@ namespace TreeConverter.LambdaExpressions.Closure
}
ProcessNode(_for_node.statements);
_visitor.context.cycle_stack.pop();
_visitor.context.leave_cycle();
_visitor.context.loop_var_stack.Pop();
_visitor.convertion_data_and_alghoritms.statement_list_stack.pop();

View file

@ -156,7 +156,7 @@ namespace PascalABCCompiler.TreeConverter
TreeRealization.for_node forNode = new TreeRealization.for_node(null, sn_while, sn_init_while, sn_inc, null, get_location(_for_node));
if (vdn.type == SystemLibrary.SystemLibrary.bool_type)
forNode.bool_cycle = true;
context.cycle_stack.push(forNode);
context.enter_in_cycle(forNode);
context.loop_var_stack.Push(vdn);
statements_list slst = new statements_list(get_location(_for_node.statements));
convertion_data_and_alghoritms.statement_list_stack_push(slst);
@ -172,7 +172,7 @@ namespace PascalABCCompiler.TreeConverter
forNode.body = slst;
}
context.cycle_stack.pop();
context.leave_cycle();
context.loop_var_stack.Pop();
head_stmts = convertion_data_and_alghoritms.statement_list_stack.pop();
head_stmts.statements.AddElement(forNode);

View file

@ -46,13 +46,13 @@ namespace PascalABCCompiler.TreeConverter
foreach_node foreachNode = new foreach_node(foreachVariable, foreachCollection, null, get_location(_foreach_stmt));
context.cycle_stack.push(foreachNode);
context.enter_in_cycle(foreachNode);
context.loop_var_stack.Push(foreachVariable);
context.enter_code_block_with_bind();
statement_node body = convert_strong(_foreach_stmt.stmt);
context.leave_code_block();
context.loop_var_stack.Pop();
context.cycle_stack.pop();
context.leave_cycle();
sl = convertion_data_and_alghoritms.statement_list_stack.pop();

View file

@ -3958,6 +3958,37 @@ namespace PascalABCCompiler.TreeConverter
_block_stack.Push(new code_block(null));
}
int finally_blocks_depth = 0;
bool disable_finally_control_break_check = false;
public void enter_finally_block()
{
finally_blocks_depth++;
disable_finally_control_break_check = false;
}
public void leave_finally_block()
{
finally_blocks_depth--;
}
public bool in_finally_block(bool ignore_disable_finally_control_break_check = false)
{
return (!disable_finally_control_break_check || ignore_disable_finally_control_break_check) && finally_blocks_depth > 0;
}
public void enter_in_cycle(statement_node stmt)
{
cycle_stack.push(stmt);
disable_finally_control_break_check = true;
}
public void leave_cycle()
{
cycle_stack.pop();
disable_finally_control_break_check = false;
}
//Убирает блок со стека
public void leave_code_block()
{

View file

@ -1766,6 +1766,10 @@ namespace PascalABCCompiler.TreeConverter
{
AddError(new BreakStatementWithoutComprehensiveCycle(call_location));
}
if (context.in_finally_block())
{
AddError(call_location, "EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK");
}
statement_node sn = context.cycle_stack.top();
switch (sn.semantic_node_type)
{
@ -1803,6 +1807,10 @@ namespace PascalABCCompiler.TreeConverter
{
AddError(new ContinueStatementWithoutComprehensiveCycle(call_location));
}
if (context.in_finally_block())
{
AddError(call_location, "EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK");
}
statement_node sn = context.cycle_stack.top();
switch (sn.semantic_node_type)
{
@ -1836,6 +1844,10 @@ namespace PascalABCCompiler.TreeConverter
{
return null;
}
if (context.in_finally_block(true))
{
AddError(call_location, "EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK");
}
if (!TreeConverter.SemanticRules.EnableExitProcedure)
AddError(new TreeConverter.UndefinedNameReference(TreeConverter.compiler_string_consts.exit_procedure_name, call_location));
return new exit_procedure(call_location);
@ -1932,7 +1944,9 @@ namespace PascalABCCompiler.TreeConverter
statements_list stm = new statements_list(null);
SyntaxTree.try_handler_finally try_hndlr_finally = _try_stmt.handler as SyntaxTree.try_handler_finally;
context.enter_code_block_without_bind();
context.enter_finally_block();
statement_node finally_stmt = convert_strong(try_hndlr_finally.stmt_list);
context.leave_finally_block();
context.leave_code_block();
stm.statements.AddElement(finally_stmt);
@ -1956,7 +1970,15 @@ namespace PascalABCCompiler.TreeConverter
if (try_handler_finally != null)
{
context.enter_code_block_without_bind();
finally_st = convert_strong(try_handler_finally.stmt_list);
context.enter_finally_block();
try
{
finally_st = convert_strong(try_handler_finally.stmt_list);
}
finally
{
context.leave_finally_block();
}
context.leave_code_block();
}
try_block tb = new try_block(try_statements, finally_st, efl, loc);
@ -15811,7 +15833,7 @@ namespace PascalABCCompiler.TreeConverter
}
while_node wn = new while_node(expr, get_location(_while_node));
context.cycle_stack.push(wn);
context.enter_in_cycle(wn);
statements_list sl = new statements_list(get_location(_while_node.statements));
convertion_data_and_alghoritms.statement_list_stack_push(sl);
@ -15828,14 +15850,14 @@ namespace PascalABCCompiler.TreeConverter
}
wn.body = st;
context.cycle_stack.pop();
context.leave_cycle();
return_value(wn);
}
public override void visit(SyntaxTree.repeat_node _repeat_node)
{
repeat_node rep = new repeat_node(get_location(_repeat_node));
context.cycle_stack.push(rep);
context.enter_in_cycle(rep);
statements_list sl = new statements_list(get_location(_repeat_node.statements));
convertion_data_and_alghoritms.statement_list_stack_push(sl);
@ -15861,7 +15883,7 @@ namespace PascalABCCompiler.TreeConverter
try_convert_typed_expression_to_function_call(ref expr, true);
rep.condition = expr;
}
context.cycle_stack.pop();
context.leave_cycle();
return_value(rep);
}
@ -20005,7 +20027,7 @@ namespace PascalABCCompiler.TreeConverter
CheckToEmbeddedStatementCannotBeADeclaration(node.stmt);
for_node fn = new for_node(sn_init, sn_cond, null, sn_next, null, get_location(node));
context.cycle_stack.push(fn);
context.enter_in_cycle(fn);
statements_list slst = new statements_list(get_location(node.stmt));
convertion_data_and_alghoritms.statement_list_stack_push(slst);
@ -20021,7 +20043,7 @@ namespace PascalABCCompiler.TreeConverter
fn.body = slst;
}
context.cycle_stack.pop();
context.leave_cycle();
head_stmts = convertion_data_and_alghoritms.statement_list_stack.pop();
head_stmts.statements.AddElement(fn);

View file

@ -175,6 +175,7 @@ AMBIGUOUS_DELEGATES=Ambiguous delegates detected
EXPECTED_INTERFACE=Interface expected
EXPECTED_PROPERTY=Property expected
NON_PUBLIC_RECORD_CONSTRUCTORS_NOT_ALLOWED=Records can not have non-public default constructor
EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK=exit, break and continue are not allowed in finally
%PREFIX%=COMPILATIONERROR_
UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Unit expected, library found
ASSEMBLY_{0}_READING_ERROR=Error by reading assembly '{0}'

View file

@ -170,6 +170,7 @@ AMBIGUOUS_DELEGATES=Невозможно выбрать конкретный д
EXPECTED_INTERFACE=Ожидалось имя интерфейса
EXPECTED_PROPERTY=Ожидалось свойство
NON_PUBLIC_RECORD_CONSTRUCTORS_NOT_ALLOWED=Записи могут иметь только публичный конструктор по умолчанию
EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK=Использование exit, break и continue в блоке finally недопустимо
%PREFIX%=COMPILATIONERROR_
UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Ожидался модуль, а встречена библиотека
ASSEMBLY_{0}_READING_ERROR=Ошибка при чтении сборки '{0}'

View file

@ -167,6 +167,7 @@ AMBIGUOUS_DELEGATES=Невозможно выбрать конкретный д
EXPECTED_INTERFACE=Ожидалось имя интерфейса
EXPECTED_PROPERTY=Ожидалось свойство
NON_PUBLIC_RECORD_CONSTRUCTORS_NOT_ALLOWED=Записи могут иметь только публичный конструктор по умолчанию
EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK=Использование exit, break и continue в блоке finally недопустимо
%PREFIX%=COMPILATIONERROR_
UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Очікувався модуль, а зустріли бібліотеку
ASSEMBLY_{0}_READING_ERROR=Помилка при читанні збірки '{0}'