From: Andrea Del Signore Date: Fri, 3 Apr 2020 17:10:40 +0000 (+0200) Subject: codegen: Fix binary 'in' operator on array with boxed value-typed needle X-Git-Tag: 0.49.1~181 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fmerge-requests%2F120%2Fhead;p=thirdparty%2Fvala.git codegen: Fix binary 'in' operator on array with boxed value-typed needle See https://gitlab.gnome.org/GNOME/vala/issues/951 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index a921cd755..559119341 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -5482,14 +5482,23 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { break; case BinaryOperator.IN: if (expr.right.value_type is ArrayType) { - var array_type = (ArrayType) expr.right.value_type; - var node = new CCodeFunctionCall (new CCodeIdentifier (generate_array_contains_wrapper (array_type))); - node.add_argument (cright); - node.add_argument (get_array_length_cexpression (expr.right)); - if (array_type.element_type is StructValueType) { - node.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft)); + unowned ArrayType array_type = (ArrayType) expr.right.value_type; + unowned DataType element_type = array_type.element_type; + var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_contains_wrapper (array_type))); + CCodeExpression node = ccall; + + ccall.add_argument (cright); + ccall.add_argument (get_array_length_cexpression (expr.right)); + if (element_type is StructValueType) { + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft)); + } else if (element_type is ValueType && !element_type.nullable + && expr.left.value_type is ValueType && expr.left.value_type.nullable) { + // null check + var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cleft, new CCodeConstant ("NULL")); + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cleft)); + node = new CCodeParenthesizedExpression (new CCodeConditionalExpression (cnull, new CCodeConstant ("FALSE"), ccall)); } else { - node.add_argument (cleft); + ccall.add_argument (cleft); } set_cvalue (expr, node); } else { diff --git a/tests/Makefile.am b/tests/Makefile.am index 083b320fb..52b7bde0e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -88,6 +88,7 @@ TESTS = \ arrays/inline-local-variable.test \ arrays/inline-parameter.test \ arrays/inline-struct-field.test \ + arrays/in-operator-with-boxed-needle.vala \ arrays/length-inline-assignment.vala \ arrays/length-type-include.vala \ arrays/struct-field-length-cname.vala \ diff --git a/tests/arrays/in-operator-with-boxed-needle.vala b/tests/arrays/in-operator-with-boxed-needle.vala new file mode 100644 index 000000000..e3b129a19 --- /dev/null +++ b/tests/arrays/in-operator-with-boxed-needle.vala @@ -0,0 +1,12 @@ +void main () { + int[] foo = { 0, 23, 42 }; + + int? i = null; + assert (!(i in foo)); + + i = 23; + assert (i in foo); + + i = 4711; + assert (!(i in foo)); +}