From 97a9f3bc32e0abb73e1aa8fe3cbbc7708a5faa61 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Fri, 1 Feb 2008 13:56:01 +0000 Subject: [PATCH] add more non-null warnings 2008-02-01 Juerg Billeter * vala/parser.y, vala/valaarraytype.vala, vala/valadatatype.vala, vala/valaintegertype.vala, vala/valanulltype.vala, vala/valapointertype.vala, vala/valasemanticanalyzer.vala, vala/valasymbolresolver.vala, vala/valaunresolvedtype.vala, ccode/valaccodeassignment.vala, ccode/valaccodebinaryexpression.vala, gobject/valaccodegenerator.vala: add more non-null warnings svn path=/trunk/; revision=940 --- ChangeLog | 9 +++++ ccode/valaccodeassignment.vala | 12 +++--- ccode/valaccodebinaryexpression.vala | 13 +++--- gobject/valaccodegenerator.vala | 9 ++--- vala/parser.y | 78 ++++++++++++++++++------------------ vala/valaarraytype.vala | 1 + vala/valadatatype.vala | 24 ++++++++--- vala/valaintegertype.vala | 4 +- vala/valanulltype.vala | 10 +++-- vala/valapointertype.vala | 2 +- vala/valasemanticanalyzer.vala | 71 ++++++++++++++++++++++---------- vala/valasymbolresolver.vala | 7 ++++ vala/valaunresolvedtype.vala | 27 +------------ 13 files changed, 148 insertions(+), 119 deletions(-) diff --git a/ChangeLog b/ChangeLog index 72bea04..32a35d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-02-01 Jürg Billeter + + * vala/parser.y, vala/valaarraytype.vala, vala/valadatatype.vala, + vala/valaintegertype.vala, vala/valanulltype.vala, + vala/valapointertype.vala, vala/valasemanticanalyzer.vala, + vala/valasymbolresolver.vala, vala/valaunresolvedtype.vala, + ccode/valaccodeassignment.vala, ccode/valaccodebinaryexpression.vala, + gobject/valaccodegenerator.vala: add more non-null warnings + 2008-01-31 Jürg Billeter * vapi/atk.vapi, vapi/gdk-pixbuf-2.0.vapi, vapi/gstreamer-0.10.vapi, diff --git a/ccode/valaccodeassignment.vala b/ccode/valaccodeassignment.vala index 96331e3..8f15cdf 100644 --- a/ccode/valaccodeassignment.vala +++ b/ccode/valaccodeassignment.vala @@ -1,6 +1,6 @@ /* valaccodeassignment.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2008 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,9 +48,8 @@ public class Vala.CCodeAssignment : CCodeExpression { } public override void write (CCodeWriter! writer) { - if (left != null) { - left.write (writer); - } + left.write (writer); + writer.write_string (" "); if (operator == CCodeAssignmentOperator.BITWISE_OR) { @@ -76,9 +75,8 @@ public class Vala.CCodeAssignment : CCodeExpression { } writer.write_string ("= "); - if (right != null) { - right.write (writer); - } + + right.write (writer); } } diff --git a/ccode/valaccodebinaryexpression.vala b/ccode/valaccodebinaryexpression.vala index e040ef5..27a8ce6 100644 --- a/ccode/valaccodebinaryexpression.vala +++ b/ccode/valaccodebinaryexpression.vala @@ -1,6 +1,6 @@ /* valaccodebinaryexpression.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2008 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,9 +48,8 @@ public class Vala.CCodeBinaryExpression : CCodeExpression { } public override void write (CCodeWriter! writer) { - if (left != null) { - left.write (writer); - } + left.write (writer); + writer.write_string (" "); if (operator == CCodeBinaryOperator.PLUS) { writer.write_string ("+"); @@ -89,10 +88,10 @@ public class Vala.CCodeBinaryExpression : CCodeExpression { } else if (operator == CCodeBinaryOperator.OR) { writer.write_string ("||"); } + writer.write_string (" "); - if (right != null) { - right.write (writer); - } + + right.write (writer); } } diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index 66693b4..60cf171 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -1057,10 +1057,6 @@ public class Vala.CCodeGenerator : CodeGenerator { * if foo is of static type non-null */ - if (type.is_null) { - return new CCodeConstant ("NULL"); - } - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL")); if (type.data_type == null) { if (!(current_type_symbol is Class) || !current_class.is_subtype_of (gobject_type)) { @@ -1131,7 +1127,7 @@ public class Vala.CCodeGenerator : CodeGenerator { var cassign = new CCodeAssignment (cvar, ccomma); // g_free (NULL) is allowed - if ((context.non_null && !type.nullable) || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) { + if ((context.non_null && !type.requires_null_check) || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) { return new CCodeParenthesizedExpression (cassign); } @@ -2415,7 +2411,8 @@ public class Vala.CCodeGenerator : CodeGenerator { var ccall = new CCodeFunctionCall (dupexpr); - if (((context.non_null && !expr.static_type.nullable) && expr.static_type.type_parameter == null) || expr is LiteralExpression) { + if (((context.non_null && !expr.static_type.requires_null_check) && expr.static_type.type_parameter == null) || expr is LiteralExpression) { + // expression is non-null ccall.add_argument ((CCodeExpression) expr.ccodenode); return ccall; diff --git a/vala/parser.y b/vala/parser.y index 8676dd3..0384f0f 100644 --- a/vala/parser.y +++ b/vala/parser.y @@ -526,7 +526,8 @@ type $$ = $1; vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2); if ($4) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_nullable ($$, TRUE); + vala_data_type_set_requires_null_check ($$, TRUE); } } | WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr @@ -535,44 +536,49 @@ type vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); if ($5) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_nullable ($$, TRUE); + vala_data_type_set_requires_null_check ($$, TRUE); } } | type_name opt_rank_specifier opt_op_neg opt_any_interr HASH { $$ = $1; - vala_unresolved_type_set_transfers_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_transfers_ownership ($$, TRUE); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2); if ($4) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_nullable ($$, TRUE); + vala_data_type_set_requires_null_check ($$, TRUE); } } | REF type_name opt_rank_specifier opt_op_neg opt_any_interr { $$ = $2; - vala_unresolved_type_set_is_ref (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_is_ref ($$, TRUE); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); if ($5) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_nullable ($$, TRUE); + vala_data_type_set_requires_null_check ($$, TRUE); } } | OUT type_name opt_rank_specifier opt_op_neg opt_any_interr { $$ = $2; - vala_unresolved_type_set_is_out (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_is_out ($$, TRUE); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); if ($5) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_nullable ($$, TRUE); + vala_data_type_set_requires_null_check ($$, TRUE); } } | OUT WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr { $$ = $3; vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE); - vala_unresolved_type_set_is_out (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_is_out ($$, TRUE); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $4); if ($6) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_nullable ($$, TRUE); + vala_data_type_set_requires_null_check ($$, TRUE); } } | type_name stars opt_rank_specifier @@ -1901,11 +1907,9 @@ local_variable_type $$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($1)); g_object_unref ($1); g_object_unref (src); - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_takes_ownership ($$, TRUE); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2); - if ($4) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); - } + vala_data_type_set_nullable ($$, TRUE); } | primary_expression stars { @@ -1922,9 +1926,7 @@ local_variable_type g_object_unref ($2); g_object_unref (src); vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3); - if ($5) { - vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE); - } + vala_data_type_set_nullable ($$, TRUE); } | VOID { @@ -2275,7 +2277,7 @@ foreach_statement { ValaSourceReference *src = src(@3); if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), TRUE); + vala_data_type_set_takes_ownership ($3, TRUE); } $$ = VALA_STATEMENT (vala_code_context_create_foreach_statement (context, $3, $4, $6, $8, src)); g_object_unref ($3); @@ -2896,11 +2898,11 @@ field_declaration src = src_com(@5, $1); if (VALA_IS_UNRESOLVED_TYPE ($5)) { - if (vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($5)) || vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($5))) { + if (vala_data_type_get_is_ref ($5) || vala_data_type_get_is_out ($5)) { vala_report_error (src, "`ref' and `out' may only be used for parameters."); } if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE); + vala_data_type_set_takes_ownership ($5, TRUE); } } @@ -3048,11 +3050,11 @@ method_header src = src_com(@6, $1); if (VALA_IS_UNRESOLVED_TYPE ($5)) { - if (vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($5)) || vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($5))) { + if (vala_data_type_get_is_ref ($5) || vala_data_type_get_is_out ($5)) { vala_report_error (src, "`ref' and `out' may only be used for parameters."); } if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_unresolved_type_set_transfers_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE); + vala_data_type_set_transfers_ownership ($5, TRUE); } } @@ -3216,15 +3218,14 @@ fixed_parameter src = src(@3); if (VALA_IS_UNRESOLVED_TYPE ($3)) { if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), TRUE); + vala_data_type_set_takes_ownership ($3, TRUE); } - if (!vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($3)) - && !vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($3)) - && !vala_unresolved_type_get_transfers_ownership (VALA_UNRESOLVED_TYPE ($3))) { - /* FIXME take_ownership for in parameters that don't transfer ownership is not supported yet - * this may require an additional local variable per parameter */ - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), FALSE); + if (!vala_data_type_get_is_ref ($3) + && !vala_data_type_get_is_out ($3) + && !vala_data_type_get_transfers_ownership ($3)) { + /* take_ownership for in parameters that don't transfer ownership is not supported */ + vala_data_type_set_takes_ownership ($3, FALSE); } } @@ -3241,15 +3242,14 @@ fixed_parameter src = src(@3); if (VALA_IS_UNRESOLVED_TYPE ($3)) { if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), TRUE); + vala_data_type_set_takes_ownership ($3, TRUE); } - if (!vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($3)) - && !vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($3)) - && !vala_unresolved_type_get_transfers_ownership (VALA_UNRESOLVED_TYPE ($3))) { - /* FIXME take_ownership for in parameters that don't transfer ownership is not supported yet - * this may require an additional local variable per parameter */ - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), FALSE); + if (!vala_data_type_get_is_ref ($3) + && !vala_data_type_get_is_out ($3) + && !vala_data_type_get_transfers_ownership ($3)) { + /* take_ownership for in parameters that don't transfer ownership is not supported */ + vala_data_type_set_takes_ownership ($3, FALSE); } } @@ -3336,7 +3336,7 @@ property_declaration ValaSourceReference *src; if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE); + vala_data_type_set_takes_ownership ($5, TRUE); } src = src_com(@5, $1); @@ -3369,7 +3369,7 @@ property_declaration ValaSourceReference *src; if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE); + vala_data_type_set_takes_ownership ($5, TRUE); } src = src_com(@5, $1); @@ -4119,7 +4119,7 @@ type_argument $$ = $1; if (VALA_IS_UNRESOLVED_TYPE ($$)) { if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($$))) { - vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE); + vala_data_type_set_takes_ownership ($$, TRUE); } } } diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala index edc8da3..a54974a 100644 --- a/vala/valaarraytype.vala +++ b/vala/valaarraytype.vala @@ -54,6 +54,7 @@ public class Vala.ArrayType : ReferenceType { result.takes_ownership = takes_ownership; result.is_out = is_out; result.nullable = nullable; + result.requires_null_check = requires_null_check; result.floating_reference = floating_reference; result.is_ref = is_ref; diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 5e07162..b8383d6 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -51,10 +51,11 @@ public class Vala.DataType : CodeNode { public bool nullable { get; set; } /** - * Specifies that the expression is known to be null. + * Specifies that the expression may not be dereferenced without + * prior null check. */ - public bool is_null { get; set; } - + public bool requires_null_check { get; set; } + /** * The referred data type. */ @@ -228,6 +229,7 @@ public class Vala.DataType : CodeNode { result.takes_ownership = takes_ownership; result.is_out = is_out; result.nullable = nullable; + result.requires_null_check = requires_null_check; result.data_type = data_type; result.type_parameter = type_parameter; result.floating_reference = floating_reference; @@ -331,7 +333,7 @@ public class Vala.DataType : CodeNode { } } - public virtual bool compatible (DataType! target_type) { + public virtual bool compatible (DataType! target_type, bool enable_non_null = true) { if (target_type is DelegateType && this is DelegateType) { return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol; } @@ -369,6 +371,10 @@ public class Vala.DataType : CodeNode { } if (data_type == target_type.data_type) { + if (requires_null_check && !target_type.nullable && data_type != null && data_type.is_reference_type ()) { + // incompatibility between null and non-null types + return !enable_non_null; + } return true; } @@ -389,7 +395,15 @@ public class Vala.DataType : CodeNode { } } - return (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type)); + if (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type)) { + if (requires_null_check && !target_type.nullable && data_type.is_reference_type ()) { + // incompatibility between null and non-null types + return !enable_non_null; + } + return true; + } + + return false; } /** diff --git a/vala/valaintegertype.vala b/vala/valaintegertype.vala index c990768..97c2bca 100644 --- a/vala/valaintegertype.vala +++ b/vala/valaintegertype.vala @@ -38,7 +38,7 @@ public class Vala.IntegerType : ValueType { return type; } - public override bool compatible (DataType! target_type) { + public override bool compatible (DataType! target_type, bool enable_non_null = true) { if (target_type.data_type is Struct && literal.get_type_name () == "int") { // int literals are implicitly convertible to integer types // of a lower rank if the value of the literal is within @@ -53,6 +53,6 @@ public class Vala.IntegerType : ValueType { } } - return base.compatible (target_type); + return base.compatible (target_type, enable_non_null); } } diff --git a/vala/valanulltype.vala b/vala/valanulltype.vala index d77be59..a2d2977 100644 --- a/vala/valanulltype.vala +++ b/vala/valanulltype.vala @@ -26,10 +26,11 @@ using GLib; * The type of the null literal. */ public class Vala.NullType : ReferenceType { - public NullType () { + public NullType (SourceReference source_reference) { + this.source_reference = source_reference; } - public override bool compatible (DataType! target_type) { + public override bool compatible (DataType! target_type, bool enable_non_null = true) { if (!(target_type is PointerType) && (target_type is NullType || (target_type.data_type == null && target_type.type_parameter == null))) { return true; } @@ -46,7 +47,8 @@ public class Vala.NullType : ReferenceType { if (target_type.data_type.is_reference_type () || target_type is ArrayType || target_type.data_type is Delegate) { - return !(CodeContext.is_non_null_enabled ()); + // incompatibility between null and non-null types + return !enable_non_null; } /* null is not compatible with any other type (i.e. value types) */ @@ -54,6 +56,6 @@ public class Vala.NullType : ReferenceType { } public override DataType! copy () { - return new NullType (); + return new NullType (source_reference); } } diff --git a/vala/valapointertype.vala b/vala/valapointertype.vala index c54bd71..9a9ede8 100644 --- a/vala/valapointertype.vala +++ b/vala/valapointertype.vala @@ -50,7 +50,7 @@ public class Vala.PointerType : DataType { return new PointerType (base_type); } - public override bool compatible (DataType! target_type) { + public override bool compatible (DataType! target_type, bool enable_non_null = true) { if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) { return true; } diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 11ecc82..8bfab9d 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -812,9 +812,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { continue; } if (!e.static_type.compatible (array_type.element_type)) { - error = true; - e.error = true; - Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (array_type.element_type.data_type.name, e.static_type.data_type.name)); + if (!e.static_type.compatible (array_type.element_type, false)) { + error = true; + e.error = true; + Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (array_type.element_type.data_type.name, e.static_type.to_string ())); + } else if (context.is_non_null_enabled ()) { + Report.warning (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (array_type.element_type.data_type.name, e.static_type.to_string ())); + } } } @@ -1032,8 +1036,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (stmt.return_expression != null && !stmt.return_expression.static_type.compatible (current_return_type)) { - Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.static_type.to_string (), current_return_type.to_string ())); - return; + if (!stmt.return_expression.static_type.compatible (current_return_type, false)) { + Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.static_type.to_string (), current_return_type.to_string ())); + return; + } else if (context.is_non_null_enabled ()) { + Report.warning (stmt.source_reference, "Return value may not be null"); + } } if (stmt.return_expression != null && @@ -1232,7 +1240,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_null_literal (NullLiteral! expr) { - expr.static_type = new NullType (); + expr.static_type = new NullType (expr.source_reference); } public override void visit_literal_expression (LiteralExpression! expr) { @@ -1630,9 +1638,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return false; } } else if (!arg.static_type.compatible (param.type_reference)) { - expr.error = true; - Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ())); - return false; + if (!arg.static_type.compatible (param.type_reference, false)) { + expr.error = true; + Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ())); + return false; + } else if (context.is_non_null_enabled ()) { + Report.warning (expr.source_reference, "Argument %d: Argument may not be null".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ())); + } } else { // 0 => null, 1 => in, 2 => ref, 3 => out int arg_type = 1; @@ -2426,9 +2438,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (!expr.right.static_type.compatible (expr.left.static_type) && !expr.left.static_type.compatible (expr.right.static_type)) { - Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible, comparison would always evaluate to false".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ())); - expr.error = true; - return; + if (!expr.right.static_type.compatible (expr.left.static_type, false) + && !expr.left.static_type.compatible (expr.right.static_type, false)) { + Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ())); + expr.error = true; + return; + } else if (context.is_non_null_enabled ()) { + // warn about incompatibility between null and non-null types + Report.warning (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ())); + } } if (expr.left.static_type.compatible (string_type) @@ -2761,12 +2779,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } } else if (a.left.static_type != null && a.right.static_type != null) { + /* if there was an error on either side, + * i.e. a.{left|right}.static_type == null, skip type check */ + if (!a.right.static_type.compatible (a.left.static_type)) { - /* if there was an error on either side, - * i.e. a.{left|right}.static_type == null, skip type check */ - a.error = true; - Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); - return; + if (!a.right.static_type.compatible (a.left.static_type, false)) { + a.error = true; + Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); + return; + } else if (context.is_non_null_enabled ()) { + // warn about incompatibility between null and non-null types + Report.warning (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); + } } if (a.right.static_type.transfers_ownership) { @@ -2787,11 +2811,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor { var ea = (ElementAccess) a.left; if (!a.right.static_type.compatible (a.left.static_type)) { - /* if there was an error on either side, - * i.e. a.{left|right}.static_type == null, skip type check */ - a.error = true; - Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); - return; + if (!a.right.static_type.compatible (a.left.static_type, false)) { + a.error = true; + Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); + return; + } else if (context.is_non_null_enabled ()) { + // warn about incompatibility between null and non-null types + Report.warning (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); + } } if (a.right.static_type.transfers_ownership) { diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala index f454a1d..5825b63 100644 --- a/vala/valasymbolresolver.vala +++ b/vala/valasymbolresolver.vala @@ -188,6 +188,7 @@ public class Vala.SymbolResolver : CodeVisitor { type.is_ref = unresolved_type.is_ref; type.is_out = unresolved_type.is_out; type.nullable = unresolved_type.nullable; + type.requires_null_check = unresolved_type.requires_null_check; foreach (DataType type_arg in unresolved_type.get_type_arguments ()) { type.add_type_argument (type_arg); } @@ -295,6 +296,7 @@ public class Vala.SymbolResolver : CodeVisitor { type.is_ref = unresolved_type.is_ref; type.is_out = unresolved_type.is_out; type.nullable = unresolved_type.nullable; + type.requires_null_check = unresolved_type.nullable; } if (type.data_type != null && !type.data_type.is_reference_type ()) { @@ -304,6 +306,11 @@ public class Vala.SymbolResolver : CodeVisitor { */ type.takes_ownership = false; type.transfers_ownership = false; + + /* reset nullable of value-types for local variables */ + if (type.nullable && !type.requires_null_check) { + type.nullable = false; + } } return type; diff --git a/vala/valaunresolvedtype.vala b/vala/valaunresolvedtype.vala index 0605b1e..33ddb6a 100644 --- a/vala/valaunresolvedtype.vala +++ b/vala/valaunresolvedtype.vala @@ -49,38 +49,12 @@ public class Vala.UnresolvedType : DataType { * indicates no pointer-type. */ public int pointer_level { get; set; } - - /** - * Specifies that the expression transfers ownership of its value. - */ - public bool transfers_ownership { get; set; } - - /** - * Specifies that the expression assumes ownership if used as an lvalue - * in an assignment. - */ - public bool takes_ownership { get; set; } /** * The weak modifier has been specified. */ public bool is_weak { get; set; } - /** - * Specifies that the expression is a reference used in ref parameters. - */ - public bool is_ref { get; set; } - - /** - * Specifies that the expression is a reference used in out parameters. - */ - public bool is_out { get; set; } - - /** - * Specifies that the expression may be null. - */ - public bool nullable { get; set; } - public UnresolvedType () { } @@ -142,6 +116,7 @@ public class Vala.UnresolvedType : DataType { result.takes_ownership = takes_ownership; result.is_out = is_out; result.nullable = nullable; + result.requires_null_check = requires_null_check; result.namespace_name = namespace_name; result.type_name = type_name; result.array_rank = array_rank; -- 2.7.4