]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: When freeing local variables don't stop at "switch" on "continue"
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 17 May 2019 06:56:12 +0000 (08:56 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 6 Aug 2019 11:54:11 +0000 (13:54 +0200)
So distinguish between BreakStatement and ContinueStatement to make the
correct decision in append_local_free().

Fixes https://gitlab.gnome.org/GNOME/vala/issues/799

codegen/valaccodebasemodule.vala
codegen/valaccodecontrolflowmodule.vala
codegen/valagasyncmodule.vala
codegen/valagerrormodule.vala
tests/Makefile.am
tests/control-flow/for-switch-continue.vala [new file with mode: 0644]

index 48d706e37de993609934fb607691aaddc222d5e3..57ee13c6509bc050f713145f23a454d7d0bbab1d 100644 (file)
@@ -3648,17 +3648,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) {
@@ -3666,7 +3671,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) {
index 91268e7d1112595b55fca5bd6efd32a77255a06e..a549f062127c5d901d5adeb7d965be8f1e716062 100644 (file)
@@ -345,13 +345,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 ();
        }
index 6c706e8cfb5b5c3c79219acdfdbc5eff44a1e006..214d86af28b9e83f2b9584e59d7523d58072b1a5 100644 (file)
@@ -866,7 +866,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);
 
                if (context.require_glib_version (2, 36)) {
                        // We already returned the error above, we must not return anything else here.
index fc82fb46affe456421aab22bb5c70cc6e9e46ea9..1c01cc9407e1c305bb3f1288f6f263b0f042c410 100644 (file)
@@ -100,7 +100,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;
@@ -115,7 +115,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)\""));
@@ -183,9 +183,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<DataType> ();
index 7df354c66f78c03da92f704c9eefc014d0431b7f..332f4b589c2be02114b379341545bcb203da4581 100644 (file)
@@ -133,6 +133,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 (file)
index 0000000..da58b1a
--- /dev/null
@@ -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 ();
+}