control-flow/assigned-local-variable.vala \
control-flow/break.vala \
control-flow/break-invalid.test \
+ control-flow/coalesce-execution-order.vala \
control-flow/coalesce-reference-transfer.vala \
control-flow/coalesce-right-value.vala \
+ control-flow/coalesce-short-circuit.vala \
control-flow/continue-invalid.test \
control-flow/double-catch.test \
control-flow/expressions-conditional.vala \
control-flow/bug691514.vala \
control-flow/bug736774-1.vala \
control-flow/bug736774-2.vala \
+ control-flow/bug764440.vala \
control-flow/bug790903.test \
control-flow/bug790903-2.test \
control-semantic/argument-extra.test \
return false;
}
- if (!right.check (context)) {
+ string temp_name = get_temp_name ();
+
+ // right expression is checked under a block (required for short-circuiting)
+ var right_local = new LocalVariable (null, temp_name, right, right.source_reference);
+ var right_decl = new DeclarationStatement (right_local, right.source_reference);
+ var true_block = new Block (source_reference);
+ true_block.add_statement (right_decl);
+
+ if (!true_block.check (context)) {
error = true;
return false;
}
+ // right expression may have been replaced by the check
+ right = right_local.initializer;
+
DataType local_type = null;
bool cast_non_null = false;
if (left.value_type is NullType && right.value_type != null) {
local_type.value_owned = true;
}
- var local = new LocalVariable (local_type, get_temp_name (), left, source_reference);
+ var local = new LocalVariable (local_type, temp_name, left, source_reference);
var decl = new DeclarationStatement (local, source_reference);
+ insert_statement (context.analyzer.insert_block, decl);
+
+ if (!decl.check (context)) {
+ error = true;
+ return false;
+ }
+
+ // replace the temporary local variable used to compute the type of the right expression by an assignment
var right_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, right.source_reference), right, AssignmentOperator.SIMPLE, right.source_reference), right.source_reference);
- var true_block = new Block (source_reference);
+ true_block.remove_local_variable (right_local);
+ true_block.replace_statement (right_decl, right_stmt);
- true_block.add_statement (right_stmt);
+ if (!right_stmt.check (context)) {
+ error = true;
+ return false;
+ }
var cond = new BinaryExpression (BinaryOperator.EQUALITY, new MemberAccess.simple (local.name, left.source_reference), new NullLiteral (source_reference), source_reference);
var if_stmt = new IfStatement (cond, true_block, null, source_reference);
- insert_statement (context.analyzer.insert_block, decl);
insert_statement (context.analyzer.insert_block, if_stmt);
- if (!decl.check (context)) {
- error = true;
- return false;
- }
-
if (!if_stmt.check (context)) {
error = true;
return false;