diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-01-12 22:01:52 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-02-12 19:45:01 +0100 |
commit | 5f316333d6a803e4240b5cccc95a6abd2294137b (patch) | |
tree | 0e3fbf1e4d7eabf93b2285042ae8568d3d040ca4 | |
parent | 20a1536f9911c1aadbfbe046bc01afc57bb724a5 (diff) | |
download | vala-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.vala | 29 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/structs/bug777194.vala | 58 |
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); +} |