From: Jürg Billeter Date: Thu, 17 Jun 2010 19:53:31 +0000 (+0200) Subject: dova: Fix flow analysis of error handling in non-void methods X-Git-Tag: 0.9.2~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9fbe219b715326a9a77b29636d542591cf16f3b0;p=thirdparty%2Fvala.git dova: Fix flow analysis of error handling in non-void methods --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index d2f47abce..5b2c10180 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1634,7 +1634,7 @@ public class Vala.CCodeBaseModule : CCodeModule { if (acc.readable && !returns_real_struct) { // 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 ()); cdecl.add_declarator (new CCodeVariableDeclarator ("result")); function.block.prepend_statement (cdecl); diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index 2e30afe2c..180f417f5 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -575,7 +575,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule { cinit.append (cdecl); // 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"))); } } diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index 37fc7ea47..74c35f6f7 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -30,6 +30,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { public bool is_break_target { get; set; } public bool is_continue_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 ErrorDomain? error_domain { get; set; } public ErrorCode? error_code { get; set; } @@ -54,6 +55,11 @@ public class Vala.FlowAnalyzer : CodeVisitor { 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) { this.basic_block = basic_block; this.catch_clause = catch_clause; @@ -68,6 +74,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { is_break_target = true; is_continue_target = true; is_return_target = true; + is_exit_target = true; is_error_target = true; } @@ -172,20 +179,24 @@ public class Vala.FlowAnalyzer : CodeVisitor { } m.entry_block = new BasicBlock.entry (); + m.return_block = new BasicBlock (); m.exit_block = new BasicBlock.exit (); + m.return_block.connect (m.exit_block); + if (context.profile == Profile.DOVA && !(m.return_type is VoidType)) { // ensure result is defined at end of method var result_ma = new MemberAccess.simple ("result", m.source_reference); 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 (); m.entry_block.connect (current_block); 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); @@ -199,7 +210,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { m.error = true; } - current_block.connect (m.exit_block); + current_block.connect (m.return_block); } analyze_body (m.entry_block); @@ -494,19 +505,23 @@ public class Vala.FlowAnalyzer : CodeVisitor { } acc.entry_block = new BasicBlock.entry (); + acc.return_block = new BasicBlock (); acc.exit_block = new BasicBlock.exit (); + acc.return_block.connect (acc.exit_block); + if (context.profile == Profile.DOVA && acc.readable) { // ensure result is defined at end of method var result_ma = new MemberAccess.simple ("result", acc.source_reference); 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 (); 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); @@ -520,7 +535,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { acc.error = true; } - current_block.connect (acc.exit_block); + current_block.connect (acc.return_block); } analyze_body (acc.entry_block); @@ -844,7 +859,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { for (int i = jump_stack.size - 1; i >= 0; 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 = null; unreachable_reported = false; diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 60995c81e..8b75efd75 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -55,6 +55,8 @@ public class Vala.Method : Member { public BasicBlock entry_block { get; set; } + public BasicBlock return_block { get; set; } + public BasicBlock exit_block { get; set; } /** diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala index 0f02efb37..a4227d987 100644 --- a/vala/valapropertyaccessor.vala +++ b/vala/valapropertyaccessor.vala @@ -77,6 +77,8 @@ public class Vala.PropertyAccessor : Symbol { public BasicBlock entry_block { get; set; } + public BasicBlock return_block { get; set; } + public BasicBlock exit_block { get; set; } /**