]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Support GObject properties with nullable GType-based struct type 3af1cfb3bf6b1d3d4a8116382e6eda702f7335bf
authorRico Tzschichholz <ricotz@ubuntu.com>
Mon, 6 May 2019 12:48:25 +0000 (14:48 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 6 May 2019 13:10:28 +0000 (15:10 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/792

codegen/valaccodebasemodule.vala
codegen/valagobjectmodule.vala
tests/Makefile.am
tests/objects/property-gboxed-nullable.vala [new file with mode: 0644]
vala/valasemanticanalyzer.vala

index 9d6320ccfd74d1109443135aeef5d3da290f6236..17091394ff61c1374bee680a76500bb617a1e6b3 100644 (file)
@@ -1883,16 +1883,20 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                                ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("0")));
                                        } else if (property_type is StructValueType) {
                                                ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value"));
-                                               get_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
-
-                                               var get_expr = new CCodeCommaExpression ();
-                                               get_expr.append_expression (get_call);
-                                               get_expr.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
-
+                                               if (property_type.nullable) {
+                                                       ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call);
+                                               } else {
+                                                       get_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
+                                                       ccode.add_expression (get_call);
+                                               }
                                                var equalfunc = generate_struct_equal_function ((Struct) property_type.data_type);
                                                var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc));
                                                ccall.add_argument (new CCodeIdentifier ("value"));
-                                               ccall.add_argument (get_expr);
+                                               if (property_type.nullable) {
+                                                       ccall.add_argument (new CCodeIdentifier ("old_value"));
+                                               } else {
+                                                       ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
+                                               }
                                                ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("TRUE")));
                                        } else {
                                                ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_call, new CCodeIdentifier ("value")));
index 8ad676ab9d1b195492fb7c0089112fc6607f6f92..8c31c924f485b9009e0ad6c37909db241b75d0f0 100644 (file)
@@ -233,21 +233,26 @@ public class Vala.GObjectModule : GTypeModule {
 
                        ccode.add_case (new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop))));
                        if (prop.property_type.is_real_struct_type ()) {
-                               var st = prop.property_type.data_type as Struct;
-
                                ccode.open_block ();
-                               ccode.add_declaration (get_ccode_name (st), new CCodeVariableDeclarator ("boxed"));
+                               ccode.add_declaration (get_ccode_name (prop.property_type), new CCodeVariableDeclarator ("boxed"));
 
                                ccall = new CCodeFunctionCall (cfunc);
                                ccall.add_argument (cself);
-                               var boxed_addr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed"));
-                               ccall.add_argument (boxed_addr);
-                               ccode.add_expression (ccall);
+                               if (prop.property_type.nullable) {
+                                       ccode.add_assignment (new CCodeIdentifier ("boxed"), ccall);
+                               } else {
+                                       ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed")));
+                                       ccode.add_expression (ccall);
+                               }
 
                                var csetcall = new CCodeFunctionCall ();
                                csetcall.call = get_value_setter_function (prop.property_type);
                                csetcall.add_argument (new CCodeIdentifier ("value"));
-                               csetcall.add_argument (boxed_addr);
+                               if (prop.property_type.nullable) {
+                                       csetcall.add_argument (new CCodeIdentifier ("boxed"));
+                               } else {
+                                       csetcall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed")));
+                               }
                                add_guarded_expression (prop, csetcall);
 
                                if (requires_destroy (prop.get_accessor.value_type)) {
index cfdfafa1e5c9a337a9a6957bb4227028e258f8ba..4527506aa484b33e6b9c8f592d4f851a4af627ad 100644 (file)
@@ -316,6 +316,7 @@ TESTS = \
        objects/property-read-only-write.test \
        objects/property-construct-only-write.test \
        objects/property-construct-only-write-foreign.test \
+       objects/property-gboxed-nullable.vala \
        objects/property-static.vala \
        objects/regex.vala \
        objects/signals.vala \
diff --git a/tests/objects/property-gboxed-nullable.vala b/tests/objects/property-gboxed-nullable.vala
new file mode 100644 (file)
index 0000000..bbf023f
--- /dev/null
@@ -0,0 +1,48 @@
+public struct Bar {
+       public string s;
+}
+
+public class Foo : Object {
+       public Bar? bar { get; construct set; }
+
+       public Foo (Bar? bar) {
+               Object (bar: bar);
+       }
+}
+
+public class Faz : Object {
+       [NoAccessorMethod]
+       public Bar? baz { owned get; set; }
+}
+
+void main () {
+       {
+               var foo = new Foo (null);
+               assert (foo.bar == null);
+       }
+       {
+               Bar bar = { "foo" };
+               var foo = (Foo) Object.@new (typeof (Foo), "bar", bar);
+               assert (foo.bar == bar);
+               assert (foo.bar.s == "foo");
+               foo.bar = null;
+               assert (foo.bar == null);
+       }
+       {
+               Bar bar = { "foo" };
+               var foo = (Foo) Object.@new (typeof (Foo), "bar", null);
+               assert (foo.bar == null);
+               foo.bar = bar;
+               assert (foo.bar == bar);
+       }
+       {
+               Bar bar = { "foo" };
+               var faz = new Faz ();
+               assert (faz.baz == null);
+               faz.baz = bar;
+               assert (faz.baz == bar);
+               assert (faz.baz.s == "foo");
+               faz.baz = null;
+               assert (faz.baz == null);
+       }
+}
index af7e63eb68d73597dc9920c6cbba7a2c5f3f507c..fa90deb7aa12f394332ce9b2b287deaf27e63d45 100644 (file)
@@ -450,8 +450,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
        public bool is_gobject_property_type (DataType property_type) {
                var st = property_type.data_type as Struct;
-               if (st != null && (!st.get_attribute_bool ("CCode", "has_type_id", true) || property_type.nullable)) {
-                       return false;
+               if (st != null) {
+                       if (st.get_attribute_bool ("CCode", "has_type_id", true)) {
+                               // Allow GType-based struct types
+                       } else if (property_type.nullable) {
+                               return false;
+                       }
                }
 
                if (property_type is ArrayType && ((ArrayType) property_type).element_type.data_type != string_type.data_type) {