]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Support casting arbitary value-types to arrays 5f316333d6a803e4240b5cccc95a6abd2294137b
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 12 Jan 2017 21:01:52 +0000 (22:01 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sun, 12 Feb 2017 18:45:01 +0000 (19:45 +0100)
Also calculate a valid length for the resulting array.

This enables easier usage of common uint8[]-based buffer API.

https://bugzilla.gnome.org/show_bug.cgi?id=777194

codegen/valaccodebasemodule.vala
tests/Makefile.am
tests/structs/bug777194.vala [new file with mode: 0644]

index e8bb29f51273103972180283da6d2c6b49e52aa1..b1eaf3e095716ded8cd340687086f6f03c028539 100644 (file)
@@ -5171,10 +5171,29 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                        }
                                }
                        } else if (array_type != null) {
-                               // cast from non-array to array, set invalid length
-                               // required by string.data, e.g.
+                               CCodeExpression array_length_expr;
+
+                               var sizeof_to = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+                               sizeof_to.add_argument (new CCodeConstant (get_ccode_name (array_type.element_type)));
+                               var sizeof_from = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+
+                               var value_type = expr.inner.value_type;
+                               if (value_type is ValueType) {
+                                       var data_type = ((ValueType) value_type).data_type;
+                                       sizeof_from.add_argument (new CCodeConstant (get_ccode_name (data_type)));
+                                       array_length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.DIV, sizeof_from, sizeof_to);
+                               } else if (value_type is PointerType && ((PointerType) value_type).base_type is ValueType) {
+                                       var data_type = ((ValueType) (((PointerType) value_type).base_type)).data_type;
+                                       sizeof_from.add_argument (new CCodeConstant (get_ccode_name (data_type)));
+                                       array_length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.DIV, sizeof_from, sizeof_to);
+                               } else {
+                                       // cast from unsupported non-array to array, set invalid length
+                                       // required by string.data, e.g.
+                                       array_length_expr = new CCodeConstant ("-1");
+                               }
+
                                for (int dim = 1; dim <= array_type.rank; dim++) {
-                                       append_array_length (expr, new CCodeConstant ("-1"));
+                                       append_array_length (expr, array_length_expr);
                                }
                        }
 
@@ -5183,6 +5202,10 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                expr.inner.value_type is ValueType && expr.inner.value_type.nullable) {
                                // nullable integer or float or boolean or struct or enum cast to non-nullable
                                innercexpr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, innercexpr);
+                       } else if (expr.type_reference is ArrayType
+                           && expr.inner.value_type is ValueType && !expr.inner.value_type.nullable) {
+                               // integer or float or boolean or struct or enum to array cast
+                               innercexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, innercexpr);
                        }
                        set_cvalue (expr, new CCodeCastExpression (innercexpr, get_ccode_name (expr.type_reference)));
 
index 76fb108b78445d5ef8632da70fe83c568170a993..f824f4e4e15effe169642fc6ba23300cfb41b94f 100644 (file)
@@ -132,6 +132,7 @@ TESTS = \
        structs/bug690380.vala \
        structs/bug749952.vala \
        structs/bug775761.vala \
+       structs/bug777194.vala \
        delegates/delegates.vala \
        delegates/bug539166.vala \
        delegates/bug595610.vala \
diff --git a/tests/structs/bug777194.vala b/tests/structs/bug777194.vala
new file mode 100644 (file)
index 0000000..def402e
--- /dev/null
@@ -0,0 +1,58 @@
+struct Foo {
+       public int64 foo;
+       public int64 bar;
+}
+
+void bar (uint8[] a) {
+       unowned Foo[] f = (Foo[]) a;
+       assert (f[0].foo == 2LL << 62);
+       assert (f[0].bar == 2LL << 31);
+}
+
+void main () {
+       unowned uint8[] tu;
+       uint8[] to;
+
+       Foo fstack = { 2LL << 62 , 2LL << 31};
+       Foo? fheap = { 2LL << 62 , 2LL << 31};
+
+       bar ((uint8[]) &fstack);
+       tu = (uint8[]) &fstack;
+       assert (tu.length == 16);
+       bar (tu);
+       to = (uint8[]) &fstack;
+       assert (to.length == 16);
+       bar (to);
+
+       bar ((uint8[]) fstack);
+       tu = (uint8[]) fstack;
+       assert (tu.length == 16);
+       bar (tu);
+       to = (uint8[]) fstack;
+       assert (to.length == 16);
+       bar (to);
+
+       bar ((uint8[]) fheap);
+       tu = (uint8[]) fheap;
+       assert (tu.length == 16);
+       bar (tu);
+       to = (uint8[]) fheap;
+       assert (to.length == 16);
+       bar (to);
+
+       int32 i32 = 2 << 28;
+       tu = (uint8[]) i32;
+       assert (tu.length == 4);
+       tu = (uint8[]) &i32;
+       assert (tu.length == 4);
+       to = (uint8[]) i32;
+       assert (to.length == 4);
+
+       uint64 u64 = 2UL << 30;
+       tu = (uint8[]) u64;
+       assert (tu.length == 8);
+       tu = (uint8[]) &u64;
+       assert (tu.length == 8);
+       to = (uint8[]) u64;
+       assert (to.length == 8);
+}