+2008-11-30 Jürg Billeter <j@bitron.ch>
+
+ * vala/valaaddressofexpression.vala:
+ * vala/valaarraycreationexpression.vala:
+ * vala/valaassignment.vala:
+ * vala/valabaseaccess.vala:
+ * vala/valabinaryexpression.vala:
+ * vala/valablock.vala:
+ * vala/valacastexpression.vala:
+ * vala/valaconditionalexpression.vala:
+ * vala/valadostatement.vala:
+ * vala/valaelementaccess.vala:
+ * vala/valaexpression.vala:
+ * vala/valaforstatement.vala:
+ * vala/valainitializerlist.vala:
+ * vala/valalambdaexpression.vala:
+ * vala/valaliteral.vala:
+ * vala/valamemberaccess.vala:
+ * vala/valamethodcall.vala:
+ * vala/valaobjectcreationexpression.vala:
+ * vala/valaparenthesizedexpression.vala:
+ * vala/valapointerindirection.vala:
+ * vala/valapostfixexpression.vala:
+ * vala/valareferencetransferexpression.vala:
+ * vala/valasemanticanalyzer.vala:
+ * vala/valasizeofexpression.vala:
+ * vala/valaswitchsection.vala:
+ * vala/valatuple.vala:
+ * vala/valatypecheck.vala:
+ * vala/valatypeofexpression.vala:
+ * vala/valaunaryexpression.vala:
+ * vala/valawhilestatement.vala:
+ * gobject/valaccodebasemodule.vala:
+
+ Fix error handling in condition of while, do, and for statements
+
2008-11-30 Jürg Billeter <j@bitron.ch>
* vala/valaexpressionstatement.vala:
}
public override void visit_block (Block b) {
+ var old_symbol = current_symbol;
current_symbol = b;
b.accept_children (codegen);
b.ccodenode = cblock;
- current_symbol = current_symbol.parent_symbol;
+ current_symbol = old_symbol;
}
public override void visit_empty_statement (EmptyStatement stmt) {
return !error;
}
-
- public override bool in_single_basic_block () {
- return inner.in_single_basic_block ();
- }
}
return !error;
}
-
- public override bool in_single_basic_block () {
- foreach (Expression size in sizes) {
- if (!size.in_single_basic_block ()) {
- return false;
- }
- }
- return true;
- }
}
}
right.get_used_variables (collection);
}
-
- public override bool in_single_basic_block () {
- return left.in_single_basic_block () && right.in_single_basic_block ();
- }
}
public enum Vala.AssignmentOperator {
return !error;
}
-
- public override bool in_single_basic_block () {
- return true;
- }
}
checked = true;
if (operator == BinaryOperator.AND || operator == BinaryOperator.OR) {
+ var old_insert_block = analyzer.insert_block;
+ analyzer.insert_block = prepare_condition_split (analyzer);
+
// convert conditional expression into if statement
// required for flow analysis and exception handling
var if_stmt = new IfStatement (left, true_block, false_block, source_reference);
- insert_statement ((Block) analyzer.current_symbol, decl);
- insert_statement ((Block) analyzer.current_symbol, if_stmt);
+ insert_statement (analyzer.insert_block, decl);
+ insert_statement (analyzer.insert_block, if_stmt);
if (!if_stmt.check (analyzer)) {
return false;
}
+ analyzer.insert_block = old_insert_block;
var ma = new MemberAccess.simple (local.name, source_reference);
ma.target_type = target_type;
left.get_used_variables (collection);
right.get_used_variables (collection);
}
-
- public override bool in_single_basic_block () {
- if (operator == BinaryOperator.AND
- || operator == BinaryOperator.OR) {
- return false;
- }
- return left.in_single_basic_block () && right.in_single_basic_block ();
- }
}
public enum Vala.BinaryOperator {
owner = analyzer.current_symbol.scope;
var old_symbol = analyzer.current_symbol;
+ var old_insert_block = analyzer.insert_block;
analyzer.current_symbol = this;
+ analyzer.insert_block = this;
for (int i = 0; i < statement_list.size; i++) {
statement_list[i].check (analyzer);
}
analyzer.current_symbol = old_symbol;
+ analyzer.insert_block = old_insert_block;
return !error;
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
-
- public override bool in_single_basic_block () {
- return inner.in_single_basic_block ();
- }
}
checked = true;
+ var old_insert_block = analyzer.insert_block;
+ analyzer.insert_block = prepare_condition_split (analyzer);
+
// convert ternary expression into if statement
// required for flow analysis and exception handling
var if_stmt = new IfStatement (condition, true_block, false_block, source_reference);
- insert_statement ((Block) analyzer.current_symbol, decl);
- insert_statement ((Block) analyzer.current_symbol, if_stmt);
+ insert_statement (analyzer.insert_block, decl);
+ insert_statement (analyzer.insert_block, if_stmt);
if (!if_stmt.check (analyzer)) {
return false;
}
+ analyzer.insert_block = old_insert_block;
true_expression = true_local.initializer;
false_expression = false_local.initializer;
return true;
}
-
- public override bool in_single_basic_block () {
- return false;
- }
}
private Expression _condition;
private Block _body;
-
+
/**
* Creates a new do statement.
*
checked = true;
- if (!condition.in_single_basic_block ()) {
- /* move condition into the loop body to allow split
- * in multiple statements
- *
- * first = false;
- * do {
- * if (first) {
- * if (!condition) {
- * break;
- * }
- * }
- * first = true;
- * ...
- * } while (true);
- */
-
- var first_local = new LocalVariable (new ValueType (analyzer.bool_type.data_type), get_temp_name (), new BooleanLiteral (false, source_reference), source_reference);
- var first_decl = new DeclarationStatement (first_local, source_reference);
- first_decl.check (analyzer);
- var block = (Block) analyzer.current_symbol;
- block.insert_before (this, first_decl);
-
- 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 MemberAccess.simple (first_local.name, 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 (true, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));
-
- condition = new BooleanLiteral (true, source_reference);
- }
-
- body.check (analyzer);
-
if (!condition.check (analyzer)) {
/* if there was an error in the condition, skip this check */
error = true;
return false;
}
+ body.check (analyzer);
+
add_error_types (condition.get_error_types ());
add_error_types (body.get_error_types ());
return !error;
}
+
+ public Block prepare_condition_split (SemanticAnalyzer analyzer) {
+ /* move condition into the loop body to allow split
+ * in multiple statements
+ *
+ * first = false;
+ * do {
+ * if (first) {
+ * if (!condition) {
+ * break;
+ * }
+ * }
+ * first = true;
+ * ...
+ * } while (true);
+ */
+
+ var first_local = new LocalVariable (new ValueType (analyzer.bool_type.data_type), get_temp_name (), new BooleanLiteral (false, source_reference), source_reference);
+ var first_decl = new DeclarationStatement (first_local, source_reference);
+ first_decl.check (analyzer);
+ var block = (Block) analyzer.current_symbol;
+ block.insert_before (this, first_decl);
+
+ 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 MemberAccess.simple (first_local.name, 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 (true, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));
+
+ condition = new BooleanLiteral (true, source_reference);
+ condition.check (analyzer);
+
+ return condition_block;
+ }
}
index.get_used_variables (collection);
}
}
-
- public override bool in_single_basic_block () {
- foreach (Expression index in indices) {
- if (!index.in_single_basic_block ()) {
- return false;
- }
- }
- return container.in_single_basic_block ();
- }
}
}
}
+ public Block prepare_condition_split (SemanticAnalyzer analyzer) {
+ var while_stmt = parent_statement as WhileStatement;
+ var do_stmt = parent_statement as DoStatement;
+ var for_stmt = parent_statement as ForStatement;
+
+ if (while_stmt != null) {
+ return while_stmt.prepare_condition_split (analyzer);
+ } else if (do_stmt != null) {
+ return do_stmt.prepare_condition_split (analyzer);
+ } else if (for_stmt != null) {
+ return for_stmt.prepare_condition_split (analyzer);
+ }
+
+ return analyzer.insert_block;
+ }
+
public void insert_statement (Block block, Statement stmt) {
block.insert_before (parent_statement, stmt);
}
-
- /**
- * Returns whether this expression is guaranteed to be part of a
- * single basic block in the control flow graph.
- */
- public abstract bool in_single_basic_block ();
}
checked = true;
-
- if (condition != null && !condition.in_single_basic_block ()) {
- // move condition into the loop body to allow split
- // in multiple statements
-
- 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);
- body.insert_statement (0, if_stmt);
-
- condition = new BooleanLiteral (true, source_reference);
- }
-
foreach (Expression init_expr in initializer) {
init_expr.check (analyzer);
}
return !error;
}
+
+ public Block prepare_condition_split (SemanticAnalyzer analyzer) {
+ // move condition into the loop body to allow split
+ // in multiple statements
+
+ 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);
+ body.insert_statement (0, if_stmt);
+
+ condition = new BooleanLiteral (true, source_reference);
+ condition.check (analyzer);
+
+ return body;
+ }
}
return !error;
}
-
- public override bool in_single_basic_block () {
- foreach (Expression initializer in initializers) {
- if (!initializer.in_single_basic_block ()) {
- return false;
- }
- }
- return true;
- }
}
return !error;
}
-
- public override bool in_single_basic_block () {
- return true;
- }
}
public override bool is_pure () {
return true;
}
-
- public override bool in_single_basic_block () {
- return true;
- }
}
collection.add (local);
}
}
-
- public override bool in_single_basic_block () {
- return inner == null || inner.in_single_basic_block ();
- }
}
if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
// simple statements, no side effects after method call
} else {
+ var old_insert_block = analyzer.insert_block;
+ analyzer.insert_block = prepare_condition_split (analyzer);
+
// store parent_node as we need to replace the expression in the old parent node later on
var old_parent_node = parent_node;
var local = new LocalVariable (value_type, get_temp_name (), null, source_reference);
var decl = new DeclarationStatement (local, source_reference);
- insert_statement ((Block) analyzer.current_symbol, decl);
+ insert_statement (analyzer.insert_block, decl);
var temp_access = new MemberAccess.simple (local.name, source_reference);
temp_access.target_type = target_type;
decl.check (analyzer);
temp_access.check (analyzer);
+ analyzer.insert_block = old_insert_block;
+
old_parent_node.replace_expression (this, temp_access);
}
}
arg.get_used_variables (collection);
}
}
-
- public override bool in_single_basic_block () {
- foreach (Expression arg in argument_list) {
- if (!arg.in_single_basic_block ()) {
- return false;
- }
- }
- return call.in_single_basic_block ();
- }
}
arg.get_used_variables (collection);
}
}
-
- public override bool in_single_basic_block () {
- foreach (Expression arg in argument_list) {
- if (!arg.in_single_basic_block ()) {
- return false;
- }
- }
- return true;
- }
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
-
- public override bool in_single_basic_block () {
- return inner.in_single_basic_block ();
- }
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
-
- public override bool in_single_basic_block () {
- return inner.in_single_basic_block ();
- }
}
return !error;
}
-
- public override bool in_single_basic_block () {
- return true;
- }
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
-
- public override bool in_single_basic_block () {
- return inner.in_single_basic_block ();
- }
}
public Class current_class;
public Struct current_struct;
+ public Block insert_block;
+
public DataType bool_type;
public DataType string_type;
public DataType uchar_type;
return !error;
}
-
- public override bool in_single_basic_block () {
- return true;
- }
}
}
owner = analyzer.current_symbol.scope;
+
+ var old_symbol = analyzer.current_symbol;
+ var old_insert_block = analyzer.insert_block;
analyzer.current_symbol = this;
+ analyzer.insert_block = this;
foreach (Statement st in get_statements ()) {
st.check (analyzer);
local.active = false;
}
- analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
+ analyzer.current_symbol = old_symbol;
+ analyzer.insert_block = old_insert_block;
return !error;
}
public override bool is_pure () {
return false;
}
-
- public override bool in_single_basic_block () {
- foreach (Expression expr in expression_list) {
- if (!expr.in_single_basic_block ()) {
- return false;
- }
- }
- return true;
- }
}
return !error;
}
-
- public override bool in_single_basic_block () {
- return expression.in_single_basic_block ();
- }
}
return !error;
}
-
- public override bool in_single_basic_block () {
- return true;
- }
}
inner.get_used_variables (collection);
}
}
-
- public override bool in_single_basic_block () {
- return inner.in_single_basic_block ();
- }
}
public enum Vala.UnaryOperator {
checked = true;
- if (!condition.in_single_basic_block ()) {
- // move condition into the loop body to allow split
- // in multiple statements
-
- 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);
- body.insert_statement (0, if_stmt);
-
- condition = new BooleanLiteral (true, source_reference);
- }
-
condition.check (analyzer);
body.check (analyzer);
return !error;
}
+
+ public Block prepare_condition_split (SemanticAnalyzer analyzer) {
+ // move condition into the loop body to allow split
+ // in multiple statements
+
+ 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);
+ body.insert_statement (0, if_stmt);
+
+ condition = new BooleanLiteral (true, source_reference);
+ condition.check (analyzer);
+
+ return body;
+ }
}
+