diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2019-10-17 14:04:15 +0200 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2019-11-07 11:52:44 +0100 |
commit | 18ed2b1cad816b9bfcd5f864d9ff53286dae6ba1 (patch) | |
tree | 53370fd5be322377a5f393ab87c0ba808fdbd1d3 | |
parent | a476dc552cdb0afba4e4239051ce10c0987009f0 (diff) | |
download | vala-18ed2b1cad816b9bfcd5f864d9ff53286dae6ba1.tar.gz |
codegen: Use G_TYPE_INSTANCE_GET_INTERFACE to get vtable for base-access
Usage of the pre-assigned *_parent_iface field is only possible in classes
which explicitly implement an interface.
-rw-r--r-- | codegen/valaccodebasemodule.vala | 20 | ||||
-rw-r--r-- | codegen/valaccodememberaccessmodule.vala | 8 | ||||
-rw-r--r-- | codegen/valaccodemethodcallmodule.vala | 6 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/objects/interface-async-base-access.vala | 25 | ||||
-rw-r--r-- | tests/objects/interface-base-access.vala | 25 | ||||
-rw-r--r-- | tests/objects/interface-property-base-access.vala | 20 | ||||
-rw-r--r-- | vala/valaclass.vala | 20 |
8 files changed, 113 insertions, 14 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 7ae022aa3..c9362387e 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -2391,6 +2391,22 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { return get_cexpression ("self"); } + public CCodeExpression get_this_interface_cexpression (Interface iface) { + if (current_class.implements (iface)) { + return new CCodeIdentifier ("%s_%s_parent_iface".printf (get_ccode_lower_case_name (current_class), get_ccode_lower_case_name (iface))); + } + + if (!current_class.is_a (iface)) { + Report.warning (current_class.source_reference, "internal: `%s' is not a `%s'".printf (current_class.get_full_name (), iface.get_full_name ())); + } + + var vcast = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_INSTANCE_GET_INTERFACE")); + vcast.add_argument (get_this_cexpression ()); + vcast.add_argument (new CCodeIdentifier (get_ccode_type_id (iface))); + vcast.add_argument (new CCodeIdentifier (get_ccode_type_name (iface))); + return vcast; + } + public CCodeExpression get_inner_error_cexpression () { return get_cexpression ("_inner_error%d_".printf (current_inner_error_id)); } @@ -6185,9 +6201,9 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { ccode.add_expression (ccall); } else if (prop.base_interface_property != null) { var base_iface = (Interface) prop.base_interface_property.parent_symbol; - string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (current_class), get_ccode_lower_case_name (base_iface)); + var vcast = get_this_interface_cexpression (base_iface); - var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), "set_%s".printf (prop.name))); + var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name))); ccall.add_argument ((CCodeExpression) get_ccodenode (instance)); var cexpr = get_cvalue_ (value); if (prop.property_type.is_real_non_null_struct_type ()) { diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala index 8fb01eaa6..2359f4ba8 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -58,9 +58,9 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { return; } 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 (get_ccode_lower_case_name (current_class), get_ccode_lower_case_name (base_iface)); + var vcast = get_this_interface_cexpression (base_iface); - set_cvalue (expr, new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), get_ccode_vfunc_name (m))); + set_cvalue (expr, new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m))); return; } } @@ -206,9 +206,9 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { } } else if (base_prop.parent_symbol is Interface) { var base_iface = (Interface) base_prop.parent_symbol; - string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (current_class), get_ccode_lower_case_name (base_iface)); + var vcast = get_this_interface_cexpression (base_iface); - var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), "get_%s".printf (prop.name))); + var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name))); ccall.add_argument (get_cvalue (expr.inner)); if (prop.property_type.is_real_non_null_struct_type ()) { var temp_value = (GLibValue) create_temp_value (prop.get_accessor.value_type, false, expr); diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index d388e15b8..3a698d612 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -104,10 +104,10 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { finish_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m)); } 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 (get_ccode_lower_case_name (current_class), get_ccode_lower_case_name (base_iface)); + var vcast = get_this_interface_cexpression (base_iface); - async_call.call = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), get_ccode_vfunc_name (m)); - finish_call.call = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), get_ccode_finish_vfunc_name (m)); + async_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m)); + finish_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m)); } } diff --git a/tests/Makefile.am b/tests/Makefile.am index 357ba6924..b6ed4f931 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -314,8 +314,11 @@ TESTS = \ objects/gsource.vala \ objects/instance-comparison.vala \ objects/interface_only.vala \ + objects/interface-async-base-access.vala \ + objects/interface-base-access.vala \ objects/interfaces.vala \ objects/interface-generics.vala \ + objects/interface-property-base-access.vala \ objects/interface-virtual-override.vala \ objects/methods.vala \ objects/paramspec.vala \ diff --git a/tests/objects/interface-async-base-access.vala b/tests/objects/interface-async-base-access.vala new file mode 100644 index 000000000..2c8bccfd9 --- /dev/null +++ b/tests/objects/interface-async-base-access.vala @@ -0,0 +1,25 @@ +interface IFoo { + public abstract async void foo (); +} + +class Bar : IFoo { + public async void foo () { + reached = true; + } +} + +class Foo : Bar { + public async void bar () { + yield base.foo (); + } +} + +bool reached = false; + +void main () { + var foo = new Foo (); + assert (foo is IFoo); + + foo.bar.begin (); + assert (reached); +} diff --git a/tests/objects/interface-base-access.vala b/tests/objects/interface-base-access.vala new file mode 100644 index 000000000..f0e853e25 --- /dev/null +++ b/tests/objects/interface-base-access.vala @@ -0,0 +1,25 @@ +interface IFoo { + public abstract void foo (); +} + +class Bar : IFoo { + public void foo () { + reached = true; + } +} + +class Foo : Bar { + public void bar () { + base.foo (); + } +} + +bool reached = false; + +void main () { + var foo = new Foo (); + assert (foo is IFoo); + + foo.bar (); + assert (reached); +} diff --git a/tests/objects/interface-property-base-access.vala b/tests/objects/interface-property-base-access.vala new file mode 100644 index 000000000..036ce8b1e --- /dev/null +++ b/tests/objects/interface-property-base-access.vala @@ -0,0 +1,20 @@ +interface IFoo { + public abstract string foo { get; set; } +} + +class Bar : IFoo { + public string foo { get; set; } +} + +class Foo : Bar { + public string bar (string s) { + base.foo = s; + return base.foo; + } +} + +void main () { + var foo = new Foo (); + assert (foo is IFoo); + assert (foo.bar ("foo") == "foo"); +} diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 51e8fbade..9823d76a3 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -497,14 +497,14 @@ public class Vala.Class : ObjectTypeSymbol { } } - private bool class_is_a (Class cl, TypeSymbol t) { - if (cl == t) { + public bool is_a (ObjectTypeSymbol t) { + if (this == t) { return true; } - foreach (DataType base_type in cl.get_base_types ()) { + foreach (DataType base_type in get_base_types ()) { if (base_type.data_type is Class) { - if (class_is_a ((Class) base_type.data_type, t)) { + if (((Class) base_type.data_type).is_a (t)) { return true; } } else if (base_type.data_type == t) { @@ -515,6 +515,16 @@ public class Vala.Class : ObjectTypeSymbol { return false; } + public bool implements (Interface i) { + foreach (DataType base_type in get_base_types ()) { + if (base_type.data_type == i) { + return true; + } + } + + return false; + } + public override bool check (CodeContext context) { if (checked) { return !error; @@ -695,7 +705,7 @@ public class Vala.Class : ObjectTypeSymbol { /* check whether all prerequisites are met */ List<string> missing_prereqs = new ArrayList<string> (); foreach (TypeSymbol prereq in prerequisites) { - if (!class_is_a (this, prereq)) { + if (!is_a ((ObjectTypeSymbol) prereq)) { missing_prereqs.insert (0, prereq.get_full_name ()); } } |