further improve initializers
[cparser] / parser.c
index fcc30ea..fd91636 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);
@@ -755,6 +739,7 @@ static void label_pop_to(size_t new_top)
 
 static int get_rank(const type_t *type)
 {
+       assert(!is_typeref(type));
        /* The C-standard allows promoting to int or unsigned int (see § 7.2.2
         * and esp. footnote 108). However we can't fold constants (yet), so we
         * can't decide wether unsigned int is possible, while int always works.
@@ -910,12 +895,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 +910,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;
        }
@@ -1111,7 +1099,7 @@ static initializer_t *initializer_from_expression(type_t *type,
        /* TODO check that expression is a constant expression */
 
        /* § 6.7.8.14/15 char array may be initialized by string literals */
-       if(type->type == TYPE_ARRAY && expression->type == EXPR_STRING_LITERAL) {
+       if(is_type_array(type) && expression->type == EXPR_STRING_LITERAL) {
                array_type_t *array_type   = &type->array;
                type_t       *element_type = array_type->element_type;
 
@@ -1130,12 +1118,17 @@ static initializer_t *initializer_from_expression(type_t *type,
                }
        }
 
-       semantic_assign(type, &expression, "initializer");
+       type_t *expression_type = skip_typeref(expression->base.datatype);
+       if(is_type_scalar(type) || types_compatible(type, expression_type)) {
+               semantic_assign(type, &expression, "initializer");
 
-       initializer_t *result = allocate_initializer(INITIALIZER_VALUE);
-       result->value.value   = expression;
+               initializer_t *result = allocate_initializer(INITIALIZER_VALUE);
+               result->value.value   = expression;
 
-       return result;
+               return result;
+       }
+
+       return NULL;
 }
 
 static initializer_t *parse_sub_initializer(type_t *type,
@@ -1183,17 +1176,11 @@ static initializer_t *parse_sub_initializer(type_t *type,
                return initializer_from_expression(type, expression);
        }
 
-       /* TODO: ignore qualifiers, comparing pointers is probably
-        * not correct */
-       if(expression != NULL && expression_type == type) {
-               initializer_t *result = allocate_initializer(INITIALIZER_VALUE);
-
-               if(type != NULL) {
-                       semantic_assign(type, &expression, "initializer");
-               }
-               result->value.value = expression;
-
-               return result;
+       /* does the expression match the currently looked at object to initalize */
+       if(expression != NULL) {
+               initializer_t *result = initializer_from_expression(type, expression);
+               if(result != NULL)
+                       return result;
        }
 
        bool read_paren = false;
@@ -1205,7 +1192,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
        /* descend into subtype */
        initializer_t  *result = NULL;
        initializer_t **elems;
-       if(type->type == TYPE_ARRAY) {
+       if(is_type_array(type)) {
                array_type_t *array_type   = &type->array;
                type_t       *element_type = array_type->element_type;
                element_type               = skip_typeref(element_type);
@@ -1235,7 +1222,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        if(token.type == '}')
                                break;
 
-                       sub = parse_sub_initializer(element_type, NULL, NULL);
+                       sub = parse_sub_initializer_elem(element_type);
                        if(sub == NULL) {
                                /* TODO error, do nicer cleanup */
                                parse_error("member initializer didn't match");
@@ -1245,8 +1232,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        ARR_APP1(initializer_t*, elems, sub);
                }
        } else {
-               assert(type->type == TYPE_COMPOUND_STRUCT
-                               || type->type == TYPE_COMPOUND_UNION);
+               assert(is_type_compound(type));
                compound_type_t *compound_type = &type->compound;
                context_t       *context       = &compound_type->declaration->context;
 
@@ -1289,7 +1275,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        type_t *iter_type = iter->type;
                        iter_type         = skip_typeref(iter_type);
 
-                       sub = parse_sub_initializer(iter_type, NULL, NULL);
+                       sub = parse_sub_initializer_elem(iter_type);
                        if(sub == NULL) {
                                /* TODO error, do nicer cleanup*/
                                parse_error("member initializer didn't match");
@@ -1327,8 +1313,19 @@ static initializer_t *parse_initializer(type_t *type)
        type = skip_typeref(type);
 
        if(token.type != '{') {
-               expression_t *expression = parse_assignment_expression();
-               return initializer_from_expression(type, expression);
+               expression_t  *expression  = parse_assignment_expression();
+               initializer_t *initializer = initializer_from_expression(type, expression);
+               if(initializer == NULL) {
+                       parser_print_error_prefix();
+                       fprintf(stderr, "initializer expression '");
+                       print_expression(expression);
+                       fprintf(stderr, "', type ");
+                       print_type_quoted(expression->base.datatype);
+                       fprintf(stderr, " is incompatible with type ");
+                       print_type_quoted(type);
+                       fprintf(stderr, "\n");
+               }
+               return initializer;
        }
 
        if(is_type_scalar(type)) {
@@ -1945,6 +1942,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 (is_type_array(type)) {
+               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;
@@ -1954,18 +1987,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;
 }
@@ -2251,7 +2273,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;
@@ -2397,7 +2419,7 @@ static void parse_init_declarator_rest(declaration_t *declaration)
 
        /* § 6.7.5 (22)  array intializers for arrays with unknown size determine
         * the array type size */
-       if(type != NULL && type->type == TYPE_ARRAY && initializer != NULL) {
+       if(type != NULL && is_type_array(type) && initializer != NULL) {
                array_type_t *array_type = &type->array;
 
                if(array_type->size == NULL) {
@@ -2418,7 +2440,7 @@ static void parse_init_declarator_rest(declaration_t *declaration)
                }
        }
 
-       if(type != NULL && type->type == TYPE_FUNCTION) {
+       if(type != NULL && is_type_function(type)) {
                parser_print_error_prefix_pos(declaration->source_position);
                fprintf(stderr, "initializers not allowed for function types at "
                                "declator '%s' (type ", declaration->symbol->string);
@@ -2526,7 +2548,7 @@ static void parse_declaration(parsed_declaration_func finished_declaration)
 static void parse_kr_declaration_list(declaration_t *declaration)
 {
        type_t *type = skip_typeref(declaration->type);
-       assert(type->type == TYPE_FUNCTION);
+       assert(is_type_function(type));
 
        if(!type->function.kr_style_parameters)
                return;
@@ -2576,6 +2598,9 @@ static void parse_kr_declaration_list(declaration_t *declaration)
 #endif
                }
 
+               semantic_parameter(parameter_declaration);
+               parameter_type = parameter_declaration->type;
+
                function_parameter_t *function_parameter
                        = obstack_alloc(type_obst, sizeof(function_parameter[0]));
                memset(function_parameter, 0, sizeof(function_parameter[0]));
@@ -2630,17 +2655,18 @@ static void parse_external_declaration(void)
                return;
        }
 
-       type_t *orig_type = ndeclaration->type;
-       if(orig_type == NULL) {
+       type_t *type = ndeclaration->type;
+       if(type == NULL) {
                eat_block();
                return;
        }
 
-       type_t *type = skip_typeref(orig_type);
+       /* note that we don't skip typerefs: the standard doesn't allow them here
+        * (so we can't use is_type_function here) */
        if(type->type != TYPE_FUNCTION) {
                parser_print_error_prefix();
                fprintf(stderr, "declarator '");
-               print_type_ext(orig_type, ndeclaration->symbol, NULL);
+               print_type_ext(type, ndeclaration->symbol, NULL);
                fprintf(stderr, "' has a body but is not a function type.\n");
                eat_block();
                return;
@@ -2841,7 +2867,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);
@@ -2873,7 +2899,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]));
@@ -2881,7 +2907,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);
@@ -2911,12 +2937,13 @@ static type_t *get_builtin_symbol_type(symbol_t *symbol)
 /**
  * performs automatic type cast as described in § 6.3.2.1
  */
-static type_t *automatic_type_conversion(type_t *type)
+static type_t *automatic_type_conversion(type_t *orig_type)
 {
-       if(type == NULL)
+       if(orig_type == NULL)
                return NULL;
 
-       if(type->type == TYPE_ARRAY) {
+       type_t *type = skip_typeref(orig_type);
+       if(is_type_array(type)) {
                array_type_t *array_type   = &type->array;
                type_t       *element_type = array_type->element_type;
                unsigned      qualifiers   = array_type->type.qualifiers;
@@ -2924,11 +2951,11 @@ static type_t *automatic_type_conversion(type_t *type)
                return make_pointer_type(element_type, qualifiers);
        }
 
-       if(type->type == TYPE_FUNCTION) {
-               return make_pointer_type(type, TYPE_QUALIFIER_NONE);
+       if(is_type_function(type)) {
+               return make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
        }
 
-       return type;
+       return orig_type;
 }
 
 /**
@@ -3300,7 +3327,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);
@@ -3308,12 +3335,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;
@@ -3336,8 +3363,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,9 +3496,9 @@ static expression_t *parse_call_expression(unsigned precedence,
 
                        type = skip_typeref(pointer_type->points_to);
 
-                       if (type->type == TYPE_FUNCTION) {
+                       if (is_type_function(type)) {
                                function_type             = &type->function;
-                               call->expression.datatype = function_type->result_type;
+                               call->expression.datatype = function_type->return_type;
                        }
                }
                if(function_type == NULL) {
@@ -3969,10 +3996,9 @@ static void semantic_sub(binary_expression_t *expression)
                expression->right = create_implicit_cast(right, arithmetic_type);
                expression->expression.datatype = arithmetic_type;
                return;
-       } else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
+       } else if(is_type_pointer(type_left) && is_type_integer(type_right)) {
                expression->expression.datatype = type_left;
-       } else if(type_left->type == TYPE_POINTER &&
-                       type_right->type == TYPE_POINTER) {
+       } else if(is_type_pointer(type_left) && is_type_pointer(type_right)) {
                if(!pointers_compatible(type_left, type_right)) {
                        parser_print_error_prefix();
                        fprintf(stderr, "pointers to incompatible objects to binary - (");
@@ -4012,12 +4038,11 @@ static void semantic_comparison(binary_expression_t *expression)
                expression->left  = create_implicit_cast(left, arithmetic_type);
                expression->right = create_implicit_cast(right, arithmetic_type);
                expression->expression.datatype = arithmetic_type;
-       } else if (type_left->type  == TYPE_POINTER &&
-                  type_right->type == TYPE_POINTER) {
+       } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
                /* TODO check compatibility */
-       } else if (type_left->type == TYPE_POINTER) {
+       } else if (is_type_pointer(type_left)) {
                expression->right = create_implicit_cast(right, type_left);
-       } else if (type_right->type == TYPE_POINTER) {
+       } else if (is_type_pointer(type_right)) {
                expression->left = create_implicit_cast(left, type_right);
        } else {
                type_error_incompatible("invalid operands in comparison",
@@ -4076,7 +4101,7 @@ static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression)
                type_t *const arithmetic_type = semantic_arithmetic(type_left, type_right);
                expression->right = create_implicit_cast(right, arithmetic_type);
                expression->expression.datatype = type_left;
-       } else if (type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
+       } else if (is_type_pointer(type_left) && is_type_integer(type_right)) {
                expression->expression.datatype = type_left;
        } else {
                parser_print_error_prefix();
@@ -4128,10 +4153,10 @@ static void semantic_binexpr_assign(binary_expression_t *expression)
                return;
 
        type_t *type_left = revert_automatic_type_conversion(left);
-       type_left = skip_typeref(orig_type_left);
+       type_left         = skip_typeref(orig_type_left);
 
        /* must be a modifiable lvalue */
-       if (type_left->type == TYPE_ARRAY) {
+       if (is_type_array(type_left)) {
                parser_print_error_prefix();
                fprintf(stderr, "Cannot assign to arrays ('");
                print_expression(left);
@@ -4754,9 +4779,9 @@ static statement_t *parse_return(void)
        statement->statement.type            = STATEMENT_RETURN;
        statement->statement.source_position = token.source_position;
 
-       assert(current_function->type->type == TYPE_FUNCTION);
+       assert(is_type_function(current_function->type));
        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 != ';') {