fixed some warnings
[cparser] / parser.c
index 3f73c1d..fa8ad94 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -45,6 +45,7 @@ static type_t         *type_float       = NULL;
 static type_t         *type_const_char  = NULL;
 static type_t         *type_string      = NULL;
 static type_t         *type_void        = NULL;
+static type_t         *type_void_ptr    = NULL;
 static type_t         *type_size_t      = NULL;
 static type_t         *type_ptrdiff_t   = NULL;
 
@@ -71,14 +72,10 @@ static type_t       *parse_typename(void);
 #ifdef PROVIDE_COMPLEX
 #define COMPLEX_SPECIFIERS  \
        case T__Complex:
-#else
-#define COMPLEX_SPECIFIERS
-#endif
-
-#ifdef PROVIDE_IMAGINARY
 #define IMAGINARY_SPECIFIERS \
        case T__Imaginary:
 #else
+#define COMPLEX_SPECIFIERS
 #define IMAGINARY_SPECIFIERS
 #endif
 
@@ -700,14 +697,35 @@ static expression_t *create_implicit_cast(expression_t *expression,
                }
 
                type_error_incompatible("can't implicitly cast types",
-                                                                                                               expression->source_position,
-                                                                                                               source_type, dest_type);
+                                       expression->source_position,
+                                       source_type, dest_type);
                return expression;
        }
 
        panic("casting of non-atomic types not implemented yet");
 }
 
+static bool is_atomic_type(const type_t *type, atomic_type_type_t atype)
+{
+       if(type->type != TYPE_ATOMIC)
+               return false;
+       const atomic_type_t *atomic_type = (const atomic_type_t*) type;
+
+       return atomic_type->atype == atype;
+}
+
+static bool is_pointer(const type_t *type)
+{
+       return type->type == TYPE_POINTER;
+}
+
+static bool is_compound_type(const type_t *type)
+{
+       return type->type == TYPE_COMPOUND_STRUCT
+               || type->type == TYPE_COMPOUND_UNION;
+}
+
+/** Implements the rules from ยง 6.5.16.1 */
 static void semantic_assign(type_t *orig_type_left, expression_t **right,
                             const char *context)
 {
@@ -719,40 +737,52 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right,
        type_t *const type_left  = skip_typeref(orig_type_left);
        type_t *const type_right = skip_typeref(orig_type_right);
 
-       if (type_left == type_right) {
-               return;
-       }
-
        if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) ||
-           (type_left->type == TYPE_POINTER && is_null_expression(*right)) ||
-           (type_left->type == TYPE_POINTER && type_right->type == TYPE_POINTER)) {
+           (is_pointer(type_left) && is_null_expression(*right)) ||
+           (is_atomic_type(type_left, ATOMIC_TYPE_BOOL)
+               && is_pointer(type_right))) {
                *right = create_implicit_cast(*right, type_left);
                return;
        }
 
-       if (type_left->type == TYPE_POINTER) {
-               switch (type_right->type) {
-                       case TYPE_FUNCTION: {
-                               pointer_type_t *const ptr_type = (pointer_type_t*)type_left;
-                               if (ptr_type->points_to == type_right) {
-                                       return;
-                               }
-                               break;
-                       }
+       if (is_pointer(type_left) && is_pointer(type_right)) {
+               pointer_type_t *pointer_type_left  = (pointer_type_t*) type_left;
+               pointer_type_t *pointer_type_right = (pointer_type_t*) type_right;
+               type_t         *points_to_left     = pointer_type_left->points_to;
+               type_t         *points_to_right    = pointer_type_right->points_to;
 
-                       case TYPE_ARRAY: {
-                               pointer_type_t *const ptr_type = (pointer_type_t*)type_left;
-                               array_type_t   *const arr_type = (array_type_t*)type_right;
-                               if (ptr_type->points_to == arr_type->element_type) {
-                                       return;
-                               }
-                               break;
-                       }
+               if(!is_atomic_type(points_to_left, ATOMIC_TYPE_VOID)
+                               && !is_atomic_type(points_to_right, ATOMIC_TYPE_VOID)
+                               && !types_compatible(points_to_left, points_to_right)) {
+                       goto incompatible_assign_types;
+               }
 
-                       default: break;
+               /* the left type has all qualifiers from the right type */
+               unsigned missing_qualifiers
+                       = points_to_right->qualifiers & ~points_to_left->qualifiers;
+               if(missing_qualifiers != 0) {
+                       parser_print_error_prefix();
+                       fprintf(stderr, "destination type ");
+                       print_type_quoted(type_left);
+                       fprintf(stderr, " in %s from type ", context);
+                       print_type_quoted(type_right);
+                       fprintf(stderr, " lacks qualifiers '");
+                       print_type_qualifiers(missing_qualifiers);
+                       fprintf(stderr, "' in pointed-to type\n");
+                       return;
                }
+
+               *right = create_implicit_cast(*right, type_left);
+               return;
        }
 
+       if (is_compound_type(type_left)
+                       && types_compatible(type_left, type_right)) {
+               *right = create_implicit_cast(*right, type_left);
+               return;
+       }
+
+incompatible_assign_types:
        /* TODO: improve error message */
        parser_print_error_prefix();
        fprintf(stderr, "incompatible types in %s\n", context);
@@ -897,10 +927,24 @@ static designator_t *parse_designation(void)
 }
 #endif
 
+static initializer_t *initializer_from_string(array_type_t *type,
+                                              const char *string)
+{
+       /* TODO: check len vs. size of array type */
+       (void) type;
+
+       initializer_string_t *initializer
+               = allocate_ast_zero(sizeof(initializer[0]));
+
+       initializer->initializer.type = INITIALIZER_STRING;
+       initializer->string           = string;
+
+       return (initializer_t*) initializer;
+}
+
 static initializer_t *initializer_from_expression(type_t *type,
                                                   expression_t *expression)
 {
-       initializer_value_t *result = allocate_ast_zero(sizeof(result[0]));
 
        /* TODO check that expression is a constant expression */
 
@@ -917,15 +961,16 @@ static initializer_t *initializer_from_expression(type_t *type,
                        if(atype == ATOMIC_TYPE_CHAR
                                        || atype == ATOMIC_TYPE_SCHAR
                                        || atype == ATOMIC_TYPE_UCHAR) {
-                               /* it's fine TODO: check for length of string array... */
-                               goto initializer_from_expression_finished;
+
+                               string_literal_t *literal = (string_literal_t*) expression;
+                               return initializer_from_string(array_type, literal->value);
                        }
                }
        }
 
        semantic_assign(type, &expression, "initializer");
 
-initializer_from_expression_finished:
+       initializer_value_t *result = allocate_ast_zero(sizeof(result[0]));
        result->initializer.type = INITIALIZER_VALUE;
        result->value            = expression;
 
@@ -980,15 +1025,15 @@ static initializer_t *parse_sub_initializer(type_t *type,
        /* TODO: ignore qualifiers, comparing pointers is probably
         * not correct */
        if(expression != NULL && expression_type == type) {
-               initializer_t *result = allocate_ast_zero(sizeof(result[0]));
-               result->type          = INITIALIZER_VALUE;
+               initializer_value_t *result = allocate_ast_zero(sizeof(result[0]));
+               result->initializer.type    = INITIALIZER_VALUE;
 
                if(type != NULL) {
                        semantic_assign(type, &expression, "initializer");
                }
-               //result->v.value = expression;
+               result->value = expression;
 
-               return result;
+               return (initializer_t*) result;
        }
 
        bool read_paren = false;
@@ -998,14 +1043,48 @@ static initializer_t *parse_sub_initializer(type_t *type,
        }
 
        /* descend into subtype */
-       initializer_t *result = NULL;
+       initializer_t  *result = NULL;
+       initializer_t **elems;
        if(type->type == TYPE_ARRAY) {
                array_type_t *array_type   = (array_type_t*) type;
                type_t       *element_type = array_type->element_type;
                element_type               = skip_typeref(element_type);
 
-               result
-                       = parse_sub_initializer(element_type, expression, expression_type);
+               initializer_t *sub;
+               had_initializer_brace_warning = false;
+               if(expression == NULL) {
+                       sub = parse_sub_initializer_elem(element_type);
+               } else {
+                       sub = parse_sub_initializer(element_type, expression,
+                                                   expression_type);
+               }
+
+               /* didn't match the subtypes -> try the parent type */
+               if(sub == NULL) {
+                       assert(!read_paren);
+                       return NULL;
+               }
+
+               elems = NEW_ARR_F(initializer_t*, 0);
+               ARR_APP1(initializer_t*, elems, sub);
+
+               while(true) {
+                       if(token.type == '}')
+                               break;
+                       expect_block(',');
+                       if(token.type == '}')
+                               break;
+
+                       initializer_t *sub
+                               = parse_sub_initializer(element_type, NULL, NULL);
+                       if(sub == NULL) {
+                               /* TODO error, do nicer cleanup */
+                               parse_error("member initializer didn't match");
+                               DEL_ARR_F(elems);
+                               return NULL;
+                       }
+                       ARR_APP1(initializer_t*, elems, sub);
+               }
        } else {
                assert(type->type == TYPE_COMPOUND_STRUCT
                                || type->type == TYPE_COMPOUND_UNION);
@@ -1032,7 +1111,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        return NULL;
                }
 
-               initializer_t **elems = NEW_ARR_F(initializer_t*, 0);
+               elems = NEW_ARR_F(initializer_t*, 0);
                ARR_APP1(initializer_t*, elems, sub);
 
                declaration_t *iter  = first->next;
@@ -1049,7 +1128,6 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        type_t *iter_type = iter->type;
                        iter_type         = skip_typeref(iter_type);
 
-                       /* read next token */
                        initializer_t *sub = parse_sub_initializer(iter_type, NULL, NULL);
                        if(sub == NULL) {
                                /* TODO error, do nicer cleanup*/
@@ -1059,20 +1137,19 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        }
                        ARR_APP1(initializer_t*, elems, sub);
                }
+       }
 
-               int    len        = ARR_LEN(elems);
-               size_t elems_size = sizeof(initializer_t*) * len;
+       int    len        = ARR_LEN(elems);
+       size_t elems_size = sizeof(initializer_t*) * len;
 
-               initializer_list_t *init
-                       = allocate_ast_zero(sizeof(init[0]) + elems_size);
+       initializer_list_t *init = allocate_ast_zero(sizeof(init[0]) + elems_size);
 
-               init->initializer.type = INITIALIZER_LIST;
-               init->len              = len;
-               memcpy(init->initializers, elems, elems_size);
-               DEL_ARR_F(elems);
+       init->initializer.type = INITIALIZER_LIST;
+       init->len              = len;
+       memcpy(init->initializers, elems, elems_size);
+       DEL_ARR_F(elems);
 
-               result = (initializer_t*) init;
-       }
+       result = (initializer_t*) init;
 
        if(read_paren) {
                if(token.type == ',')
@@ -1189,7 +1266,7 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
        return declaration;
 }
 
-static void parse_enum_entries(void)
+static void parse_enum_entries(type_t *enum_type)
 {
        eat('{');
 
@@ -1208,13 +1285,16 @@ static void parse_enum_entries(void)
                        return;
                }
                entry->storage_class   = STORAGE_CLASS_ENUM_ENTRY;
+               entry->type            = enum_type;
                entry->symbol          = token.v.symbol;
                entry->source_position = token.source_position;
                next_token();
 
                if(token.type == '=') {
                        next_token();
-                       entry->init.initializer = parse_initializer(type_int);
+                       entry->init.enum_value = parse_constant_expression();
+
+                       /* TODO semantic */
                }
 
                record_declaration(entry);
@@ -1265,7 +1345,7 @@ static declaration_t *parse_enum_specifier(void)
                record_declaration(declaration);
                declaration->init.is_defined = 1;
 
-               parse_enum_entries();
+               parse_enum_entries(NULL);
                parse_attributes();
        }
 
@@ -1347,8 +1427,6 @@ typedef enum {
        SPECIFIER_VOID      = 1 << 10,
 #ifdef PROVIDE_COMPLEX
        SPECIFIER_COMPLEX   = 1 << 11,
-#endif
-#ifdef PROVIDE_IMAGINARY
        SPECIFIER_IMAGINARY = 1 << 12,
 #endif
 } specifiers_t;
@@ -1443,8 +1521,6 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                MATCH_SPECIFIER(T__Bool,      SPECIFIER_BOOL,      "_Bool")
 #ifdef PROVIDE_COMPLEX
                MATCH_SPECIFIER(T__Complex,   SPECIFIER_COMPLEX,   "_Complex")
-#endif
-#ifdef PROVIDE_IMAGINARY
                MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary")
 #endif
                case T_inline:
@@ -1603,8 +1679,6 @@ finish_specifiers:
                case SPECIFIER_LONG | SPECIFIER_DOUBLE | SPECIFIER_COMPLEX:
                        atomic_type = ATOMIC_TYPE_LONG_DOUBLE_COMPLEX;
                        break;
-#endif
-#ifdef PROVIDE_IMAGINARY
                case SPECIFIER_FLOAT | SPECIFIER_IMAGINARY:
                        atomic_type = ATOMIC_TYPE_FLOAT_IMAGINARY;
                        break;
@@ -1722,7 +1796,7 @@ static declaration_t *parse_parameters(function_type_t *type)
        if(token.type == T_IDENTIFIER) {
                symbol_t      *symbol = token.v.symbol;
                if(!is_typedef_symbol(symbol)) {
-                       /* TODO */
+                       /* TODO: K&R style C parameters */
                        parse_identifier_list();
                        return NULL;
                }
@@ -1888,19 +1962,24 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration)
 }
 
 static construct_type_t *parse_inner_declarator(declaration_t *declaration,
-               int may_be_abstract)
+               bool may_be_abstract)
 {
-       construct_type_t *result = NULL;
-       construct_type_t *last   = NULL;
+       /* construct a single linked list of construct_type_t's which describe
+        * how to construct the final declarator type */
+       construct_type_t *first = NULL;
+       construct_type_t *last  = NULL;
 
+       /* pointers */
        while(token.type == '*') {
                construct_type_t *type = parse_pointer_declarator();
-               if(last != NULL) {
-                       last->next = type;
+
+               if(last == NULL) {
+                       first = type;
+                       last  = type;
                } else {
-                       result = type;
+                       last->next = type;
+                       last       = type;
                }
-               last = type;
        }
 
        /* TODO: find out if this is correct */
@@ -1937,6 +2016,8 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
                return NULL;
        }
 
+       construct_type_t *p = last;
+
        while(true) {
                construct_type_t *type;
                switch(token.type) {
@@ -1950,27 +2031,32 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
                        goto declarator_finished;
                }
 
-               if(last != NULL) {
-                       last->next = type;
+               /* insert in the middle of the list (behind p) */
+               if(p != NULL) {
+                       type->next = p->next;
+                       p->next    = type;
                } else {
-                       result = type;
+                       type->next = first;
+                       first      = type;
+               }
+               if(last == p) {
+                       last = type;
                }
-               last = type;
        }
 
 declarator_finished:
        parse_attributes();
 
-       if(inner_types != NULL) {
-               if(last != NULL) {
-                       last->next = inner_types;
-               } else {
-                       result = inner_types;
-               }
-               last = inner_types;
+       /* append inner_types at the end of the list, we don't to set last anymore
+        * as it's not needed anymore */
+       if(last == NULL) {
+               assert(first == NULL);
+               first = inner_types;
+       } else {
+               last->next = inner_types;
        }
 
-       return result;
+       return first;
 }
 
 static type_t *construct_declarator_type(construct_type_t *construct_list,
@@ -2022,7 +2108,11 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
 
                type_t *hashed_type = typehash_insert((type_t*) type);
                if(hashed_type != type) {
-                       free_type(type);
+                       /* the function type was constructed earlier freeing it here will
+                        * destroy other types... */
+                       if(iter->type != CONSTRUCT_FUNCTION) {
+                               free_type(type);
+                       }
                        type = hashed_type;
                }
        }
@@ -2102,7 +2192,8 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
 
                declaration_t *declaration = record_declaration(ndeclaration);
 
-               type_t *type = declaration->type;
+               type_t *orig_type = declaration->type;
+               type_t *type      = skip_typeref(orig_type);
                if(type->type != TYPE_FUNCTION && declaration->is_inline) {
                        parser_print_warning_prefix_pos(declaration->source_position);
                        fprintf(stderr, "variable '%s' declared 'inline'\n",
@@ -2118,13 +2209,40 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
                                parser_error_multiple_definition(declaration, ndeclaration);
                        }
 
-                       ndeclaration->init.initializer = parse_initializer(declaration->type);
+                       initializer_t *initializer = parse_initializer(type);
+
+                       if(type->type == TYPE_ARRAY && initializer != NULL) {
+                               array_type_t       *array_type = (array_type_t*) type;
+
+                               if(array_type->size == NULL) {
+                                       const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
+
+                                       cnst->expression.type     = EXPR_CONST;
+                                       cnst->expression.datatype = type_size_t;
+
+                                       if(initializer->type == INITIALIZER_LIST) {
+                                               initializer_list_t *list
+                                                       = (initializer_list_t*) initializer;
+                                               cnst->v.int_value = list->len;
+                                       } else {
+                                               assert(initializer->type == INITIALIZER_STRING);
+                                               initializer_string_t *string
+                                                       = (initializer_string_t*) initializer;
+                                               cnst->v.int_value = strlen(string->string) + 1;
+                                       }
+
+                                       array_type->size = (expression_t*) cnst;
+                               }
+                       }
+
+
+                       ndeclaration->init.initializer = initializer;
                } else if(token.type == '{') {
-                       if(declaration->type->type != TYPE_FUNCTION) {
+                       if(type->type != TYPE_FUNCTION) {
                                parser_print_error_prefix();
-                               fprintf(stderr, "Declarator ");
-                               print_type_ext(declaration->type, declaration->symbol, NULL);
-                               fprintf(stderr, " has a body but is not a function type.\n");
+                               fprintf(stderr, "declarator '");
+                               print_type_ext(orig_type, declaration->symbol, NULL);
+                               fprintf(stderr, "' has a body but is not a function type.\n");
                                eat_block();
                                continue;
                        }
@@ -2333,7 +2451,7 @@ static expression_t *parse_int_const(void)
        const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
 
        cnst->expression.type     = EXPR_CONST;
-       cnst->expression.datatype = type_int;
+       cnst->expression.datatype = token.datatype;
        cnst->v.int_value         = token.v.intvalue;
 
        next_token();
@@ -2346,7 +2464,7 @@ static expression_t *parse_float_const(void)
        const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
 
        cnst->expression.type     = EXPR_CONST;
-       cnst->expression.datatype = type_double;
+       cnst->expression.datatype = token.datatype;
        cnst->v.float_value       = token.v.floatvalue;
 
        next_token();
@@ -2635,18 +2753,42 @@ static expression_t *parse_va_arg(void)
        return (expression_t*) expression;
 }
 
+static type_t *make_function_1_type(type_t *result_type, type_t *argument_type)
+{
+       function_parameter_t *parameter = allocate_type_zero(sizeof(parameter[0]));
+       parameter->type = argument_type;
+
+       function_type_t *type = allocate_type_zero(sizeof(type[0]));
+       type->type.type   = TYPE_FUNCTION;
+       type->result_type = result_type;
+       type->parameters  = parameter;
+
+       type_t *result = typehash_insert((type_t*) type);
+       if(result != (type_t*) type) {
+               free_type(type);
+       }
+
+       return result;
+}
+
 static expression_t *parse_builtin_symbol(void)
 {
        builtin_symbol_expression_t *expression
                = allocate_ast_zero(sizeof(expression[0]));
        expression->expression.type = EXPR_BUILTIN_SYMBOL;
 
-       /* TODO: set datatype */
-
        expression->symbol = token.v.symbol;
 
+       type_t *type;
+       switch(token.type) {
+       case T___builtin_alloca:
+               type = make_function_1_type(type_void_ptr, type_size_t);
+               break;
+       }
+
        next_token();
 
+       expression->expression.datatype = type;
        return (expression_t*) expression;
 }
 
@@ -2670,6 +2812,7 @@ static expression_t *parse_primary_expression(void)
                return parse_offsetof();
        case T___builtin_va_arg:
                return parse_va_arg();
+       case T___builtin_alloca:
        case T___builtin_expect:
        case T___builtin_va_start:
        case T___builtin_va_end:
@@ -2695,25 +2838,37 @@ static expression_t *parse_array_expression(unsigned precedence,
 
        eat('[');
 
+       expression_t *index = parse_expression();
+
        array_access_expression_t *array_access
                = allocate_ast_zero(sizeof(array_access[0]));
 
-       array_access->expression.type     = EXPR_ARRAY_ACCESS;
-       array_access->array_ref           = array_ref;
-       array_access->index               = parse_expression();
+       array_access->expression.type = EXPR_ARRAY_ACCESS;
+       array_access->array_ref       = array_ref;
+       array_access->index           = index;
+
+       type_t *type_left  = skip_typeref(array_ref->datatype);
+       type_t *type_right = skip_typeref(index->datatype);
 
-       type_t *type = array_ref->datatype;
-       if(type != NULL) {
-               if(type->type == TYPE_POINTER) {
-                       pointer_type_t *pointer           = (pointer_type_t*) type;
+       if(type_left != NULL && type_right != NULL) {
+               if(type_left->type == TYPE_POINTER) {
+                       pointer_type_t *pointer           = (pointer_type_t*) type_left;
+                       array_access->expression.datatype = pointer->points_to;
+               } else if(type_left->type == TYPE_ARRAY) {
+                       array_type_t *array_type          = (array_type_t*) type_left;
+                       array_access->expression.datatype = array_type->element_type;
+               } else if(type_right->type == TYPE_POINTER) {
+                       pointer_type_t *pointer           = (pointer_type_t*) type_right;
                        array_access->expression.datatype = pointer->points_to;
-               } else if(type->type == TYPE_ARRAY) {
-                       array_type_t *array_type          = (array_type_t*) type;
+               } else if(type_right->type == TYPE_ARRAY) {
+                       array_type_t *array_type          = (array_type_t*) type_right;
                        array_access->expression.datatype = array_type->element_type;
                } else {
                        parser_print_error_prefix();
-                       fprintf(stderr, "array access on object with non-pointer type ");
-                       print_type_quoted(type);
+                       fprintf(stderr, "array access on object with non-pointer types ");
+                       print_type_quoted(type_left);
+                       fprintf(stderr, ", ");
+                       print_type_quoted(type_right);
                        fprintf(stderr, "\n");
                }
        }
@@ -2790,16 +2945,18 @@ static expression_t *parse_select_expression(unsigned precedence,
        select->symbol   = symbol;
        next_token();
 
-       type_t *type = compound->datatype;
-       if(type == NULL)
+       type_t *orig_type = compound->datatype;
+       if(orig_type == NULL)
                return make_invalid_expression();
 
+       type_t *type = skip_typeref(orig_type);
+
        type_t *type_left = type;
        if(is_pointer) {
                if(type->type != TYPE_POINTER) {
                        parser_print_error_prefix();
                        fprintf(stderr, "left hand side of '->' is not a pointer, but ");
-                       print_type_quoted(type);
+                       print_type_quoted(orig_type);
                        fputc('\n', stderr);
                        return make_invalid_expression();
                }
@@ -2857,21 +3014,23 @@ static expression_t *parse_call_expression(unsigned precedence,
        call->function          = expression;
 
        function_type_t *function_type;
-       type_t          *type = expression->datatype;
+       type_t          *orig_type     = expression->datatype;
+       type_t          *type          = skip_typeref(orig_type);
+
+       if(type->type == TYPE_POINTER) {
+               pointer_type_t *pointer_type = (pointer_type_t*) type;
+
+               type = skip_typeref(pointer_type->points_to);
+       }
        if (type->type == TYPE_FUNCTION) {
                function_type             = (function_type_t*) type;
                call->expression.datatype = function_type->result_type;
-       } else if (type->type == TYPE_POINTER &&
-                  ((pointer_type_t*)type)->points_to->type == TYPE_FUNCTION) {
-               pointer_type_t *const ptr_type = (pointer_type_t*)type;
-               function_type                  = (function_type_t*)ptr_type->points_to;
-               call->expression.datatype      = function_type->result_type;
        } else {
                parser_print_error_prefix();
                fputs("called object '", stderr);
                print_expression(expression);
                fputs("' (type ", stderr);
-               print_type_quoted(type);
+               print_type_quoted(orig_type);
                fputs(") is not a function\n", stderr);
 
                function_type             = NULL;
@@ -2959,14 +3118,16 @@ static expression_t *parse_conditional_expression(unsigned precedence,
        conditional_expression_t *conditional
                = allocate_ast_zero(sizeof(conditional[0]));
        conditional->expression.type = EXPR_CONDITIONAL;
-       conditional->condition = expression;
+       conditional->condition       = expression;
 
        /* 6.5.15.2 */
        type_t *condition_type_orig = conditional->condition->datatype;
-       type_t *condition_type      = skip_typeref(condition_type_orig);
-       if(condition_type != NULL && !is_type_scalar(condition_type)) {
-               type_error("expected a scalar type", expression->source_position,
-                          condition_type_orig);
+       if(condition_type_orig != NULL) {
+               type_t *condition_type      = skip_typeref(condition_type_orig);
+               if(condition_type != NULL && !is_type_scalar(condition_type)) {
+                       type_error("expected a scalar type", expression->source_position,
+                                          condition_type_orig);
+               }
        }
 
        expression_t *const t_expr = parse_expression();
@@ -3408,8 +3569,7 @@ static void semantic_comparison(binary_expression_t *expression)
                expression->left = create_implicit_cast(left, type_right);
        } else {
                type_error_incompatible("invalid operands in comparison",
-                                       expression->expression.source_position,
-                                       type_left, type_right);
+                                       token.source_position, type_left, type_right);
        }
        expression->expression.datatype = type_int;
 }
@@ -3502,16 +3662,31 @@ static void semantic_logical_op(binary_expression_t *expression)
 
 static void semantic_binexpr_assign(binary_expression_t *expression)
 {
-       expression_t *left       = expression->left;
-       type_t       *type_left  = left->datatype;
+       expression_t *left           = expression->left;
+       type_t       *orig_type_left = left->datatype;
+
+       if(orig_type_left == NULL)
+               return;
+
+       type_t *type_left = skip_typeref(orig_type_left);
 
        if (type_left->type == TYPE_ARRAY) {
                parse_error("Cannot assign to arrays.");
-       } else if (type_left != NULL) {
-               semantic_assign(type_left, &expression->right, "assignment");
+               return;
        }
 
-       expression->expression.datatype = type_left;
+       if(type_left->qualifiers & TYPE_QUALIFIER_CONST) {
+               parser_print_error_prefix();
+               fprintf(stderr, "assignment to readonly location '");
+               print_expression(left);
+               fprintf(stderr, "' (type ");
+               print_type_quoted(orig_type_left);
+               fprintf(stderr, ")\n");
+       }
+
+       semantic_assign(orig_type_left, &expression->right, "assignment");
+
+       expression->expression.datatype = orig_type_left;
 }
 
 static void semantic_comma(binary_expression_t *expression)
@@ -3558,7 +3733,6 @@ CREATE_BINEXPR_PARSER('|', BINEXPR_BITWISE_OR,     semantic_binexpr_arithmetic,
 CREATE_BINEXPR_PARSER('^', BINEXPR_BITWISE_XOR,    semantic_binexpr_arithmetic, 1)
 CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND,  semantic_logical_op, 1)
 CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR, semantic_logical_op, 1)
-/* TODO shift has a bit special semantic */
 CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT,
                       semantic_shift_op, 1)
 CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT,
@@ -3745,7 +3919,7 @@ static statement_t *parse_case_statement(void)
        label->expression = parse_expression();
 
        expect(':');
-       label->statement.next = parse_statement();
+       label->label_statement = parse_statement();
 
        return (statement_t*) label;
 }
@@ -3759,7 +3933,7 @@ static statement_t *parse_default_statement(void)
        label->statement.source_position = token.source_position;
 
        expect(':');
-       label->statement.next = parse_statement();
+       label->label_statement = parse_statement();
 
        return (statement_t*) label;
 }
@@ -4271,6 +4445,7 @@ void init_parser(void)
        type_ptrdiff_t   = make_atomic_type(ATOMIC_TYPE_LONG, 0);
        type_const_char  = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
        type_void        = make_atomic_type(ATOMIC_TYPE_VOID, 0);
+       type_void_ptr    = make_pointer_type(type_void, 0);
        type_string      = make_pointer_type(type_const_char, 0);
 }