]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
add more non-null warnings
authorJuerg Billeter <j@bitron.ch>
Fri, 1 Feb 2008 13:56:01 +0000 (13:56 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 1 Feb 2008 13:56:01 +0000 (13:56 +0000)
2008-02-01  Juerg Billeter  <j@bitron.ch>

* 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

13 files changed:
ChangeLog
ccode/valaccodeassignment.vala
ccode/valaccodebinaryexpression.vala
gobject/valaccodegenerator.vala
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

index 72bea048cca82c9531f4e2d7f9ca2792736b44a9..32a35d078b378909ee7f8ee3f08600660b66c0db 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-02-01  Jürg Billeter  <j@bitron.ch>
+
+       * 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  <j@bitron.ch>
 
        * vapi/atk.vapi, vapi/gdk-pixbuf-2.0.vapi, vapi/gstreamer-0.10.vapi,
index 96331e3891dc64640b4f97ee62074764192b3872..8f15cdfa377d01f3b19f1465e5e112795effa9aa 100644 (file)
@@ -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);
        }
 }
        
index e040ef5960a60610e5f665c53616d0a6929ddf2b..27a8ce6dc102fbac7e4e14552c14e87743a7ff6f 100644 (file)
@@ -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);
        }
 }
 
index 66693b4c5c3659fc2b67c86096f040874fdb70e7..60cf171ca73d89fb46c89d881e0145708a0e0a96 100644 (file)
@@ -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;
index 8676dd36e272fbcd52425957a45f27a29c144d32..0384f0f7390b169c7c4799c4ddc5de185c91d36a 100644 (file)
@@ -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);
                        }
                }
          }
index edc8da3af694dbb912629c933b5a35fafb5cf4ee..a54974a6d68e5257eaee7edbeaad6f0fb4036cb2 100644 (file)
@@ -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;
                
index 5e071626a5f644e453e097da810d3865d5006555..b8383d633d273a332be9fc560cd12ded307b7b88 100644 (file)
@@ -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;
        }
 
        /**
index c99076832049bfdef6ddf2b6135e044b5df9a403..97c2bcab602423663331b23d57bc291fb2e1577d 100644 (file)
@@ -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);
        }
 }
index d77be59fc4dbdcf035fe513856344920fbbb9c66..a2d2977c335a70f0db18a465d47da2040152810b 100644 (file)
@@ -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);
        }
 }
index c54bd71d672ff9b24b1161e6ea0db1d8111278ba..9a9ede86e36db8d39c2831952f1d23f72ac9ad63 100644 (file)
@@ -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;
                }
index 11ecc822f27f2adc2205bb21d5ac6ebd497e514e..8bfab9dd760127b8209002229d897f40e37850a2 100644 (file)
@@ -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) {
index f454a1d32ed910390236401fe7bced1d0e61c15c..5825b633a139f2c0b927a98d8173809661ef5933 100644 (file)
@@ -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;
index 0605b1ec48a83b1288c22605f043844171b34377..33ddb6a2336bca72e8b81699ea3f6a1630e4a5d4 100644 (file)
@@ -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;