From: Jürg Billeter Date: Mon, 16 Nov 2009 21:07:48 +0000 (+0100) Subject: GAsync: Fix base access in async methods X-Git-Tag: 0.7.9~39 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=07e2c63dbfdb8a2c6bc802540f1ad4691952a774;p=thirdparty%2Fvala.git GAsync: Fix base access in async methods Fixes bug 601558. --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 9b240a4e8..0a7779f33 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -3220,7 +3220,15 @@ internal class Vala.CCodeBaseModule : CCodeModule { } public override void visit_base_access (BaseAccess expr) { - expr.ccodenode = generate_instance_cast (new CCodeIdentifier ("self"), expr.value_type.data_type); + CCodeExpression this_access; + if (current_method != null && current_method.coroutine) { + // use closure + this_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "self"); + } else { + this_access = new CCodeIdentifier ("self"); + } + + expr.ccodenode = generate_instance_cast (this_access, expr.value_type.data_type); } public override void visit_postfix_expression (PostfixExpression expr) { diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index c5a188db6..4589cbf1b 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -73,6 +73,24 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule { // async call async_call = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ())); + var finish_call = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ())); + + if (ma.inner is BaseAccess) { + if (m.base_method != null) { + var base_class = (Class) m.base_method.parent_symbol; + var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null)))); + vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null)))); + + async_call.call = new CCodeMemberAccess.pointer (vcast, m.vfunc_name); + finish_call.call = new CCodeMemberAccess.pointer (vcast, m.get_finish_vfunc_name ()); + } else if (m.base_interface_method != null) { + var base_iface = (Interface) m.base_interface_method.parent_symbol; + string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null)); + + async_call.call = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), m.vfunc_name); + finish_call.call = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), m.get_finish_vfunc_name ()); + } + } if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) { // no finish call @@ -80,14 +98,14 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule { params = m.get_async_begin_parameters (); } else if (ma.member_name == "end" && ma.inner.symbol_reference == ma.symbol_reference) { // no async call - ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ())); + ccall = finish_call; params = m.get_async_end_parameters (); } else if (!expr.is_yield_expression) { // same as .begin, backwards compatible to bindings without async methods ccall = async_call; params = m.get_async_begin_parameters (); } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ())); + ccall = finish_call; // output arguments used separately out_arg_map = new HashMap (direct_hash, direct_equal); diff --git a/tests/Makefile.am b/tests/Makefile.am index 7e6f22289..87d3b72de 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -71,6 +71,7 @@ TESTS = \ asynchronous/bug598698.vala \ asynchronous/bug599568.vala \ asynchronous/bug600827.vala \ + asynchronous/bug601558.vala \ dbus/basic-types.test \ dbus/arrays.test \ dbus/async.test \ diff --git a/tests/asynchronous/bug601558.vala b/tests/asynchronous/bug601558.vala new file mode 100644 index 000000000..cd98c0f0f --- /dev/null +++ b/tests/asynchronous/bug601558.vala @@ -0,0 +1,13 @@ +public class Foo { + public virtual async void do_foo () { + } +} + +public class Bar : Foo { + public override async void do_foo () { + yield base.do_foo (); + } +} + +void main () { +} diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 6828341f0..ff97edf66 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -854,7 +854,12 @@ public class Vala.Parser : CodeVisitor { Expression parse_yield_expression () throws ParseError { var begin = get_location (); expect (TokenType.YIELD); - var member = parse_member_name (); + Expression base_expr = null; + if (current () == TokenType.BASE) { + base_expr = parse_base_access (); + expect (TokenType.DOT); + } + var member = parse_member_name (base_expr); var call = (MethodCall) parse_method_call (begin, member); call.is_yield_expression = true; return call; @@ -3103,7 +3108,7 @@ public class Vala.Parser : CodeVisitor { return null; } - MemberAccess parse_member_name () throws ParseError { + MemberAccess parse_member_name (Expression? base_expr = null) throws ParseError { var begin = get_location (); MemberAccess expr = null; bool first = true; @@ -3118,7 +3123,7 @@ public class Vala.Parser : CodeVisitor { } List type_arg_list = parse_type_argument_list (false); - expr = new MemberAccess (expr, id, get_src (begin)); + expr = new MemberAccess (expr != null ? expr : base_expr, id, get_src (begin)); expr.qualified = qualified; if (type_arg_list != null) { foreach (DataType type_arg in type_arg_list) {