Improve type checking for conditional expressions with pointer types (... ? ptr0...
authorChristoph Mallon <christoph.mallon@gmx.de>
Wed, 6 Aug 2008 11:30:35 +0000 (11:30 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Wed, 6 Aug 2008 11:30:35 +0000 (11:30 +0000)
[r21011]

parser.c
type.c
type.h

index 287af0c..fa04afb 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -6065,12 +6065,33 @@ static expression_t *parse_conditional_expression(unsigned precedence,
                        other_expression = true_expression;
                }
 
-               if(is_type_pointer(other_type)) {
-                       if(!pointers_compatible(true_type, false_type)) {
+               /* TODO Treat (void*)0 as null pointer constant */
+               if (is_type_pointer(other_type)) {
+                       type_t *to1 = pointer_type->pointer.points_to;
+                       type_t *to2 = other_type->pointer.points_to;
+
+                       type_t *to;
+                       if (is_type_atomic(to1, ATOMIC_TYPE_VOID) ||
+                           is_type_atomic(to2, ATOMIC_TYPE_VOID)) {
+                               to = type_void;
+                       } else if (types_compatible(get_unqualified_type(to1),
+                                                   get_unqualified_type(to2))) {
+                               to = to1;
+                       } else {
                                warningf(&expression->base.source_position,
-                                               "pointer types '%T' and '%T' in conditional expression are incompatible", true_type, false_type);
+                                       "pointer types '%T' and '%T' in conditional expression are incompatible",
+                                       true_type, false_type);
+                               to = type_void;
                        }
-                       result_type = true_type;
+
+                       type_t *const copy = duplicate_type(to);
+                       copy->base.qualifiers = to1->base.qualifiers | to2->base.qualifiers;
+
+                       type_t *const type = typehash_insert(copy);
+                       if (type != copy)
+                               free_type(copy);
+
+                       result_type = make_pointer_type(type, TYPE_QUALIFIER_NONE);
                } else if(is_null_pointer_constant(other_expression)) {
                        result_type = pointer_type;
                } else if(is_type_integer(other_type)) {
diff --git a/type.c b/type.c
index 6d0d1e6..59d7722 100644 (file)
--- a/type.c
+++ b/type.c
@@ -1023,22 +1023,6 @@ bool types_compatible(const type_t *type1, const type_t *type2)
        return false;
 }
 
-/**
- * Check if two pointer types are compatible.
- */
-bool pointers_compatible(const type_t *type1, const type_t *type2)
-{
-       assert(!is_typeref(type1));
-       assert(!is_typeref(type2));
-
-       assert(type1->kind == TYPE_POINTER);
-       assert(type2->kind == TYPE_POINTER);
-       (void) type1;
-       (void) type2;
-       /* TODO */
-       return true;
-}
-
 /**
  * Skip all typerefs and return the underlying type.
  */
diff --git a/type.h b/type.h
index 964013b..4b03f6c 100644 (file)
--- a/type.h
+++ b/type.h
@@ -137,8 +137,6 @@ bool is_type_object(const type_t *type);
 
 bool types_compatible(const type_t *type1, const type_t *type2);
 
-bool pointers_compatible(const type_t *type1, const type_t *type2);
-
 type_t *get_unqualified_type(type_t *type);
 type_t *skip_typeref(type_t *type);