vala r894 - in trunk: . compiler gobject tests vala



Author: juergbi
Date: Wed Jan 23 15:26:07 2008
New Revision: 894
URL: http://svn.gnome.org/viewvc/vala?rev=894&view=rev

Log:
2008-01-23  Juerg Billeter  <j bitron ch>

	* vala/Makefile.am, vala/valabasicblock.vala, vala/valacfgbuilder.vala,
	  vala/valadostatement.vala, vala/valaforstatement.vala,
	  vala/valaifstatement.vala, vala/valamemorymanager.vala,
	  vala/valamethod.vala, vala/valasemanticanalyzer.vala,
	  vala/valasymbolresolver.vala, vala/valawhilestatement.vala,
	  gobject/valaccodegenerator.vala, compiler/valacompiler.vala: build
	  control flow graph, report error for missing return statement in
	  non-void methods, and report warning for unreachable code,
	  fixes bug 508480

	* tests/exceptions.vala: add missing return statement


Added:
   trunk/vala/valabasicblock.vala
   trunk/vala/valacfgbuilder.vala
Modified:
   trunk/ChangeLog
   trunk/compiler/valacompiler.vala
   trunk/gobject/valaccodegenerator.vala
   trunk/tests/exceptions.vala
   trunk/vala/Makefile.am
   trunk/vala/valadostatement.vala
   trunk/vala/valaforstatement.vala
   trunk/vala/valaifstatement.vala
   trunk/vala/valamemorymanager.vala
   trunk/vala/valamethod.vala
   trunk/vala/valasemanticanalyzer.vala
   trunk/vala/valasymbolresolver.vala
   trunk/vala/valawhilestatement.vala

Modified: trunk/compiler/valacompiler.vala
==============================================================================
--- trunk/compiler/valacompiler.vala	(original)
+++ trunk/compiler/valacompiler.vala	Wed Jan 23 15:26:07 2008
@@ -269,6 +269,13 @@
 			return quit ();
 		}
 
+		var cfg_builder = new CFGBuilder ();
+		cfg_builder.build_cfg (context);
+
+		if (Report.get_errors () > 0) {
+			return quit ();
+		}
+
 		var memory_manager = new MemoryManager ();
 		memory_manager.analyze (context);
 

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Wed Jan 23 15:26:07 2008
@@ -1341,6 +1341,8 @@
 	}
 
 	public override void visit_if_statement (IfStatement! stmt) {
+		stmt.accept_children (this);
+
 		if (stmt.false_statement != null) {
 			stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
 		} else {
@@ -1496,18 +1498,24 @@
 	}
 
 	public override void visit_while_statement (WhileStatement! stmt) {
+		stmt.accept_children (this);
+
 		stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
 		
 		create_temp_decl (stmt, stmt.condition.temp_vars);
 	}
 
 	public override void visit_do_statement (DoStatement! stmt) {
+		stmt.accept_children (this);
+
 		stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
 		
 		create_temp_decl (stmt, stmt.condition.temp_vars);
 	}
 
 	public override void visit_for_statement (ForStatement! stmt) {
+		stmt.accept_children (this);
+
 		var cfor = new CCodeForStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
 		stmt.ccodenode = cfor;
 		

Modified: trunk/tests/exceptions.vala
==============================================================================
--- trunk/tests/exceptions.vala	(original)
+++ trunk/tests/exceptions.vala	Wed Jan 23 15:26:07 2008
@@ -23,6 +23,8 @@
 		foo ();
 
 		stdout.printf (" BAD");
+
+		return 0;
 	}
 
 	public void good () throws BarError {

Modified: trunk/vala/Makefile.am
==============================================================================
--- trunk/vala/Makefile.am	(original)
+++ trunk/vala/Makefile.am	Wed Jan 23 15:26:07 2008
@@ -24,6 +24,7 @@
 	valaattribute.vala \
 	valaattributeprocessor.vala \
 	valabaseaccess.vala \
+	valabasicblock.vala \
 	valabinaryexpression.vala \
 	valabindingprovider.vala \
 	valablock.vala \
@@ -31,6 +32,7 @@
 	valabreakstatement.vala \
 	valacastexpression.vala \
 	valacatchclause.vala \
+	valacfgbuilder.vala \
 	valacharacterliteral.vala \
 	valaclass.vala \
 	valaclasstype.vala \

Added: trunk/vala/valabasicblock.vala
==============================================================================
--- (empty file)
+++ trunk/vala/valabasicblock.vala	Wed Jan 23 15:26:07 2008
@@ -0,0 +1,65 @@
+/* valabasicblock.vala
+ *
+ * Copyright (C) 2008  JÃrg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	JÃrg Billeter <j bitron ch>
+ */
+
+using GLib;
+using Gee;
+
+/**
+ * Represents a basic block, i.e. a straight-line piece of code without any
+ * jumps or jump targets.
+ */
+public class Vala.BasicBlock : Object {
+	private Gee.List<CodeNode> nodes = new ArrayList<CodeNode> ();
+
+	private Gee.List<weak BasicBlock> predecessors = new ArrayList<weak BasicBlock> ();
+	private Gee.List<BasicBlock> successors = new ArrayList<BasicBlock> ();
+
+	public BasicBlock () {
+	}
+
+	public BasicBlock.entry () {
+	}
+
+	public BasicBlock.exit () {
+	}
+
+	public void add_node (CodeNode node) {
+		nodes.add (node);
+	}
+
+	public void connect (BasicBlock target) {
+		if (!successors.contains (target)) {
+			successors.add (target);
+		}
+		if (!target.predecessors.contains (this)) {
+			target.predecessors.add (this);
+		}
+	}
+
+	public Gee.List<weak BasicBlock> get_predecessors () {
+		return new ReadOnlyList<weak BasicBlock> (predecessors);
+	}
+
+	public Gee.List<weak BasicBlock> get_successors () {
+		return new ReadOnlyList<weak BasicBlock> (successors);
+	}
+}

Added: trunk/vala/valacfgbuilder.vala
==============================================================================
--- (empty file)
+++ trunk/vala/valacfgbuilder.vala	Wed Jan 23 15:26:07 2008
@@ -0,0 +1,395 @@
+/* valacfgbuilder.vala
+ *
+ * Copyright (C) 2008  JÃrg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	JÃrg Billeter <j bitron ch>
+ */
+
+using GLib;
+using Gee;
+
+/**
+ * Code visitor building the control flow graph.
+ */
+public class Vala.CFGBuilder : CodeVisitor {
+	private CodeContext context;
+	private BasicBlock current_block;
+	private bool unreachable_reported;
+	private Method current_method;
+	private Gee.List<BasicBlock> breakable_stack = new ArrayList<BasicBlock> ();
+	private Gee.List<BasicBlock> continuable_stack = new ArrayList<BasicBlock> ();
+
+	public CFGBuilder () {
+	}
+
+	/**
+	 * Build control flow graph in the specified context.
+	 *
+	 * @param context a code context
+	 */
+	public void build_cfg (CodeContext! context) {
+		this.context = context;
+
+		/* we're only interested in non-pkg source files */
+		var source_files = context.get_source_files ();
+		foreach (SourceFile file in source_files) {
+			if (!file.pkg) {
+				file.accept (this);
+			}
+		}
+	}
+
+	public override void visit_source_file (SourceFile! source_file) {
+		source_file.accept_children (this);
+	}
+
+	public override void visit_class (Class! cl) {
+		cl.accept_children (this);
+	}
+
+	public override void visit_struct (Struct! st) {
+		st.accept_children (this);
+	}
+
+	public override void visit_interface (Interface! iface) {
+		iface.accept_children (this);
+	}
+
+	public override void visit_enum (Enum! en) {
+		en.accept_children (this);
+	}
+
+	public override void visit_method (Method! m) {
+		if (m.body == null) {
+			return;
+		}
+
+		var old_method = current_method;
+		current_method = m;
+
+		m.entry_block = new BasicBlock.entry ();
+		m.exit_block = new BasicBlock.exit ();
+
+		current_block = new BasicBlock ();
+		m.entry_block.connect (current_block);
+
+		m.accept_children (this);
+
+		if (current_block != null) {
+			// end of method body reachable
+
+			if (!(m.return_type is VoidType)) {
+				Report.error (m.source_reference, "missing return statement at end of method body");
+				m.error = true;
+			}
+
+			current_block.connect (m.exit_block);
+		}
+
+		current_method = old_method;
+	}
+
+	public override void visit_block (Block! b) {
+		b.accept_children (this);
+	}
+
+	public override void visit_declaration_statement (DeclarationStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		current_block.add_node (stmt);
+	}
+
+	public override void visit_expression_statement (ExpressionStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		current_block.add_node (stmt);
+	}
+
+	public override void visit_if_statement (IfStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		// condition
+		current_block.add_node (stmt.condition);
+
+		// true block
+		var last_block = current_block;
+		current_block = new BasicBlock ();
+		last_block.connect (current_block);
+		stmt.true_statement.accept (this);
+
+		// false block
+		var last_true_block = current_block;
+		current_block = new BasicBlock ();
+		last_block.connect (current_block);
+		if (stmt.false_statement != null) {
+			stmt.false_statement.accept (this);
+		}
+
+		// after if/else
+		var last_false_block = current_block;
+		// reachable?
+		if (last_true_block != null || last_false_block != null) {
+			current_block = new BasicBlock ();
+			if (last_true_block != null) {
+				last_true_block.connect (current_block);
+			}
+			if (last_false_block != null) {
+				last_false_block.connect (current_block);
+			}
+		}
+	}
+
+	public override void visit_while_statement (WhileStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		var condition_block = new BasicBlock ();
+		continuable_stack.add (condition_block);
+		var after_loop_block = new BasicBlock ();
+		breakable_stack.add (after_loop_block);
+
+		// condition
+		var last_block = current_block;
+		last_block.connect (condition_block);
+		condition_block.add_node (stmt.condition);
+
+		// loop block
+		current_block = new BasicBlock ();
+		condition_block.connect (current_block);
+		stmt.body.accept (this);
+		// end of loop block reachable?
+		if (current_block != null) {
+			current_block.connect (condition_block);
+		}
+
+		// after loop
+		condition_block.connect (after_loop_block);
+		current_block = after_loop_block;
+
+		continuable_stack.remove_at (continuable_stack.size - 1);
+		breakable_stack.remove_at (breakable_stack.size - 1);
+	}
+
+	public override void visit_do_statement (DoStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		var condition_block = new BasicBlock ();
+		continuable_stack.add (condition_block);
+		var after_loop_block = new BasicBlock ();
+		breakable_stack.add (after_loop_block);
+
+		// loop block
+		var last_block = current_block;
+		var loop_block = new BasicBlock ();
+		last_block.connect (loop_block);
+		current_block = loop_block;
+		stmt.body.accept (this);
+
+		// condition
+		// reachable?
+		if (current_block != null || condition_block.get_predecessors ().size > 0) {
+			if (current_block != null) {
+				last_block = current_block;
+				last_block.connect (condition_block);
+			}
+			condition_block.add_node (stmt.condition);
+			condition_block.connect (loop_block);
+			current_block = condition_block;
+		}
+
+		// after loop
+		// reachable?
+		if (current_block != null || after_loop_block.get_predecessors ().size > 0) {
+			if (current_block != null) {
+				last_block = current_block;
+				last_block.connect (after_loop_block);
+			}
+			current_block = after_loop_block;
+		}
+
+		continuable_stack.remove_at (continuable_stack.size - 1);
+		breakable_stack.remove_at (breakable_stack.size - 1);
+	}
+
+	public override void visit_for_statement (ForStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		// initializer
+		foreach (Expression init_expr in stmt.get_initializer ()) {
+			current_block.add_node (init_expr);
+		}
+
+		var iterator_block = new BasicBlock ();
+		continuable_stack.add (iterator_block);
+		var after_loop_block = new BasicBlock ();
+		breakable_stack.add (after_loop_block);
+
+		// condition
+		var condition_block = new BasicBlock ();
+		current_block.connect (condition_block);
+		condition_block.add_node (stmt.condition);
+
+		// loop block
+		current_block = new BasicBlock ();
+		condition_block.connect (current_block);
+		stmt.body.accept (this);
+
+		// iterator
+		// reachable?
+		if (current_block != null || iterator_block.get_predecessors ().size > 0) {
+			if (current_block != null) {
+				current_block.connect (iterator_block);
+			}
+			foreach (Expression it_expr in stmt.get_iterator ()) {
+				iterator_block.add_node (it_expr);
+			}
+			iterator_block.connect (condition_block);
+		}
+
+		// after loop
+		condition_block.connect (after_loop_block);
+		current_block = after_loop_block;
+
+		continuable_stack.remove_at (continuable_stack.size - 1);
+		breakable_stack.remove_at (breakable_stack.size - 1);
+	}
+
+	public override void visit_foreach_statement (ForeachStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		var loop_block = new BasicBlock ();
+		continuable_stack.add (loop_block);
+		var after_loop_block = new BasicBlock ();
+		breakable_stack.add (after_loop_block);
+
+		// loop block
+		var last_block = current_block;
+		last_block.connect (loop_block);
+		current_block = loop_block;
+		stmt.body.accept (this);
+		if (current_block != null) {
+			current_block.connect (loop_block);
+		}
+
+		// after loop
+		last_block.connect (after_loop_block);
+		if (current_block != null) {
+			current_block.connect (after_loop_block);
+		}
+		current_block = after_loop_block;
+
+		continuable_stack.remove_at (continuable_stack.size - 1);
+		breakable_stack.remove_at (breakable_stack.size - 1);
+	}
+
+	public override void visit_break_statement (BreakStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		current_block.add_node (stmt);
+		current_block.connect (top_breakable ());
+		current_block = null;
+		unreachable_reported = false;
+	}
+
+	public override void visit_continue_statement (ContinueStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		current_block.add_node (stmt);
+		current_block.connect (top_continuable ());
+		current_block = null;
+		unreachable_reported = false;
+	}
+
+	public override void visit_return_statement (ReturnStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		current_block.add_node (stmt);
+		current_block.connect (current_method.exit_block);
+		current_block = null;
+		unreachable_reported = false;
+	}
+
+	public override void visit_throw_statement (ThrowStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		current_block.add_node (stmt);
+		// TODO connect to catch blocks instead of exit block if appropriate
+		current_block.connect (current_method.exit_block);
+		current_block = null;
+		unreachable_reported = false;
+	}
+
+	public override void visit_try_statement (TryStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		stmt.body.accept (this);
+
+		// TODO exceptional control flow
+	}
+
+	public override void visit_lock_statement (LockStatement! stmt) {
+		if (unreachable (stmt)) {
+			return;
+		}
+
+		stmt.body.accept (this);
+	}
+
+	private bool unreachable (CodeNode node) {
+		if (current_block == null) {
+			if (!unreachable_reported) {
+				Report.warning (node.source_reference, "unreachable code detected");
+				unreachable_reported = true;
+			}
+			return true;
+		}
+
+		return false;
+	}
+
+	private BasicBlock top_breakable () {
+		return breakable_stack.get (breakable_stack.size - 1);
+	}
+
+	private BasicBlock top_continuable () {
+		return continuable_stack.get (continuable_stack.size - 1);
+	}
+}

Modified: trunk/vala/valadostatement.vala
==============================================================================
--- trunk/vala/valadostatement.vala	(original)
+++ trunk/vala/valadostatement.vala	Wed Jan 23 15:26:07 2008
@@ -1,6 +1,6 @@
 /* valadostatement.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -65,15 +65,17 @@
 	 */
 	public DoStatement (construct Block! body, construct Expression! condition, construct SourceReference source_reference = null) {
 	}
-	
+
 	public override void accept (CodeVisitor! visitor) {
+		visitor.visit_do_statement (this);
+	}
+
+	public override void accept_children (CodeVisitor! visitor) {
 		body.accept (visitor);
 
 		condition.accept (visitor);
 		
 		visitor.visit_end_full_expression (condition);
-
-		visitor.visit_do_statement (this);
 	}
 
 	public override void replace_expression (Expression! old_node, Expression! new_node) {

Modified: trunk/vala/valaforstatement.vala
==============================================================================
--- trunk/vala/valaforstatement.vala	(original)
+++ trunk/vala/valaforstatement.vala	Wed Jan 23 15:26:07 2008
@@ -1,6 +1,6 @@
 /* valaforstatement.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -109,6 +109,10 @@
 	}
 	
 	public override void accept (CodeVisitor! visitor) {
+		visitor.visit_for_statement (this);
+	}
+	
+	public override void accept_children (CodeVisitor! visitor) {
 		foreach (Expression init_expr in initializer) {
 			init_expr.accept (visitor);
 			visitor.visit_end_full_expression (init_expr);
@@ -124,8 +128,6 @@
 		}
 		
 		body.accept (visitor);
-
-		visitor.visit_for_statement (this);
 	}
 
 	public override void replace_expression (Expression! old_node, Expression! new_node) {

Modified: trunk/vala/valaifstatement.vala
==============================================================================
--- trunk/vala/valaifstatement.vala	(original)
+++ trunk/vala/valaifstatement.vala	Wed Jan 23 15:26:07 2008
@@ -1,6 +1,6 @@
 /* valaifstatement.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -67,6 +67,10 @@
 	}
 	
 	public override void accept (CodeVisitor! visitor) {
+		visitor.visit_if_statement (this);
+	}
+
+	public override void accept_children (CodeVisitor! visitor) {
 		condition.accept (visitor);
 		
 		visitor.visit_end_full_expression (condition);
@@ -75,8 +79,6 @@
 		if (false_statement != null) {
 			false_statement.accept (visitor);
 		}
-
-		visitor.visit_if_statement (this);
 	}
 
 	public override void replace_expression (Expression! old_node, Expression! new_node) {

Modified: trunk/vala/valamemorymanager.vala
==============================================================================
--- trunk/vala/valamemorymanager.vala	(original)
+++ trunk/vala/valamemorymanager.vala	Wed Jan 23 15:26:07 2008
@@ -149,10 +149,26 @@
 		visit_possibly_leaked_expression (stmt.expression);
 	}
 
+	public override void visit_if_statement (IfStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
 	public override void visit_switch_section (SwitchSection! section) {
 		section.accept_children (this);
 	}
 
+	public override void visit_while_statement (WhileStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_do_statement (DoStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_for_statement (ForStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
 	public override void visit_foreach_statement (ForeachStatement! stmt) {
 		stmt.accept_children (this);
 	}

Modified: trunk/vala/valamethod.vala
==============================================================================
--- trunk/vala/valamethod.vala	(original)
+++ trunk/vala/valamethod.vala	Wed Jan 23 15:26:07 2008
@@ -42,7 +42,11 @@
 	}
 	
 	public Block body { get; set; }
-	
+
+	public BasicBlock entry_block { get; set; }
+
+	public BasicBlock exit_block { get; set; }
+
 	/**
 	 * Specifies whether this method may only be called with an instance of
 	 * the contained type.

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Wed Jan 23 15:26:07 2008
@@ -858,6 +858,8 @@
 	}
 
 	public override void visit_if_statement (IfStatement! stmt) {
+		stmt.accept_children (this);
+
 		if (stmt.condition.error) {
 			/* if there was an error in the condition, skip this check */
 			stmt.error = true;
@@ -891,6 +893,24 @@
 	}
 
 	public override void visit_while_statement (WhileStatement! stmt) {
+		stmt.accept_children (this);
+
+		if (stmt.condition.error) {
+			/* if there was an error in the condition, skip this check */
+			stmt.error = true;
+			return;
+		}
+
+		if (!stmt.condition.static_type.compatible (bool_type)) {
+			stmt.error = true;
+			Report.error (stmt.condition.source_reference, "Condition must be boolean");
+			return;
+		}
+	}
+
+	public override void visit_do_statement (DoStatement! stmt) {
+		stmt.accept_children (this);
+
 		if (stmt.condition.error) {
 			/* if there was an error in the condition, skip this check */
 			stmt.error = true;
@@ -905,6 +925,8 @@
 	}
 
 	public override void visit_for_statement (ForStatement! stmt) {
+		stmt.accept_children (this);
+
 		if (stmt.condition.error) {
 			/* if there was an error in the condition, skip this check */
 			stmt.error = true;

Modified: trunk/vala/valasymbolresolver.vala
==============================================================================
--- trunk/vala/valasymbolresolver.vala	(original)
+++ trunk/vala/valasymbolresolver.vala	Wed Jan 23 15:26:07 2008
@@ -322,10 +322,26 @@
 		list.accept_children (this);
 	}
 
+	public override void visit_if_statement (IfStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
 	public override void visit_switch_section (SwitchSection! section) {
 		section.accept_children (this);
 	}
 
+	public override void visit_while_statement (WhileStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_do_statement (DoStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_for_statement (ForStatement! stmt) {
+		stmt.accept_children (this);
+	}
+
 	public override void visit_foreach_statement (ForeachStatement! stmt) {
 		stmt.accept_children (this);
 	}

Modified: trunk/vala/valawhilestatement.vala
==============================================================================
--- trunk/vala/valawhilestatement.vala	(original)
+++ trunk/vala/valawhilestatement.vala	Wed Jan 23 15:26:07 2008
@@ -1,6 +1,6 @@
 /* valawhilestatement.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -67,13 +67,15 @@
 	}
 	
 	public override void accept (CodeVisitor! visitor) {
+		visitor.visit_while_statement (this);
+	}
+
+	public override void accept_children (CodeVisitor! visitor) {
 		condition.accept (visitor);
 		
 		visitor.visit_end_full_expression (condition);
 
 		body.accept (visitor);
-
-		visitor.visit_while_statement (this);
 	}
 
 	public override void replace_expression (Expression! old_node, Expression! new_node) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]