summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2019-10-17 14:04:15 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2019-11-07 11:52:44 +0100
commit18ed2b1cad816b9bfcd5f864d9ff53286dae6ba1 (patch)
tree53370fd5be322377a5f393ab87c0ba808fdbd1d3
parenta476dc552cdb0afba4e4239051ce10c0987009f0 (diff)
downloadvala-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.vala20
-rw-r--r--codegen/valaccodememberaccessmodule.vala8
-rw-r--r--codegen/valaccodemethodcallmodule.vala6
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/objects/interface-async-base-access.vala25
-rw-r--r--tests/objects/interface-base-access.vala25
-rw-r--r--tests/objects/interface-property-base-access.vala20
-rw-r--r--vala/valaclass.vala20
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 ());
}
}