implemented several type compatibility rules, renamed function_type->result_type...
authorMatthias Braun <matze@braunis.de>
Fri, 30 Nov 2007 11:22:25 +0000 (11:22 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 30 Nov 2007 11:22:25 +0000 (11:22 +0000)
[r18574]

ast2firm.c
parser.c
type.c
type.h
type_hash.c
type_t.h
write_fluffy.c

index 315da62..4d96505 100644 (file)
@@ -263,15 +263,15 @@ static ir_type *create_atomic_type(const atomic_type_t *type)
 
 static ir_type *create_method_type(const function_type_t *function_type)
 {
-       type_t  *result_type  = function_type->result_type;
+       type_t  *return_type  = function_type->return_type;
 
        ident   *id           = unique_ident("functiontype");
        int      n_parameters = count_parameters(function_type);
-       int      n_results    = result_type == type_void ? 0 : 1;
+       int      n_results    = return_type == type_void ? 0 : 1;
        ir_type *irtype       = new_type_method(id, n_parameters, n_results);
 
-       if(result_type != type_void) {
-               ir_type *restype = get_ir_type(result_type);
+       if(return_type != type_void) {
+               ir_type *restype = get_ir_type(return_type);
                set_method_res_type(irtype, 0, restype);
        }
 
@@ -854,7 +854,7 @@ static ir_node *process_builtin_call(const call_expression_t *call)
        case T___builtin_nand: {
                /* Ignore string for now... */
                assert(function_type->type == TYPE_FUNCTION);
-               ir_mode *mode = get_ir_mode(function_type->function.result_type);
+               ir_mode *mode = get_ir_mode(function_type->function.return_type);
                tarval  *tv   = get_mode_NAN(mode);
                ir_node *res  = new_d_Const(dbgi, mode, tv);
                return res;
@@ -935,13 +935,13 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
        ir_node  *mem   = new_d_Proj(dbgi, node, mode_M, pn_Call_M_regular);
        set_store(mem);
 
-       type_t  *result_type = skip_typeref(function_type->result_type);
+       type_t  *return_type = skip_typeref(function_type->return_type);
        ir_node *result      = NULL;
 
-       if(!is_type_atomic(result_type, ATOMIC_TYPE_VOID)) {
+       if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
                ir_mode *mode;
-               if(is_type_scalar(result_type)) {
-                       mode = get_ir_mode(result_type);
+               if(is_type_scalar(return_type)) {
+                       mode = get_ir_mode(return_type);
                } else {
                        mode = mode_P_data;
                }
@@ -2921,15 +2921,15 @@ static void create_function(declaration_t *declaration)
        if(get_cur_block() != NULL) {
                assert(declaration->type->type == TYPE_FUNCTION);
                const function_type_t* const func_type = &declaration->type->function;
-               const type_t *result_type = skip_typeref(func_type->result_type);
+               const type_t *return_type = skip_typeref(func_type->return_type);
 
                ir_node *ret;
-               if (is_type_atomic(result_type, ATOMIC_TYPE_VOID)) {
+               if (is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
                        ret = new_Return(get_store(), 0, NULL);
                } else {
                        ir_mode *mode;
-                       if(is_type_scalar(result_type)) {
-                               mode = get_ir_mode(func_type->result_type);
+                       if(is_type_scalar(return_type)) {
+                               mode = get_ir_mode(func_type->return_type);
                        } else {
                                mode = mode_P_data;
                        }
index 811f2a0..d7317ce 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -517,26 +517,10 @@ static bool is_compatible_declaration(declaration_t *declaration,
                return true;
        }
 
-       /* shortcur, same types are always compatible */
-       if(declaration->type == previous->type)
-               return true;
-
-       if (declaration->type->type == TYPE_FUNCTION &&
-                       previous->type->type == TYPE_FUNCTION) {
-               function_type_t* const prev_func = &previous->type->function;
-               function_type_t* const decl_func = &declaration->type->function;
-
-               /* 1 of the 2 declarations might have unspecified parameters */
-               if(decl_func->unspecified_parameters) {
-                       return true;
-               } else if(prev_func->unspecified_parameters) {
-                       declaration->type = previous->type;
-                       return true;
-               }
-       }
+       type_t *type1 = skip_typeref(declaration->type);
+       type_t *type2 = skip_typeref(previous->type);
 
-       /* TODO: not correct/complete yet */
-       return false;
+       return types_compatible(type1, type2);
 }
 
 static declaration_t *get_declaration(symbol_t *symbol, namespace_t namespc)
@@ -587,7 +571,7 @@ static declaration_t *stack_push(stack_entry_t **stack_ptr,
                        && previous_declaration->parent_context == context) {
                if(!is_compatible_declaration(declaration, previous_declaration)) {
                        parser_print_error_prefix_pos(declaration->source_position);
-                       fprintf(stderr, "definition of symbol %s%s with type ",
+                       fprintf(stderr, "definition of symbol '%s%s' with type ",
                                        get_namespace_prefix(namespc), symbol->string);
                        print_type_quoted(declaration->type);
                        fputc('\n', stderr);
@@ -910,12 +894,6 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right,
                points_to_left  = skip_typeref(points_to_left);
                points_to_right = skip_typeref(points_to_right);
 
-               if(!is_type_atomic(points_to_left, ATOMIC_TYPE_VOID)
-                               && !is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)
-                               && !types_compatible(points_to_left, points_to_right)) {
-                       goto incompatible_assign_types;
-               }
-
                /* the left type has all qualifiers from the right type */
                unsigned missing_qualifiers
                        = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers;
@@ -931,6 +909,15 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right,
                        return;
                }
 
+               points_to_left  = get_unqualified_type(points_to_left);
+               points_to_right = get_unqualified_type(points_to_right);
+
+               if(!is_type_atomic(points_to_left, ATOMIC_TYPE_VOID)
+                               && !is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)
+                               && !types_compatible(points_to_left, points_to_right)) {
+                       goto incompatible_assign_types;
+               }
+
                *right = create_implicit_cast(*right, type_left);
                return;
        }
@@ -1943,6 +1930,42 @@ static declaration_t *parse_identifier_list(void)
        return declarations;
 }
 
+static void semantic_parameter(declaration_t *declaration)
+{
+       /* TODO: improve error messages */
+
+       if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) {
+               parse_error("typedef not allowed in parameter list");
+       } else if(declaration->storage_class != STORAGE_CLASS_NONE
+                       && declaration->storage_class != STORAGE_CLASS_REGISTER) {
+               parse_error("parameter may only have none or register storage class");
+       }
+
+       type_t *orig_type = declaration->type;
+       if(orig_type == NULL)
+               return;
+       type_t *type = skip_typeref(orig_type);
+
+       /* Array as last part of a paramter type is just syntactic sugar.  Turn it
+        * into a pointer. ยง 6.7.5.3 (7) */
+       if (type->type == TYPE_ARRAY) {
+               const array_type_t *arr_type     = &type->array;
+               type_t             *element_type = arr_type->element_type;
+
+               type = make_pointer_type(element_type, type->base.qualifiers);
+
+               declaration->type = type;
+       }
+
+       if(is_type_incomplete(type)) {
+               parser_print_error_prefix();
+               fprintf(stderr, "incomplete type (");
+               print_type_quoted(orig_type);
+               fprintf(stderr, ") not allowed for parameter '%s'\n",
+                       declaration->symbol->string);
+       }
+}
+
 static declaration_t *parse_parameter(void)
 {
        declaration_specifiers_t specifiers;
@@ -1952,18 +1975,7 @@ static declaration_t *parse_parameter(void)
 
        declaration_t *declaration = parse_declarator(&specifiers, true);
 
-       /* TODO check declaration constraints for parameters */
-       if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) {
-               parse_error("typedef not allowed in parameter list");
-       }
-
-       /* Array as last part of a paramter type is just syntactic sugar.  Turn it
-        * into a pointer */
-       if (declaration->type->type == TYPE_ARRAY) {
-               const array_type_t *const arr_type = &declaration->type->array;
-               type_t *element_type = arr_type->element_type;
-               declaration->type = make_pointer_type(element_type, TYPE_QUALIFIER_NONE);
-       }
+       semantic_parameter(declaration);
 
        return declaration;
 }
@@ -2249,7 +2261,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
 
                        type_t *function_type = construct_function_type->function_type;
 
-                       function_type->function.result_type = type;
+                       function_type->function.return_type = type;
 
                        type = function_type;
                        break;
@@ -2574,6 +2586,8 @@ static void parse_kr_declaration_list(declaration_t *declaration)
 #endif
                }
 
+               semantic_parameter(parameter_declaration);
+
                function_parameter_t *function_parameter
                        = obstack_alloc(type_obst, sizeof(function_parameter[0]));
                memset(function_parameter, 0, sizeof(function_parameter[0]));
@@ -2839,7 +2853,7 @@ static declaration_t *create_implicit_function(symbol_t *symbol,
                const source_position_t source_position)
 {
        type_t *ntype                          = allocate_type_zero(TYPE_FUNCTION);
-       ntype->function.result_type            = type_int;
+       ntype->function.return_type            = type_int;
        ntype->function.unspecified_parameters = true;
 
        type_t *type = typehash_insert(ntype);
@@ -2871,7 +2885,7 @@ static declaration_t *create_implicit_function(symbol_t *symbol,
        return declaration;
 }
 
-static type_t *make_function_1_type(type_t *result_type, type_t *argument_type)
+static type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
 {
        function_parameter_t *parameter
                = obstack_alloc(type_obst, sizeof(parameter[0]));
@@ -2879,7 +2893,7 @@ static type_t *make_function_1_type(type_t *result_type, type_t *argument_type)
        parameter->type = argument_type;
 
        type_t *type               = allocate_type_zero(TYPE_FUNCTION);
-       type->function.result_type = result_type;
+       type->function.return_type = return_type;
        type->function.parameters  = parameter;
 
        type_t *result = typehash_insert(type);
@@ -3298,7 +3312,7 @@ static expression_t *parse_array_expression(unsigned precedence,
 
        type_t *type_left   = left->base.datatype;
        type_t *type_inside = inside->base.datatype;
-       type_t *result_type = NULL;
+       type_t *return_type = NULL;
 
        if(type_left != NULL && type_inside != NULL) {
                type_left   = skip_typeref(type_left);
@@ -3306,12 +3320,12 @@ static expression_t *parse_array_expression(unsigned precedence,
 
                if(is_type_pointer(type_left)) {
                        pointer_type_t *pointer = &type_left->pointer;
-                       result_type             = pointer->points_to;
+                       return_type             = pointer->points_to;
                        array_access->array_ref = left;
                        array_access->index     = inside;
                } else if(is_type_pointer(type_inside)) {
                        pointer_type_t *pointer = &type_inside->pointer;
-                       result_type             = pointer->points_to;
+                       return_type             = pointer->points_to;
                        array_access->array_ref = inside;
                        array_access->index     = left;
                        array_access->flipped   = true;
@@ -3334,8 +3348,8 @@ static expression_t *parse_array_expression(unsigned precedence,
        }
        next_token();
 
-       result_type = automatic_type_conversion(result_type);
-       array_access->expression.datatype = result_type;
+       return_type = automatic_type_conversion(return_type);
+       array_access->expression.datatype = return_type;
 
        return (expression_t*) array_access;
 }
@@ -3469,7 +3483,7 @@ static expression_t *parse_call_expression(unsigned precedence,
 
                        if (type->type == TYPE_FUNCTION) {
                                function_type             = &type->function;
-                               call->expression.datatype = function_type->result_type;
+                               call->expression.datatype = function_type->return_type;
                        }
                }
                if(function_type == NULL) {
@@ -4754,7 +4768,7 @@ static statement_t *parse_return(void)
 
        assert(current_function->type->type == TYPE_FUNCTION);
        function_type_t *function_type = &current_function->type->function;
-       type_t          *return_type   = function_type->result_type;
+       type_t          *return_type   = function_type->return_type;
 
        expression_t *return_value = NULL;
        if(token.type != ';') {
diff --git a/type.c b/type.c
index 608625c..8a6486d 100644 (file)
--- a/type.c
+++ b/type.c
@@ -74,7 +74,7 @@ static void print_function_type_pre(const function_type_t *type)
 {
        print_type_qualifiers(type->type.qualifiers);
 
-       intern_print_type_pre(type->result_type);
+       intern_print_type_pre(type->return_type);
 
        /* TODO: don't emit braces if we're the toplevel type... */
        fputc('(', out);
@@ -84,7 +84,7 @@ static void print_function_type_post(const function_type_t *type,
                                      const context_t *context)
 {
        /* TODO: don't emit braces if we're the toplevel type... */
-       intern_print_type_post(type->result_type);
+       intern_print_type_post(type->return_type);
        fputc(')', out);
 
        fputc('(', out);
@@ -336,6 +336,54 @@ void print_type_ext(type_t *type, const symbol_t *symbol,
        }
 }
 
+static size_t get_type_size(type_t *type)
+{
+       switch(type->type) {
+       case TYPE_ATOMIC:          return sizeof(atomic_type_t);
+       case TYPE_COMPOUND_STRUCT:
+       case TYPE_COMPOUND_UNION:  return sizeof(compound_type_t);
+       case TYPE_ENUM:            return sizeof(enum_type_t);
+       case TYPE_FUNCTION:        return sizeof(function_type_t);
+       case TYPE_POINTER:         return sizeof(pointer_type_t);
+       case TYPE_ARRAY:           return sizeof(array_type_t);
+       case TYPE_BUILTIN:         return sizeof(builtin_type_t);
+       case TYPE_TYPEDEF:         return sizeof(typedef_type_t);
+       case TYPE_TYPEOF:          return sizeof(typeof_type_t);
+       case TYPE_INVALID:         panic("invalid type found");
+       }
+       panic("unknown type found");
+}
+
+/**
+ * duplicates a type
+ * note that this does not produce a deep copy!
+ */
+type_t *duplicate_type(type_t *type)
+{
+       size_t size = get_type_size(type);
+
+       type_t *copy = obstack_alloc(type_obst, size);
+       memcpy(copy, type, size);
+
+       return copy;
+}
+
+type_t *get_unqualified_type(type_t *type)
+{
+       if(type->base.qualifiers == TYPE_QUALIFIER_NONE)
+               return type;
+
+       type_t *unqualified_type          = duplicate_type(type);
+       unqualified_type->base.qualifiers = TYPE_QUALIFIER_NONE;
+
+       type_t *result = typehash_insert(unqualified_type);
+       if(result != unqualified_type) {
+               obstack_free(type_obst, unqualified_type);
+       }
+
+       return result;
+}
+
 bool type_valid(const type_t *type)
 {
        return type->type != TYPE_INVALID;
@@ -496,19 +544,97 @@ bool is_type_incomplete(const type_t *type)
        panic("invalid type found");
 }
 
+static bool function_types_compatible(const function_type_t *func1,
+                                      const function_type_t *func2)
+{
+       if(!types_compatible(func1->return_type, func2->return_type))
+               return false;
+
+       /* can parameters be compared? */
+       if(func1->unspecified_parameters || func2->unspecified_parameters)
+               return true;
+
+       if(func1->variadic != func2->variadic)
+               return false;
+
+       /* TODO: handling of unspecified parameters not correct yet */
+
+       /* all argument types must be compatible */
+       function_parameter_t *parameter1 = func1->parameters;
+       function_parameter_t *parameter2 = func2->parameters;
+       for( ; parameter1 != NULL && parameter2 != NULL;
+                       parameter1 = parameter1->next, parameter2 = parameter2->next) {
+               type_t *parameter1_type = skip_typeref(parameter1->type);
+               type_t *parameter2_type = skip_typeref(parameter2->type);
+
+               parameter1_type = get_unqualified_type(parameter1_type);
+               parameter2_type = get_unqualified_type(parameter2_type);
+
+               if(!types_compatible(parameter1_type, parameter2_type))
+                       return false;
+       }
+       /* same number of arguments? */
+       if(parameter1 != NULL || parameter2 != NULL)
+               return false;
+
+       return true;
+}
+
+static bool array_types_compatible(const array_type_t *array1,
+                                   const array_type_t *array2)
+{
+       type_t *element_type1 = skip_typeref(array1->element_type);
+       type_t *element_type2 = skip_typeref(array2->element_type);
+       if(!types_compatible(element_type1, element_type2))
+               return false;
+
+       if(array1->size != NULL && array2->size != NULL) {
+               /* TODO: check if size expression evaulate to the same value
+                * if they are constant */
+       }
+
+       return true;
+}
+
 bool types_compatible(const type_t *type1, const type_t *type2)
 {
        assert(!is_typeref(type1));
        assert(!is_typeref(type2));
 
-       /* TODO: really incomplete */
+       /* shortcut: the same type is always compatible */
        if(type1 == type2)
                return true;
 
-       if(type1->type == TYPE_ATOMIC && type2->type == TYPE_ATOMIC) {
+       if(type1->base.qualifiers != type2->base.qualifiers)
+               return false;
+       if(type1->type != type2->type)
+               return false;
+
+       switch(type1->type) {
+       case TYPE_FUNCTION:
+               return function_types_compatible(&type1->function, &type2->function);
+       case TYPE_ATOMIC:
                return type1->atomic.atype == type2->atomic.atype;
+       case TYPE_ARRAY:
+               return array_types_compatible(&type1->array, &type2->array);
+       case TYPE_POINTER:
+               return types_compatible(type1->pointer.points_to,
+                                       type2->pointer.points_to);
+       case TYPE_COMPOUND_STRUCT:
+       case TYPE_COMPOUND_UNION:
+       case TYPE_ENUM:
+       case TYPE_BUILTIN:
+               /* TODO: not implemented */
+               break;
+
+       case TYPE_INVALID:
+               panic("invalid type found in compatible types");
+       case TYPE_TYPEDEF:
+       case TYPE_TYPEOF:
+               panic("typerefs not skipped in compatible types?!?");
        }
 
+       /* TODO: incomplete */
        return false;
 }
 
@@ -523,38 +649,6 @@ bool pointers_compatible(const type_t *type1, const type_t *type2)
        return true;
 }
 
-static size_t get_type_size(type_t *type)
-{
-       switch(type->type) {
-       case TYPE_ATOMIC:          return sizeof(atomic_type_t);
-       case TYPE_COMPOUND_STRUCT:
-       case TYPE_COMPOUND_UNION:  return sizeof(compound_type_t);
-       case TYPE_ENUM:            return sizeof(enum_type_t);
-       case TYPE_FUNCTION:        return sizeof(function_type_t);
-       case TYPE_POINTER:         return sizeof(pointer_type_t);
-       case TYPE_ARRAY:           return sizeof(array_type_t);
-       case TYPE_BUILTIN:         return sizeof(builtin_type_t);
-       case TYPE_TYPEDEF:         return sizeof(typedef_type_t);
-       case TYPE_TYPEOF:          return sizeof(typeof_type_t);
-       case TYPE_INVALID:         panic("invalid type found");
-       }
-       panic("unknown type found");
-}
-
-/**
- * duplicates a type
- * note that this does not produce a deep copy!
- */
-type_t *duplicate_type(type_t *type)
-{
-       size_t size = get_type_size(type);
-
-       type_t *copy = obstack_alloc(type_obst, size);
-       memcpy(copy, type, size);
-
-       return copy;
-}
-
 type_t *skip_typeref(type_t *type)
 {
        unsigned qualifiers = type->base.qualifiers;
diff --git a/type.h b/type.h
index 33300a9..30050da 100644 (file)
--- a/type.h
+++ b/type.h
@@ -79,6 +79,7 @@ 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);
 
 #endif
index c21d16f..d731867 100644 (file)
@@ -53,7 +53,7 @@ static unsigned hash_type(const type_t *type);
 
 static unsigned hash_function_type(const function_type_t *type)
 {
-       unsigned result = hash_ptr(type->result_type);
+       unsigned result = hash_ptr(type->return_type);
 
        function_parameter_t *parameter = type->parameters;
        while(parameter != NULL) {
@@ -130,7 +130,7 @@ static bool atomic_types_equal(const atomic_type_t *type1,
 static bool function_types_equal(const function_type_t *type1,
                                  const function_type_t *type2)
 {
-       if(type1->result_type != type2->result_type)
+       if(type1->return_type != type2->return_type)
                return false;
        if(type1->variadic != type2->variadic)
                return false;
index a45997d..13a090f 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -105,7 +105,7 @@ struct function_parameter_t {
 
 struct function_type_t {
        type_base_t           type;
-       type_t               *result_type;
+       type_t               *return_type;
        function_parameter_t *parameters;
        unsigned              variadic : 1;
        unsigned              unspecified_parameters : 1;
index 4895a36..c6463d0 100644 (file)
@@ -131,7 +131,7 @@ static void write_function_type(const function_type_t *type)
        }
 
        fprintf(out, ") : ");
-       write_type(type->result_type);
+       write_type(type->return_type);
        fprintf(out, ")");
 }
 
@@ -298,11 +298,10 @@ static void write_function(const declaration_t *declaration)
        }
        fprintf(out, ")");
 
-       const type_t *result_type = function_type->result_type;
-       if(result_type->type != TYPE_ATOMIC ||
-                       ((const atomic_type_t*) result_type)->atype != ATOMIC_TYPE_VOID) {
+       const type_t *return_type = function_type->return_type;
+       if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
                fprintf(out, " : ");
-               write_type(result_type);
+               write_type(return_type);
        }
        fputc('\n', out);
 }