summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2017-01-12 22:01:52 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2017-02-12 19:45:01 +0100
commit5f316333d6a803e4240b5cccc95a6abd2294137b (patch)
tree0e3fbf1e4d7eabf93b2285042ae8568d3d040ca4
parent20a1536f9911c1aadbfbe046bc01afc57bb724a5 (diff)
downloadvala-5f316333d6a803e4240b5cccc95a6abd2294137b.tar.gz
codegen: Support casting arbitary value-types to arrays
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
-rw-r--r--codegen/valaccodebasemodule.vala29
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/structs/bug777194.vala58
3 files changed, 85 insertions, 3 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index e8bb29f51..b1eaf3e09 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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)));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 76fb108b7..f824f4e4e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 000000000..def402e35
--- /dev/null
+++ b/tests/structs/bug777194.vala
@@ -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);
+}