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



commit 9863d3dec36984dbce550c8c45cd932ebcd72275
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 750257d33..fccc80dbe 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2395,6 +2395,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));
        }
@@ -6165,9 +6181,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 4e5cb10b8..4d7cf1d8e 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 6f16d9569..f5bf01eb3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -319,8 +319,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 933a67c26..d61e47a51 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -507,14 +507,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) {
@@ -525,6 +525,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;
@@ -705,7 +715,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]