[vala/0.40] codegen: Use G_TYPE_INSTANCE_GET_INTERFACE to get vtable for base-access



commit 61fbeca91748c185604e70517d70821f66ccd705
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Thu Oct 17 14:04:15 2019 +0200

    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.

 codegen/valaccodebasemodule.vala                  | 20 ++++++++++++++++--
 codegen/valaccodememberaccessmodule.vala          |  8 ++++----
 codegen/valaccodemethodcallmodule.vala            |  6 +++---
 tests/Makefile.am                                 |  3 +++
 tests/objects/interface-async-base-access.vala    | 25 +++++++++++++++++++++++
 tests/objects/interface-base-access.vala          | 25 +++++++++++++++++++++++
 tests/objects/interface-property-base-access.vala | 20 ++++++++++++++++++
 vala/valaclass.vala                               | 20 +++++++++++++-----
 8 files changed, 113 insertions(+), 14 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 37d42dc1a..a4277299b 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2362,6 +2362,22 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                }
        }
 
+       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 () {
                if (is_in_coroutine ()) {
                        return new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), 
"_inner_error%d_".printf (current_inner_error_id));
@@ -6056,9 +6072,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 0ddffc962..51708e584 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 d8eabffd0..115ec891f 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -102,10 +102,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 791acaa45..01053cb68 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -283,7 +283,10 @@ TESTS = \
        objects/fields.vala \
        objects/gsource.vala \
        objects/instance-comparison.vala \
+       objects/interface-async-base-access.vala \
+       objects/interface-base-access.vala \
        objects/interfaces.vala \
+       objects/interface-property-base-access.vala \
        objects/methods.vala \
        objects/paramspec.vala \
        objects/properties.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 dafef35ef..a891c0c9e 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -468,14 +468,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) {
@@ -486,6 +486,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;
@@ -649,7 +659,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 ());
                        }
                }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]