summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ccode/valaccodefunction.vala6
-rw-r--r--codegen/valaccodebasemodule.vala4
-rw-r--r--codegen/valaccodemethodcallmodule.vala2
-rw-r--r--codegen/valaccodemethodmodule.vala34
-rw-r--r--codegen/valagasyncmodule.vala2
-rw-r--r--codegen/valagdbusclientmodule.vala2
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/asynchronous/bug741929.vala50
-rw-r--r--vala/valamethod.vala2
-rw-r--r--vala/valamethodcall.vala1
-rw-r--r--vala/valaobjectcreationexpression.vala1
-rw-r--r--vala/valayieldstatement.vala2
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;
}