From: Rico Tzschichholz Date: Fri, 17 May 2019 06:56:12 +0000 (+0200) Subject: codegen: When freeing local variables don't stop at "switch" on "continue" X-Git-Tag: 0.45.1~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fkeep-around%2Fa929a44437a46eb9f814160c4ecf807a94ba2138;p=thirdparty%2Fvala.git codegen: When freeing local variables don't stop at "switch" on "continue" So distinguish between BreakStatement and ContinueStatement to make the correct decision in append_local_free(). Fixes https://gitlab.gnome.org/GNOME/vala/issues/799 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index b623a2060..e3d8d3b55 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -3741,17 +3741,22 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } } - public void append_local_free (Symbol sym, bool stop_at_loop = false, CodeNode? stop_at = null) { + public void append_local_free (Symbol sym, Statement? jump_stmt = null, CodeNode? stop_at = null) { var b = (Block) sym; append_scope_free (sym, stop_at); - if (stop_at_loop) { + if (jump_stmt is BreakStatement) { if (b.parent_node is Loop || b.parent_node is ForeachStatement || b.parent_node is SwitchStatement) { return; } + } else if (jump_stmt is ContinueStatement) { + if (b.parent_node is Loop || + b.parent_node is ForeachStatement) { + return; + } } if (stop_at != null && b.parent_node == stop_at) { @@ -3759,7 +3764,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } if (sym.parent_symbol is Block) { - append_local_free (sym.parent_symbol, stop_at_loop, stop_at); + append_local_free (sym.parent_symbol, jump_stmt, stop_at); } else if (sym.parent_symbol is Method) { append_param_free ((Method) sym.parent_symbol); } else if (sym.parent_symbol is PropertyAccessor) { diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala index 58e51d99f..25c386f50 100644 --- a/codegen/valaccodecontrolflowmodule.vala +++ b/codegen/valaccodecontrolflowmodule.vala @@ -350,13 +350,13 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule { } public override void visit_break_statement (BreakStatement stmt) { - append_local_free (current_symbol, true); + append_local_free (current_symbol, stmt); ccode.add_break (); } public override void visit_continue_statement (ContinueStatement stmt) { - append_local_free (current_symbol, true); + append_local_free (current_symbol, stmt); ccode.add_continue (); } diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index dfc308f4d..68a13dd29 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -724,7 +724,7 @@ public class Vala.GAsyncModule : GtkModule { set_error.add_argument (error_expr); ccode.add_expression (set_error); - append_local_free (current_symbol, false); + append_local_free (current_symbol); // We already returned the error above, we must not return anything else here. var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala index 6855377c8..bae957f02 100644 --- a/codegen/valagerrormodule.vala +++ b/codegen/valagerrormodule.vala @@ -102,7 +102,7 @@ public class Vala.GErrorModule : CCodeDelegateModule { ccode.add_expression (cpropagate); // free local variables - append_local_free (current_symbol, false); + append_local_free (current_symbol); if (current_method is CreationMethod && current_method.parent_symbol is Class) { var cl = (Class) current_method.parent_symbol; @@ -117,7 +117,7 @@ public class Vala.GErrorModule : CCodeDelegateModule { void uncaught_error_statement (CCodeExpression inner_error, bool unexpected = false) { // free local variables - append_local_free (current_symbol, false); + append_local_free (current_symbol); var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical")); ccritical.add_argument (new CCodeConstant (unexpected ? "\"file %s: line %d: unexpected error: %s (%s, %d)\"" : "\"file %s: line %d: uncaught error: %s (%s, %d)\"")); @@ -185,9 +185,9 @@ public class Vala.GErrorModule : CCodeDelegateModule { // free local variables if (is_in_catch) { - append_local_free (current_symbol, false, current_catch); + append_local_free (current_symbol, null, current_catch); } else { - append_local_free (current_symbol, false, current_try); + append_local_free (current_symbol, null, current_try); } var error_types = new ArrayList (); diff --git a/tests/Makefile.am b/tests/Makefile.am index 57e784b61..b67d91c5b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -156,6 +156,7 @@ TESTS = \ control-flow/expressions-conditional.vala \ control-flow/finally-return.test \ control-flow/for.vala \ + control-flow/for-switch-continue.vala \ control-flow/foreach.vala \ control-flow/missing-break.test \ control-flow/missing-return.test \ diff --git a/tests/control-flow/for-switch-continue.vala b/tests/control-flow/for-switch-continue.vala new file mode 100644 index 000000000..da58b1ad0 --- /dev/null +++ b/tests/control-flow/for-switch-continue.vala @@ -0,0 +1,24 @@ +bool success = false; + +class Foo : Object { + ~Foo () { + success = true; + } +} + +void bar () { + assert (!success); + for (int i = 0; i < 1; i++) { + Foo? foo = null; + switch (i) { + case 0: + foo = new Foo (); + continue; + } + } + assert (success); +} + +void main() { + bar (); +}