simplify conditional expression type analysis, fixes crash
authorJuerg Billeter <j@bitron.ch>
Fri, 18 Jan 2008 16:51:06 +0000 (16:51 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 18 Jan 2008 16:51:06 +0000 (16:51 +0000)
2008-01-18  Juerg Billeter  <j@bitron.ch>

* vala/valanulltype.vala, vala/valasemanticanalyzer.vala: simplify
  conditional expression type analysis, fixes crash

svn path=/trunk/; revision=851

ChangeLog
vala/valanulltype.vala
vala/valasemanticanalyzer.vala

index cef312d..bf7b3b1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2008-01-18  Jürg Billeter  <j@bitron.ch>
 
+       * vala/valanulltype.vala, vala/valasemanticanalyzer.vala: simplify
+         conditional expression type analysis, fixes crash
+
+2008-01-18  Jürg Billeter  <j@bitron.ch>
+
        * gobject/valaccodegeneratormethod.vala: fix methods with ref array
          parameters, based on patch by Hans Vercammen, fixes bug 510418
 
index 4dcf18c..5221c5b 100644 (file)
@@ -52,4 +52,8 @@ public class Vala.NullType : ReferenceType {
                /* null is not compatible with any other type (i.e. value types) */
                return false;
        }
+
+       public override DataType! copy () {
+               return new NullType ();
+       }
 }
index 9bcf65b..988dd86 100644 (file)
@@ -2359,114 +2359,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                expr.static_type = bool_type;
        }
 
-       private DataType compute_common_base_type (Collection<DataType> types, SourceReference source_reference) {
-               bool null_found = false;
-               bool class_or_iface_found = false;
-               bool type_param_found = false;
-               bool ref_struct_found = false;
-               bool val_struct_found = false;
-               bool enum_found = false;
-               bool callback_found = false;
-               DataType base_type = null;
-               DataType last_type = null;
-               foreach (DataType type in types) {
-                       last_type = type;
-                       if (type.error) {
-                               return new InvalidType ();
-                       }
-                       if (type.data_type == null && type.type_parameter == null) {
-                               if (!null_found) {
-                                       null_found = true;
-                                       if (val_struct_found || enum_found) {
-                                               base_type.error = true;
-                                               break;
-                                       }
-                               }
-                       } else if (type.data_type is Class || type.data_type is Interface) {
-                               if (!class_or_iface_found) {
-                                       class_or_iface_found = true;
-                                       if (type_param_found || ref_struct_found || val_struct_found || enum_found || callback_found) {
-                                               base_type.error = true;
-                                               break;
-                                       }
-                               }
-                       } else if (type.type_parameter != null) {
-                               if (!type_param_found) {
-                                       type_param_found = true;
-                                       if (class_or_iface_found || ref_struct_found || val_struct_found || enum_found || callback_found) {
-                                               base_type.error = true;
-                                               break;
-                                       }
-                               }
-                       } else if (type.data_type is Struct) {
-                               var st = (Struct) type.data_type;
-                               if (st.is_reference_type ()) {
-                                       if (!ref_struct_found) {
-                                               ref_struct_found = true;
-                                               if (class_or_iface_found || type_param_found || val_struct_found || enum_found || callback_found) {
-                                                       base_type.error = true;
-                                                       break;
-                                               }
-                                       }
-                               } else {
-                                       if (!val_struct_found) {
-                                               val_struct_found = true;
-                                               if (class_or_iface_found || type_param_found || ref_struct_found || enum_found || callback_found) {
-                                                       base_type.error = true;
-                                                       break;
-                                               }
-                                       }
-                               }
-                       } else if (type.data_type is Enum) {
-                               if (!enum_found) {
-                                       enum_found = true;
-                                       if (class_or_iface_found || type_param_found || ref_struct_found || val_struct_found) {
-                                               base_type.error = true;
-                                               break;
-                                       }
-                               }
-                       } else if (type.data_type is Delegate) {
-                               if (!callback_found) {
-                                       callback_found = true;
-                                       if (class_or_iface_found || type_param_found || ref_struct_found || val_struct_found || enum_found) {
-                                               base_type.error = true;
-                                               break;
-                                       }
-                               }
-                       } else {
-                               Report.error (type.source_reference, "internal error: unsupported type `%s'".printf (type.to_string ()));
-                               return new InvalidType ();
-                       }
-                       if (base_type == null) {
-                               base_type = new DataType ();
-                               base_type.data_type = type.data_type;
-                               base_type.type_parameter = type.type_parameter;
-                               base_type.nullable = type.nullable;
-                               base_type.is_null = type.is_null;
-                               base_type.transfers_ownership = type.transfers_ownership;
-                       } else {
-                               if (base_type.data_type != type.data_type) {
-                                       if (type.compatible (base_type)) {
-                                       } else if (base_type.compatible (type)) {
-                                               base_type.data_type = type.data_type;
-                                       } else {
-                                               base_type.error = true;
-                                               break;
-                                       }
-                               }
-                               base_type.nullable = base_type.nullable || type.nullable;
-                               base_type.is_null = base_type.is_null && type.is_null;
-                               // if one subexpression transfers ownership, all subexpressions must transfer ownership
-                               // FIXME add ref calls to subexpressions that don't transfer ownership
-                               base_type.transfers_ownership = base_type.transfers_ownership || type.transfers_ownership;
-                       }
-               }
-               if (base_type != null && base_type.error) {
-                       Report.error (source_reference, "`%s' is incompatible with `%s'".printf (last_type.to_string (), base_type.to_string ()));
-               }
-               return base_type;
-       }
-
        public override void visit_conditional_expression (ConditionalExpression! expr) {
                if (!expr.condition.static_type.compatible (bool_type)) {
                        expr.error = true;
@@ -2475,10 +2367,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
 
                /* FIXME: support memory management */
-               Gee.List<DataType> types = new ArrayList<DataType> ();
-               types.add (expr.true_expression.static_type);
-               types.add (expr.false_expression.static_type);
-               expr.static_type = compute_common_base_type (types, expr.source_reference);
+               if (expr.false_expression.static_type.compatible (expr.true_expression.static_type)) {
+                       expr.static_type = expr.true_expression.static_type.copy ();
+               } else if (expr.true_expression.static_type.compatible (expr.false_expression.static_type)) {
+                       expr.static_type = expr.false_expression.static_type.copy ();
+               } else {
+                       expr.error = true;
+                       Report.error (expr.condition.source_reference, "Incompatible expressions");
+                       return;
+               }
        }
 
        private string get_lambda_name () {