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



commit 81dbabcc8535a28f660e3b28a21f8e44f3a74647
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
    
    Using the pre-assigned *_parent_iface field it error prone. It only works
    for direct implementations in the same source file.

 codegen/valaccodebasemodule.vala                  | 16 +++++++++++++--
 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 ++++++++++++++++++
 tests/objects/methods.vala                        |  2 +-
 vala/valaclass.vala                               | 10 ++++-----
 9 files changed, 100 insertions(+), 15 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 83f028013..1db8066f1 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2385,6 +2385,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                return get_cexpression ("self");
        }
 
+       public CCodeExpression get_this_interface_cexpression (Interface 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));
        }
@@ -6039,9 +6051,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 54a71a3e2..2a37ceb5c 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;
                                }
                        }
@@ -219,9 +219,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 3c3290092..fc0561dd7 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 6578f43ab..b0a89eb41 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -323,9 +323,12 @@ TESTS = \
        objects/gsource.vala \
        objects/instance-comparison.vala \
        objects/interface_only.vala \
+       objects/interface-async-base-access.vala
+       objects/interface-base-access.vala
        objects/interface-inner-types.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/tests/objects/methods.vala b/tests/objects/methods.vala
index 9a950c322..018aac8ba 100644
--- a/tests/objects/methods.vala
+++ b/tests/objects/methods.vala
@@ -151,7 +151,7 @@ namespace Maman.BaseAccess {
                }
        }
 
-       public class FooBar : Foo, IFoo {
+       public class FooBar : Foo {
                public int interface_method () {
                        return base.interface_method () * 10 + 6;
                }
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 507a10d23..92096fcff 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -469,14 +469,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.type_symbol is Class) {
-                               if (class_is_a ((Class) base_type.type_symbol, t)) {
+                               if (((Class) base_type.type_symbol).is_a (t)) {
                                        return true;
                                }
                        } else if (base_type.type_symbol == t) {
@@ -671,7 +671,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]