]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Move DoStatement transformation into the code transformer
authorLuca Bruno <lucabru@src.gnome.org>
Tue, 30 Aug 2011 11:42:39 +0000 (13:42 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 1 Apr 2020 08:17:51 +0000 (10:17 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/27

codegen/valaccodetransformer.vala
vala/valadostatement.vala
vala/valaflowanalyzer.vala

index 9ce39209a255adf87dc4898a896c05e356d97f86..52073323910b363faf9768c248c92449705ca22f 100644 (file)
@@ -81,6 +81,29 @@ public class Vala.CCodeTransformer : CodeTransformer {
                end_replace_statement ();
        }
 
+       public override void visit_do_statement (DoStatement stmt) {
+               // convert to simple loop
+               begin_replace_statement (stmt);
+
+               b.open_loop ();
+               // do not generate variable and if block if condition is always true
+               if (!stmt.condition.is_always_true ()) {
+                       var notfirst = b.add_temp_declaration (null, expression ("false"));
+                       b.open_if (expression (notfirst));
+                       b.open_if (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.source_reference));
+                       b.add_break ();
+                       b.close ();
+                       b.add_else ();
+                       b.add_assignment (expression (notfirst), expression ("true"));
+                       b.close ();
+               }
+               stmt.body.checked = false;
+               b.add_statement (stmt.body);
+               b.close ();
+
+               end_replace_statement ();
+       }
+
        public override void visit_expression (Expression expr) {
                if (expr in context.analyzer.replaced_nodes) {
                        return;
index 80df5849ea719c30b9c44f4d87aca6baa9283d1c..23e8982da17b406997a79595c0e4656608500b75 100644 (file)
@@ -94,46 +94,25 @@ public class Vala.DoStatement : CodeNode, Statement {
 
                checked = true;
 
-               // convert to simple loop
+               condition.target_type = context.analyzer.bool_type.copy ();
 
-               // do not generate variable and if block if condition is always true
-               if (condition.is_always_true ()) {
-                       var loop = new Loop (body, source_reference);
+               condition.check (context);
 
-                       unowned Block parent_block = (Block) parent_node;
-                       parent_block.replace_statement (this, loop);
-
-                       if (!loop.check (context)) {
-                               error = true;
-                       }
-
-                       return !error;
+               if (condition.error) {
+                       /* if there was an error in the condition, skip this check */
+                       error = true;
+                       return false;
                }
 
-               var block = new Block (source_reference);
-
-               var first_local = new LocalVariable (context.analyzer.bool_type.copy (), get_temp_name (), new BooleanLiteral (true, source_reference), source_reference);
-               block.add_statement (new DeclarationStatement (first_local, source_reference));
-
-               var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
-               var true_block = new Block (condition.source_reference);
-               true_block.add_statement (new BreakStatement (condition.source_reference));
-               var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
-
-               var condition_block = new Block (condition.source_reference);
-               condition_block.add_statement (if_stmt);
-
-               var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, source_reference), source_reference), condition_block, null, source_reference);
-               body.insert_statement (0, first_if);
-               body.insert_statement (1, new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, source_reference), new BooleanLiteral (false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));
-
-               block.add_statement (new Loop (body, source_reference));
-
-               unowned Block parent_block = (Block) parent_node;
-               parent_block.replace_statement (this, block);
+               if (condition.value_type == null || !condition.value_type.compatible (context.analyzer.bool_type)) {
+                       error = true;
+                       Report.error (condition.source_reference, "Condition must be boolean");
+                       return false;
+               }
 
-               if (!block.check (context)) {
+               if (!body.check (context)) {
                        error = true;
+                       return false;
                }
 
                return !error;
index acce8e22f0acfac94b827f6063ec6d02a466166a..fc167a1eea6ca29ef9ee582a04594e39411cb544 100644 (file)
@@ -791,6 +791,57 @@ public class Vala.FlowAnalyzer : CodeVisitor {
                jump_stack.remove_at (jump_stack.size - 1);
        }
 
+       public override void visit_do_statement (DoStatement stmt) {
+               if (unreachable (stmt)) {
+                       return;
+               }
+
+               var body_block = new BasicBlock ();
+               all_basic_blocks.add (body_block);
+               current_block.connect (body_block);
+               current_block = body_block;
+
+               var loop_block = new BasicBlock ();
+               all_basic_blocks.add (loop_block);
+               jump_stack.add (new JumpTarget.continue_target (loop_block));
+               var after_loop_block = new BasicBlock ();
+               all_basic_blocks.add (after_loop_block);
+               jump_stack.add (new JumpTarget.break_target (after_loop_block));
+
+               // body
+               stmt.body.accept (this);
+
+               // end of loop block reachable?
+               if (current_block != null) {
+                       current_block.connect (loop_block);
+               }
+
+               // condition
+               current_block = loop_block;
+               loop_block.add_node (stmt.condition);
+               handle_errors (stmt.condition);
+
+               if (!stmt.condition.is_always_false ()) {
+                       loop_block.connect (body_block);
+               }
+
+               if (!stmt.condition.is_always_true ()) {
+                       loop_block.connect (after_loop_block);
+               }
+
+               // after loop block reachable?
+               if (after_loop_block.get_predecessors ().size == 0) {
+                       // after loop block not reachable
+                       mark_unreachable ();
+               } else {
+                       // after loop block reachable
+                       current_block = after_loop_block;
+               }
+
+               jump_stack.remove_at (jump_stack.size - 1);
+               jump_stack.remove_at (jump_stack.size - 1);
+       }
+
        public override void visit_foreach_statement (ForeachStatement stmt) {
                if (unreachable (stmt)) {
                        return;