diff options
-rw-r--r-- | ccode/valaccodefunction.vala | 6 | ||||
-rw-r--r-- | codegen/valaccodebasemodule.vala | 4 | ||||
-rw-r--r-- | codegen/valaccodemethodcallmodule.vala | 2 | ||||
-rw-r--r-- | codegen/valaccodemethodmodule.vala | 34 | ||||
-rw-r--r-- | codegen/valagasyncmodule.vala | 2 | ||||
-rw-r--r-- | codegen/valagdbusclientmodule.vala | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/asynchronous/bug741929.vala | 50 | ||||
-rw-r--r-- | vala/valamethod.vala | 2 | ||||
-rw-r--r-- | vala/valamethodcall.vala | 1 | ||||
-rw-r--r-- | vala/valaobjectcreationexpression.vala | 1 | ||||
-rw-r--r-- | vala/valayieldstatement.vala | 2 |
12 files changed, 82 insertions, 25 deletions
diff --git a/ccode/valaccodefunction.vala b/ccode/valaccodefunction.vala index 08d3876fb..ef8dad6a8 100644 --- a/ccode/valaccodefunction.vala +++ b/ccode/valaccodefunction.vala @@ -48,9 +48,13 @@ public class Vala.CCodeFunction : CCodeNode { */ public CCodeLineDirective current_line { get; set; } + /** + * The current block to be written into. + */ + public CCodeBlock current_block { get; set; } + private List<CCodeParameter> parameters = new ArrayList<CCodeParameter> (); - CCodeBlock current_block; List<CCodeStatement> statement_stack = new ArrayList<CCodeStatement> (); public CCodeFunction (string name, string return_type = "void") { diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index f083e9848..09e8c9cb7 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -38,6 +38,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { public int next_temp_var_id; public bool current_method_inner_error; public bool current_method_return; + public int next_coroutine_state = 1; public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal); public Map<string,int> closure_variable_count_map = new HashMap<string,int> (str_hash, str_equal); public Map<LocalVariable,int> closure_variable_clash_map = new HashMap<LocalVariable,int> (); @@ -270,7 +271,6 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { set { emit_context.current_method_return = value; } } - public int next_coroutine_state = 1; int next_block_id = 0; Map<Block,int> block_map = new HashMap<Block,int> (); @@ -4796,7 +4796,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { if (expr.is_yield_expression) { // set state before calling async function to support immediate callbacks - int state = next_coroutine_state++; + int state = emit_context.next_coroutine_state++; ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); ccode.add_expression (async_call); diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index 6202f319b..69d68026f 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -704,7 +704,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { if (expr.is_yield_expression) { // set state before calling async function to support immediate callbacks - int state = next_coroutine_state++; + int state = emit_context.next_coroutine_state++; ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); ccode.add_expression (async_call); diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index 700c7afdc..4d0d5fbc4 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -361,10 +361,6 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { } } - if (m.coroutine) { - next_coroutine_state = 1; - } - var creturn_type = m.return_type; if (m.return_type.is_real_non_null_struct_type ()) { // structs are returned via out parameter @@ -489,6 +485,8 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { push_function (function); + unowned CCodeBlock? co_switch_block = null; + // generate *_real_* functions for virtual methods // also generate them for abstract methods of classes to prevent faulty subclassing if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) { @@ -500,15 +498,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { ccode.add_case (new CCodeConstant ("0")); ccode.add_goto ("_state_0"); - for (int state = 1; state <= m.yield_count; state++) { - ccode.add_case (new CCodeConstant (state.to_string ())); - ccode.add_goto ("_state_%d".printf (state)); - } - - - // let gcc know that this can't happen - ccode.add_default (); - ccode.add_expression (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))); + co_switch_block = ccode.current_block; ccode.close (); @@ -732,6 +722,24 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { if (m.body != null) { m.body.emit (this); + + if (co_switch_block != null) { + // after counting the number of yields for coroutines, append the case statements to the switch + var old_block = ccode.current_block; + ccode.current_block = co_switch_block; + + for (int state = 1; state < emit_context.next_coroutine_state; state++) { + ccode.add_case (new CCodeConstant (state.to_string ())); + ccode.add_goto ("_state_%d".printf (state)); + } + + // let gcc know that this can't happen + ccode.add_default (); + ccode.add_expression (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))); + + ccode.current_block = old_block; + co_switch_block = null; + } } // we generate the same code if we see a return statement, this handles the case without returns diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index a077b4a54..74bbf5790 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -764,7 +764,7 @@ public class Vala.GAsyncModule : GtkModule { } if (stmt.yield_expression == null) { - int state = next_coroutine_state++; + int state = emit_context.next_coroutine_state++; ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); ccode.add_return (new CCodeConstant ("FALSE")); diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala index 31cd12e55..d986b24db 100644 --- a/codegen/valagdbusclientmodule.vala +++ b/codegen/valagdbusclientmodule.vala @@ -407,7 +407,7 @@ public class Vala.GDBusClientModule : GDBusModule { if (bus_get_proxy_async || conn_get_proxy_async) { if (expr.is_yield_expression) { - int state = next_coroutine_state++; + int state = emit_context.next_coroutine_state++; ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); ccode.add_expression (ccall); diff --git a/tests/Makefile.am b/tests/Makefile.am index 2a2f4d43c..fb58de2ca 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -258,6 +258,7 @@ TESTS = \ asynchronous/bug659886.vala \ asynchronous/bug661961.vala \ asynchronous/bug710103.vala \ + asynchronous/bug741929.vala \ asynchronous/bug742621.vala \ asynchronous/bug762819.vala \ asynchronous/bug777242.vala \ diff --git a/tests/asynchronous/bug741929.vala b/tests/asynchronous/bug741929.vala new file mode 100644 index 000000000..b7818231f --- /dev/null +++ b/tests/asynchronous/bug741929.vala @@ -0,0 +1,50 @@ +MainLoop? loop = null; + +class Foo : Object { + bool running = false; + + public Foo () { + } + + public async void query_async () throws Error { + running = true; + + try { + if (!yield internal_query_async ()) { + return; + } + } finally { + try { + yield close_query_async (); + } catch (Error e) { + // ignored + } + + running = false; + } + } + + async bool internal_query_async () throws Error { + return true; + } + + async void close_query_async () throws Error { + } +} + +async void go_async () { + Foo foo = new Foo (); + try { + yield foo.query_async (); + } catch (Error e) { + } + + loop.quit (); +} + +void main () { + loop = new MainLoop (); + go_async.begin (); + loop.run (); +} + diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 9988c6628..c37cfe7f1 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -183,8 +183,6 @@ public class Vala.Method : Subroutine, Callable { public bool is_async_callback { get; set; } - public int yield_count { get; set; } - private List<Parameter> parameters = new ArrayList<Parameter> (); private List<Expression> preconditions; private List<Expression> postconditions; diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index cefc65131..444395ac3 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -478,7 +478,6 @@ public class Vala.MethodCall : Expression { error = true; Report.error (source_reference, "yield expression not available outside async method"); } - context.analyzer.current_method.yield_count++; } if (m != null && m.coroutine && !is_yield_expression && ((MemberAccess) call).member_name != "end") { // .begin call of async method, no error can happen here diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala index c4b119a44..4e5a9b958 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -358,7 +358,6 @@ public class Vala.ObjectCreationExpression : Expression { error = true; Report.error (source_reference, "yield expression not available outside async method"); } - context.analyzer.current_method.yield_count++; } // FIXME partial code duplication of MethodCall.check diff --git a/vala/valayieldstatement.vala b/vala/valayieldstatement.vala index 8b2069f21..5b5a6f307 100644 --- a/vala/valayieldstatement.vala +++ b/vala/valayieldstatement.vala @@ -75,8 +75,6 @@ public class Vala.YieldStatement : CodeNode, Statement { error = yield_expression.error; } - context.analyzer.current_method.yield_count++; - return !error; } |