Commit 9fbe219b authored by Jürg Billeter's avatar Jürg Billeter

dova: Fix flow analysis of error handling in non-void methods

parent 47b5fc36
...@@ -1634,7 +1634,7 @@ public class Vala.CCodeBaseModule : CCodeModule { ...@@ -1634,7 +1634,7 @@ public class Vala.CCodeBaseModule : CCodeModule {
if (acc.readable && !returns_real_struct) { if (acc.readable && !returns_real_struct) {
// do not declare result variable if exit block is known to be unreachable // do not declare result variable if exit block is known to be unreachable
if (acc.exit_block == null || acc.exit_block.get_predecessors ().size > 0) { if (acc.return_block == null || acc.return_block.get_predecessors ().size > 0) {
var cdecl = new CCodeDeclaration (acc.value_type.get_cname ()); var cdecl = new CCodeDeclaration (acc.value_type.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator ("result")); cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
function.block.prepend_statement (cdecl); function.block.prepend_statement (cdecl);
......
...@@ -575,7 +575,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule { ...@@ -575,7 +575,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
cinit.append (cdecl); cinit.append (cdecl);
// add dummy return if exit block is known to be unreachable to silence C compiler // add dummy return if exit block is known to be unreachable to silence C compiler
if (m.exit_block != null && m.exit_block.get_predecessors ().size == 0) { if (m.return_block != null && m.return_block.get_predecessors ().size == 0) {
function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
} }
} }
......
...@@ -30,6 +30,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -30,6 +30,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
public bool is_break_target { get; set; } public bool is_break_target { get; set; }
public bool is_continue_target { get; set; } public bool is_continue_target { get; set; }
public bool is_return_target { get; set; } public bool is_return_target { get; set; }
public bool is_exit_target { get; set; }
public bool is_error_target { get; set; } public bool is_error_target { get; set; }
public ErrorDomain? error_domain { get; set; } public ErrorDomain? error_domain { get; set; }
public ErrorCode? error_code { get; set; } public ErrorCode? error_code { get; set; }
...@@ -54,6 +55,11 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -54,6 +55,11 @@ public class Vala.FlowAnalyzer : CodeVisitor {
is_return_target = true; is_return_target = true;
} }
public JumpTarget.exit_target (BasicBlock basic_block) {
this.basic_block = basic_block;
is_exit_target = true;
}
public JumpTarget.error_target (BasicBlock basic_block, CatchClause catch_clause, ErrorDomain? error_domain, ErrorCode? error_code, Class? error_class) { public JumpTarget.error_target (BasicBlock basic_block, CatchClause catch_clause, ErrorDomain? error_domain, ErrorCode? error_code, Class? error_class) {
this.basic_block = basic_block; this.basic_block = basic_block;
this.catch_clause = catch_clause; this.catch_clause = catch_clause;
...@@ -68,6 +74,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -68,6 +74,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
is_break_target = true; is_break_target = true;
is_continue_target = true; is_continue_target = true;
is_return_target = true; is_return_target = true;
is_exit_target = true;
is_error_target = true; is_error_target = true;
} }
...@@ -172,20 +179,24 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -172,20 +179,24 @@ public class Vala.FlowAnalyzer : CodeVisitor {
} }
m.entry_block = new BasicBlock.entry (); m.entry_block = new BasicBlock.entry ();
m.return_block = new BasicBlock ();
m.exit_block = new BasicBlock.exit (); m.exit_block = new BasicBlock.exit ();
m.return_block.connect (m.exit_block);
if (context.profile == Profile.DOVA && !(m.return_type is VoidType)) { if (context.profile == Profile.DOVA && !(m.return_type is VoidType)) {
// ensure result is defined at end of method // ensure result is defined at end of method
var result_ma = new MemberAccess.simple ("result", m.source_reference); var result_ma = new MemberAccess.simple ("result", m.source_reference);
result_ma.symbol_reference = m.result_var; result_ma.symbol_reference = m.result_var;
m.exit_block.add_node (result_ma); m.return_block.add_node (result_ma);
} }
current_block = new BasicBlock (); current_block = new BasicBlock ();
m.entry_block.connect (current_block); m.entry_block.connect (current_block);
current_block.add_node (m); current_block.add_node (m);
jump_stack.add (new JumpTarget.return_target (m.exit_block)); jump_stack.add (new JumpTarget.return_target (m.return_block));
jump_stack.add (new JumpTarget.exit_target (m.exit_block));
m.accept_children (this); m.accept_children (this);
...@@ -199,7 +210,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -199,7 +210,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
m.error = true; m.error = true;
} }
current_block.connect (m.exit_block); current_block.connect (m.return_block);
} }
analyze_body (m.entry_block); analyze_body (m.entry_block);
...@@ -494,19 +505,23 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -494,19 +505,23 @@ public class Vala.FlowAnalyzer : CodeVisitor {
} }
acc.entry_block = new BasicBlock.entry (); acc.entry_block = new BasicBlock.entry ();
acc.return_block = new BasicBlock ();
acc.exit_block = new BasicBlock.exit (); acc.exit_block = new BasicBlock.exit ();
acc.return_block.connect (acc.exit_block);
if (context.profile == Profile.DOVA && acc.readable) { if (context.profile == Profile.DOVA && acc.readable) {
// ensure result is defined at end of method // ensure result is defined at end of method
var result_ma = new MemberAccess.simple ("result", acc.source_reference); var result_ma = new MemberAccess.simple ("result", acc.source_reference);
result_ma.symbol_reference = acc.result_var; result_ma.symbol_reference = acc.result_var;
acc.exit_block.add_node (result_ma); acc.return_block.add_node (result_ma);
} }
current_block = new BasicBlock (); current_block = new BasicBlock ();
acc.entry_block.connect (current_block); acc.entry_block.connect (current_block);
jump_stack.add (new JumpTarget.return_target (acc.exit_block)); jump_stack.add (new JumpTarget.return_target (acc.return_block));
jump_stack.add (new JumpTarget.exit_target (acc.exit_block));
acc.accept_children (this); acc.accept_children (this);
...@@ -520,7 +535,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -520,7 +535,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
acc.error = true; acc.error = true;
} }
current_block.connect (acc.exit_block); current_block.connect (acc.return_block);
} }
analyze_body (acc.entry_block); analyze_body (acc.entry_block);
...@@ -844,7 +859,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { ...@@ -844,7 +859,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
for (int i = jump_stack.size - 1; i >= 0; i--) { for (int i = jump_stack.size - 1; i >= 0; i--) {
var jump_target = jump_stack[i]; var jump_target = jump_stack[i];
if (jump_target.is_return_target) { if (jump_target.is_exit_target) {
current_block.connect (jump_target.basic_block); current_block.connect (jump_target.basic_block);
current_block = null; current_block = null;
unreachable_reported = false; unreachable_reported = false;
......
...@@ -55,6 +55,8 @@ public class Vala.Method : Member { ...@@ -55,6 +55,8 @@ public class Vala.Method : Member {
public BasicBlock entry_block { get; set; } public BasicBlock entry_block { get; set; }
public BasicBlock return_block { get; set; }
public BasicBlock exit_block { get; set; } public BasicBlock exit_block { get; set; }
/** /**
......
...@@ -77,6 +77,8 @@ public class Vala.PropertyAccessor : Symbol { ...@@ -77,6 +77,8 @@ public class Vala.PropertyAccessor : Symbol {
public BasicBlock entry_block { get; set; } public BasicBlock entry_block { get; set; }
public BasicBlock return_block { get; set; }
public BasicBlock exit_block { get; set; } public BasicBlock exit_block { get; set; }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment