always prefere complete over incomplete types when mergin declarations
[cparser] / parser.c
index 6acf52b..97252da 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -44,14 +44,16 @@ static token_t             lookahead_buffer[MAX_LOOKAHEAD];
 static int                 lookahead_bufpos;
 static stack_entry_t      *environment_stack = NULL;
 static stack_entry_t      *label_stack       = NULL;
-static context_t          *global_context    = NULL;
-static context_t          *context           = NULL;
+static scope_t            *global_scope      = NULL;
+static scope_t            *scope             = NULL;
 static declaration_t      *last_declaration  = NULL;
 static declaration_t      *current_function  = NULL;
 static switch_statement_t *current_switch    = NULL;
 static statement_t        *current_loop      = NULL;
 static goto_statement_t   *goto_first        = NULL;
 static goto_statement_t   *goto_last         = NULL;
+static label_statement_t  *label_first       = NULL;
+static label_statement_t  *label_last        = NULL;
 static struct obstack  temp_obst;
 
 /** The current source position. */
@@ -138,7 +140,7 @@ static void *allocate_ast_zero(size_t size)
 
 static declaration_t *allocate_declaration_zero(void)
 {
-       declaration_t *declaration = allocate_ast_zero(sizeof(*allocate_declaration_zero()));
+       declaration_t *declaration = allocate_ast_zero(sizeof(declaration_t));
        declaration->type = type_error_type;
        return declaration;
 }
@@ -204,7 +206,8 @@ static size_t get_expression_struct_size(expression_kind_t kind)
                [EXPR_CONDITIONAL]         = sizeof(conditional_expression_t),
                [EXPR_SELECT]              = sizeof(select_expression_t),
                [EXPR_ARRAY_ACCESS]        = sizeof(array_access_expression_t),
-               [EXPR_SIZEOF]              = sizeof(sizeof_expression_t),
+               [EXPR_SIZEOF]              = sizeof(typeprop_expression_t),
+               [EXPR_ALIGNOF]             = sizeof(typeprop_expression_t),
                [EXPR_CLASSIFY_TYPE]       = sizeof(classify_type_expression_t),
                [EXPR_FUNCTION]            = sizeof(string_literal_expression_t),
                [EXPR_PRETTY_FUNCTION]     = sizeof(string_literal_expression_t),
@@ -236,8 +239,8 @@ static expression_t *allocate_expression_zero(expression_kind_t kind)
        size_t        size = get_expression_struct_size(kind);
        expression_t *res  = allocate_ast_zero(size);
 
-       res->base.kind     = kind;
-       res->base.datatype = type_error_type;
+       res->base.kind = kind;
+       res->base.type = type_error_type;
        return res;
 }
 
@@ -487,11 +490,11 @@ static void eat_paren(void)
     }                                              \
     next_token();
 
-static void set_context(context_t *new_context)
+static void set_scope(scope_t *new_scope)
 {
-       context = new_context;
+       scope = new_scope;
 
-       last_declaration = new_context->declarations;
+       last_declaration = new_scope->declarations;
        if(last_declaration != NULL) {
                while(last_declaration->next != NULL) {
                        last_declaration = last_declaration->next;
@@ -558,13 +561,13 @@ static void stack_push(stack_entry_t **stack_ptr, declaration_t *declaration)
 static void environment_push(declaration_t *declaration)
 {
        assert(declaration->source_position.input_name != NULL);
-       assert(declaration->parent_context != NULL);
+       assert(declaration->parent_scope != NULL);
        stack_push(&environment_stack, declaration);
 }
 
 static void label_push(declaration_t *declaration)
 {
-       declaration->parent_context = &current_function->context;
+       declaration->parent_scope = &current_function->scope;
        stack_push(&label_stack, declaration);
 }
 
@@ -664,8 +667,8 @@ static expression_t *create_cast_expression(expression_t *expression,
 {
        expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST_IMPLICIT);
 
-       cast->unary.value   = expression;
-       cast->base.datatype = dest_type;
+       cast->unary.value = expression;
+       cast->base.type   = dest_type;
 
        return cast;
 }
@@ -686,7 +689,7 @@ static bool is_null_pointer_constant(const expression_t *expression)
        if (expression->kind != EXPR_CONST)
                return false;
 
-       type_t *const type = skip_typeref(expression->base.datatype);
+       type_t *const type = skip_typeref(expression->base.type);
        if (!is_type_integer(type))
                return false;
 
@@ -702,7 +705,7 @@ static bool is_null_pointer_constant(const expression_t *expression)
 static expression_t *create_implicit_cast(expression_t *expression,
                                           type_t *dest_type)
 {
-       type_t *const source_type = expression->base.datatype;
+       type_t *const source_type = expression->base.type;
 
        if (source_type == dest_type)
                return expression;
@@ -715,7 +718,7 @@ static type_t *semantic_assign(type_t *orig_type_left,
                             const expression_t *const right,
                             const char *context)
 {
-       type_t *const orig_type_right = right->base.datatype;
+       type_t *const orig_type_right = right->base.type;
        type_t *const type_left       = skip_typeref(orig_type_left);
        type_t *const type_right      = skip_typeref(orig_type_right);
 
@@ -945,7 +948,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 */
-       type_t *const expr_type = expression->base.datatype;
+       type_t *const expr_type = expression->base.type;
        if (is_type_array(type) && expr_type->kind == TYPE_POINTER) {
                array_type_t *const array_type   = &type->array;
                type_t       *const element_type = skip_typeref(array_type->element_type);
@@ -1102,7 +1105,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                }
        } else {
                assert(is_type_compound(type));
-               context_t *const context = &type->compound.declaration->context;
+               scope_t *const scope = &type->compound.declaration->scope;
 
                if(token.type == '[') {
                        errorf(HERE,
@@ -1111,7 +1114,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        skip_designator();
                }
 
-               declaration_t *first = context->declarations;
+               declaration_t *first = scope->declarations;
                if(first == NULL)
                        return NULL;
                type_t *first_type = first->type;
@@ -1193,7 +1196,7 @@ static initializer_t *parse_initializer(type_t *const orig_type)
                if(initializer == NULL) {
                        errorf(HERE,
                                "initializer expression '%E' of type '%T' is incompatible with type '%T'",
-                               expression, expression->base.datatype, orig_type);
+                               expression, expression->base.type, orig_type);
                }
                return initializer;
        }
@@ -1262,7 +1265,7 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
                        (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION);
                declaration->source_position = token.source_position;
                declaration->symbol          = symbol;
-               declaration->parent_context  = context;
+               declaration->parent_scope  = scope;
                if (symbol != NULL) {
                        environment_push(declaration);
                }
@@ -1274,19 +1277,19 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
                        assert(symbol != NULL);
                        errorf(HERE, "multiple definition of '%s %Y'",
                               is_struct ? "struct" : "union", symbol);
-                       declaration->context.declarations = NULL;
+                       declaration->scope.declarations = NULL;
                }
                declaration->init.is_defined = true;
 
-               int         top          = environment_top();
-               context_t  *last_context = context;
-               set_context(&declaration->context);
+               int       top        = environment_top();
+               scope_t  *last_scope = scope;
+               set_scope(&declaration->scope);
 
                parse_compound_type_entries();
                parse_attributes();
 
-               assert(context == &declaration->context);
-               set_context(last_context);
+               assert(scope == &declaration->scope);
+               set_scope(last_scope);
                environment_pop_to(top);
        }
 
@@ -1360,7 +1363,7 @@ static type_t *parse_enum_specifier(void)
                declaration->namespc         = NAMESPACE_ENUM;
                declaration->source_position = token.source_position;
                declaration->symbol          = symbol;
-               declaration->parent_context  = context;
+               declaration->parent_scope  = scope;
        }
 
        type_t *const type      = allocate_type_zero(TYPE_ENUM);
@@ -1420,7 +1423,7 @@ restart:
                        type = parse_typename();
                } else {
                        expression = parse_expression();
-                       type       = expression->base.datatype;
+                       type       = expression->base.type;
                }
                break;
 
@@ -1430,7 +1433,7 @@ restart:
 
        default:
                expression = parse_expression();
-               type       = expression->base.datatype;
+               type       = expression->base.type;
                break;
        }
 
@@ -1802,6 +1805,7 @@ static declaration_t *parse_identifier_list(void)
        declaration_t *last_declaration = NULL;
        do {
                declaration_t *const declaration = allocate_declaration_zero();
+               declaration->type            = NULL; /* a K&R parameter list has no types, yet */
                declaration->source_position = token.source_position;
                declaration->symbol          = token.v.symbol;
                next_token();
@@ -2020,7 +2024,7 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration)
 
        declaration_t *parameters = parse_parameters(&type->function);
        if(declaration != NULL) {
-               declaration->context.declarations = parameters;
+               declaration->scope.declarations = parameters;
        }
 
        construct_function_type_t *construct_function_type =
@@ -2243,12 +2247,62 @@ static declaration_t *append_declaration(declaration_t* const declaration)
        if (last_declaration != NULL) {
                last_declaration->next = declaration;
        } else {
-               context->declarations = declaration;
+               scope->declarations = declaration;
        }
        last_declaration = declaration;
        return declaration;
 }
 
+/**
+ * Check if the declaration of main is suspicious.  main should be a
+ * function with external linkage, returning int, taking either zero
+ * arguments, two, or three arguments of appropriate types, ie.
+ *
+ * int main([ int argc, char **argv [, char **env ] ]).
+ *
+ * @param decl    the declaration to check
+ * @param type    the function type of the declaration
+ */
+static void check_type_of_main(const declaration_t *const decl, const function_type_t *const func_type)
+{
+       if (decl->storage_class == STORAGE_CLASS_STATIC) {
+               warningf(decl->source_position, "'main' is normally a non-static function");
+       }
+       if (skip_typeref(func_type->return_type) != type_int) {
+               warningf(decl->source_position, "return type of 'main' should be 'int', but is '%T'", func_type->return_type);
+       }
+       const function_parameter_t *parm = func_type->parameters;
+       if (parm != NULL) {
+               type_t *const first_type = parm->type;
+               if (!types_compatible(skip_typeref(first_type), type_int)) {
+                       warningf(decl->source_position, "first argument of 'main' should be 'int', but is '%T'", first_type);
+               }
+               parm = parm->next;
+               if (parm != NULL) {
+                       type_t *const second_type = parm->type;
+                       if (!types_compatible(skip_typeref(second_type), type_char_ptr_ptr)) {
+                               warningf(decl->source_position, "second argument of 'main' should be 'char**', but is '%T'", second_type);
+                       }
+                       parm = parm->next;
+                       if (parm != NULL) {
+                               type_t *const third_type = parm->type;
+                               if (!types_compatible(skip_typeref(third_type), type_char_ptr_ptr)) {
+                                       warningf(decl->source_position, "third argument of 'main' should be 'char**', but is '%T'", third_type);
+                               }
+                               parm = parm->next;
+                               if (parm != NULL) {
+                                       warningf(decl->source_position, "'main' takes only zero, two or three arguments");
+                               }
+                       }
+               } else {
+                       warningf(decl->source_position, "'main' takes only zero, two or three arguments");
+               }
+       }
+}
+
+/**
+ * Check if a symbol is the equal to "main".
+ */
 static bool is_sym_main(const symbol_t *const sym)
 {
        return strcmp(sym->string, "main") == 0;
@@ -2261,36 +2315,50 @@ static declaration_t *internal_record_declaration(
        const symbol_t *const symbol  = declaration->symbol;
        const namespace_t     namespc = (namespace_t)declaration->namespc;
 
-       const type_t *const type = skip_typeref(declaration->type);
+       type_t *const orig_type = declaration->type;
+       type_t *const type      = skip_typeref(orig_type);
        if (is_type_function(type) &&
                        type->function.unspecified_parameters &&
                        warning.strict_prototypes) {
                warningf(declaration->source_position,
                         "function declaration '%#T' is not a prototype",
-                        type, declaration->symbol);
+                        orig_type, declaration->symbol);
+       }
+
+       if (is_function_definition && warning.main && is_sym_main(symbol)) {
+               check_type_of_main(declaration, &type->function);
        }
 
        declaration_t *const previous_declaration = get_declaration(symbol, namespc);
        assert(declaration != previous_declaration);
        if (previous_declaration != NULL) {
-               if (previous_declaration->parent_context == context) {
+               if (previous_declaration->parent_scope == scope) {
                        /* can happen for K&R style declarations */
                        if(previous_declaration->type == NULL) {
                                previous_declaration->type = declaration->type;
                        }
 
-                       const type_t *const prev_type = skip_typeref(previous_declaration->type);
+                       const type_t *prev_type = skip_typeref(previous_declaration->type);
                        if (!types_compatible(type, prev_type)) {
                                errorf(declaration->source_position,
-                                       "declaration '%#T' is incompatible with previous declaration '%#T'",
-                                       type, symbol, previous_declaration->type, symbol);
-                               errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol);
+                                      "declaration '%#T' is incompatible with "
+                                      "previous declaration '%#T'",
+                                      orig_type, symbol, previous_declaration->type, symbol);
+                               errorf(previous_declaration->source_position,
+                                      "previous declaration of '%Y' was here", symbol);
                        } else {
-                               unsigned old_storage_class = previous_declaration->storage_class;
+                               unsigned old_storage_class
+                                       = previous_declaration->storage_class;
                                unsigned new_storage_class = declaration->storage_class;
 
-                               /* pretend no storage class means extern for function declarations
-                                * (except if the previous declaration is neither none nor extern) */
+                               if(is_type_incomplete(prev_type)) {
+                                       previous_declaration->type = type;
+                                       prev_type                  = type;
+                               }
+
+                               /* pretend no storage class means extern for function
+                                * declarations (except if the previous declaration is neither
+                                * none nor extern) */
                                if (is_type_function(type)) {
                                        switch (old_storage_class) {
                                                case STORAGE_CLASS_NONE:
@@ -2301,7 +2369,9 @@ static declaration_t *internal_record_declaration(
                                                                if (warning.missing_prototypes &&
                                                                    prev_type->function.unspecified_parameters &&
                                                                    !is_sym_main(symbol)) {
-                                                                       warningf(declaration->source_position, "no previous prototype for '%#T'", type, symbol);
+                                                                       warningf(declaration->source_position,
+                                                                                "no previous prototype for '%#T'",
+                                                                                orig_type, symbol);
                                                                }
                                                        } else if (new_storage_class == STORAGE_CLASS_NONE) {
                                                                new_storage_class = STORAGE_CLASS_EXTERN;
@@ -2316,14 +2386,20 @@ static declaration_t *internal_record_declaration(
                                                new_storage_class == STORAGE_CLASS_EXTERN) {
 warn_redundant_declaration:
                                        if (warning.redundant_decls) {
-                                               warningf(declaration->source_position, "redundant declaration for '%Y'", symbol);
-                                               warningf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol);
+                                               warningf(declaration->source_position,
+                                                        "redundant declaration for '%Y'", symbol);
+                                               warningf(previous_declaration->source_position,
+                                                        "previous declaration of '%Y' was here",
+                                                        symbol);
                                        }
                                } else if (current_function == NULL) {
                                        if (old_storage_class != STORAGE_CLASS_STATIC &&
                                                        new_storage_class == STORAGE_CLASS_STATIC) {
-                                               errorf(declaration->source_position, "static declaration of '%Y' follows non-static declaration", symbol);
-                                               errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol);
+                                               errorf(declaration->source_position,
+                                                      "static declaration of '%Y' follows non-static declaration",
+                                                      symbol);
+                                               errorf(previous_declaration->source_position,
+                                                      "previous declaration of '%Y' was here", symbol);
                                        } else {
                                                if (old_storage_class != STORAGE_CLASS_EXTERN && !is_function_definition) {
                                                        goto warn_redundant_declaration;
@@ -2334,36 +2410,45 @@ warn_redundant_declaration:
                                        }
                                } else {
                                        if (old_storage_class == new_storage_class) {
-                                               errorf(declaration->source_position, "redeclaration of '%Y'", symbol);
+                                               errorf(declaration->source_position,
+                                                      "redeclaration of '%Y'", symbol);
                                        } else {
-                                               errorf(declaration->source_position, "redeclaration of '%Y' with different linkage", symbol);
+                                               errorf(declaration->source_position,
+                                                      "redeclaration of '%Y' with different linkage",
+                                                      symbol);
                                        }
-                                       errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol);
+                                       errorf(previous_declaration->source_position,
+                                              "previous declaration of '%Y' was here", symbol);
                                }
                        }
                        return previous_declaration;
                }
-       } else if (is_function_definition &&
-                       declaration->storage_class != STORAGE_CLASS_STATIC) {
-               if (warning.missing_prototypes && !is_sym_main(symbol)) {
-                       warningf(declaration->source_position, "no previous prototype for '%#T'", type, symbol);
-               } else if (warning.missing_declarations && !is_sym_main(symbol)) {
-                       warningf(declaration->source_position, "no previous declaration for '%#T'", type, symbol);
+       } else if (is_function_definition) {
+               if (declaration->storage_class != STORAGE_CLASS_STATIC) {
+                       if (warning.missing_prototypes && !is_sym_main(symbol)) {
+                               warningf(declaration->source_position,
+                                        "no previous prototype for '%#T'", orig_type, symbol);
+                       } else if (warning.missing_declarations && !is_sym_main(symbol)) {
+                               warningf(declaration->source_position,
+                                        "no previous declaration for '%#T'", orig_type,
+                                        symbol);
+                       }
                }
        } else if (warning.missing_declarations &&
-           context == global_context &&
-           declaration->storage_class != STORAGE_CLASS_STATIC &&
-           declaration->storage_class != STORAGE_CLASS_TYPEDEF &&
-           declaration->storage_class != STORAGE_CLASS_ENUM_ENTRY &&
-           declaration->storage_class != STORAGE_CLASS_THREAD_STATIC) {
-               warningf(declaration->source_position, "no previous declaration for '%#T'", type, symbol);
+           scope == global_scope &&
+           !is_type_function(type) && (
+             declaration->storage_class == STORAGE_CLASS_NONE ||
+             declaration->storage_class == STORAGE_CLASS_THREAD
+           )) {
+               warningf(declaration->source_position,
+                        "no previous declaration for '%#T'", orig_type, symbol);
        }
 
-       assert(declaration->parent_context == NULL);
+       assert(declaration->parent_scope == NULL);
        assert(declaration->symbol != NULL);
-       assert(context != NULL);
+       assert(scope != NULL);
 
-       declaration->parent_context = context;
+       declaration->parent_scope = scope;
 
        environment_push(declaration);
        return append_declaration(declaration);
@@ -2428,7 +2513,7 @@ static void parse_init_declarator_rest(declaration_t *declaration)
                if(array_type->size == NULL) {
                        expression_t *cnst = allocate_expression_zero(EXPR_CONST);
 
-                       cnst->base.datatype = type_size_t;
+                       cnst->base.type = type_size_t;
 
                        switch (initializer->kind) {
                                case INITIALIZER_LIST: {
@@ -2544,7 +2629,7 @@ static declaration_t *finished_kr_declaration(declaration_t *declaration)
 
        declaration_t *previous_declaration = get_declaration(symbol, namespc);
        if(previous_declaration == NULL ||
-                       previous_declaration->parent_context != context) {
+                       previous_declaration->parent_scope != scope) {
                errorf(HERE, "expected declaration of a function parameter, found '%Y'",
                       symbol);
                return declaration;
@@ -2553,7 +2638,7 @@ static declaration_t *finished_kr_declaration(declaration_t *declaration)
        if(previous_declaration->type == NULL) {
                previous_declaration->type           = declaration->type;
                previous_declaration->storage_class  = declaration->storage_class;
-               previous_declaration->parent_context = context;
+               previous_declaration->parent_scope = scope;
                return previous_declaration;
        } else {
                return record_declaration(declaration);
@@ -2584,14 +2669,14 @@ static void parse_kr_declaration_list(declaration_t *declaration)
                return;
 
        /* push function parameters */
-       int         top          = environment_top();
-       context_t  *last_context = context;
-       set_context(&declaration->context);
+       int       top        = environment_top();
+       scope_t  *last_scope = scope;
+       set_scope(&declaration->scope);
 
-       declaration_t *parameter = declaration->context.declarations;
+       declaration_t *parameter = declaration->scope.declarations;
        for( ; parameter != NULL; parameter = parameter->next) {
-               assert(parameter->parent_context == NULL);
-               parameter->parent_context = context;
+               assert(parameter->parent_scope == NULL);
+               parameter->parent_scope = scope;
                environment_push(parameter);
        }
 
@@ -2601,8 +2686,8 @@ static void parse_kr_declaration_list(declaration_t *declaration)
        }
 
        /* pop function parameters */
-       assert(context == &declaration->context);
-       set_context(last_context);
+       assert(scope == &declaration->scope);
+       set_scope(last_scope);
        environment_pop_to(top);
 
        /* update function type */
@@ -2612,7 +2697,7 @@ static void parse_kr_declaration_list(declaration_t *declaration)
        function_parameter_t *parameters     = NULL;
        function_parameter_t *last_parameter = NULL;
 
-       declaration_t *parameter_declaration = declaration->context.declarations;
+       declaration_t *parameter_declaration = declaration->scope.declarations;
        for( ; parameter_declaration != NULL;
                        parameter_declaration = parameter_declaration->next) {
                type_t *parameter_type = parameter_declaration->type;
@@ -2655,29 +2740,76 @@ static void parse_kr_declaration_list(declaration_t *declaration)
        declaration->type = type;
 }
 
+static bool first_err = true;
+
+/**
+ * When called with first_err set, prints the name of the current function,
+ * else does noting.
+ */
+static void print_in_function(void) {
+       if (first_err) {
+               first_err = false;
+               diagnosticf("%s: In function '%Y':\n",
+                       current_function->source_position.input_name,
+                       current_function->symbol);
+       }
+}
+
 /**
  * Check if all labels are defined in the current function.
+ * Check if all labels are used in the current function.
  */
-static void check_for_missing_labels(void)
+static void check_labels(void)
 {
-       bool first_err = true;
        for (const goto_statement_t *goto_statement = goto_first;
-            goto_statement != NULL;
-            goto_statement = goto_statement->next) {
-                const declaration_t *label = goto_statement->label;
-
-                if (label->source_position.input_name == NULL) {
-                        if (first_err) {
-                                first_err = false;
-                                diagnosticf("%s: In function '%Y':\n",
-                                        current_function->source_position.input_name,
-                                        current_function->symbol);
-                        }
-                        errorf(goto_statement->statement.source_position,
-                                "label '%Y' used but not defined", label->symbol);
+           goto_statement != NULL;
+           goto_statement = goto_statement->next) {
+               declaration_t *label = goto_statement->label;
+
+               label->used = true;
+               if (label->source_position.input_name == NULL) {
+                       print_in_function();
+                       errorf(goto_statement->base.source_position,
+                              "label '%Y' used but not defined", label->symbol);
                 }
        }
        goto_first = goto_last = NULL;
+
+       if (warning.unused_label) {
+               for (const label_statement_t *label_statement = label_first;
+                        label_statement != NULL;
+                        label_statement = label_statement->next) {
+                       const declaration_t *label = label_statement->label;
+
+                       if (! label->used) {
+                               print_in_function();
+                               warningf(label_statement->base.source_position,
+                                       "label '%Y' defined but not used", label->symbol);
+                       }
+               }
+       }
+       label_first = label_last = NULL;
+}
+
+/**
+ * Check declarations of current_function for unused entities.
+ */
+static void check_declarations(void)
+{
+       if (warning.unused_parameter) {
+               const scope_t *scope = &current_function->scope;
+
+               const declaration_t *parameter = scope->declarations;
+               for (; parameter != NULL; parameter = parameter->next) {
+                       if (! parameter->used) {
+                               print_in_function();
+                               warningf(parameter->source_position,
+                                       "unused parameter '%Y'", parameter->symbol);
+                       }
+               }
+       }
+       if (warning.unused_variable) {
+       }
 }
 
 static void parse_external_declaration(void)
@@ -2740,23 +2872,23 @@ static void parse_external_declaration(void)
 
        declaration_t *const declaration = record_function_definition(ndeclaration);
        if(ndeclaration != declaration) {
-               declaration->context = ndeclaration->context;
+               declaration->scope = ndeclaration->scope;
        }
        type = skip_typeref(declaration->type);
 
-       /* push function parameters and switch context */
-       int         top          = environment_top();
-       context_t  *last_context = context;
-       set_context(&declaration->context);
+       /* push function parameters and switch scope */
+       int       top        = environment_top();
+       scope_t  *last_scope = scope;
+       set_scope(&declaration->scope);
 
-       declaration_t *parameter = declaration->context.declarations;
+       declaration_t *parameter = declaration->scope.declarations;
        for( ; parameter != NULL; parameter = parameter->next) {
-               if(parameter->parent_context == &ndeclaration->context) {
-                       parameter->parent_context = context;
+               if(parameter->parent_scope == &ndeclaration->scope) {
+                       parameter->parent_scope = scope;
                }
-               assert(parameter->parent_context == NULL
-                               || parameter->parent_context == context);
-               parameter->parent_context = context;
+               assert(parameter->parent_scope == NULL
+                               || parameter->parent_scope == scope);
+               parameter->parent_scope = scope;
                environment_push(parameter);
        }
 
@@ -2771,7 +2903,9 @@ static void parse_external_declaration(void)
                current_function                    = declaration;
 
                declaration->init.statement = parse_compound_statement();
-               check_for_missing_labels();
+               first_err = true;
+               check_labels();
+               check_declarations();
 
                assert(current_function == declaration);
                current_function = old_current_function;
@@ -2779,8 +2913,8 @@ static void parse_external_declaration(void)
        }
 
 end_of_parse_external_declaration:
-       assert(context == &declaration->context);
-       set_context(last_context);
+       assert(scope == &declaration->scope);
+       set_scope(last_scope);
        environment_pop_to(top);
 }
 
@@ -2913,9 +3047,9 @@ static expression_t *expected_expression_error(void)
  */
 static expression_t *parse_string_const(void)
 {
-       expression_t *cnst  = allocate_expression_zero(EXPR_STRING_LITERAL);
-       cnst->base.datatype = type_string;
-       cnst->string.value  = parse_string_literals();
+       expression_t *cnst = allocate_expression_zero(EXPR_STRING_LITERAL);
+       cnst->base.type    = type_char_ptr;
+       cnst->string.value = parse_string_literals();
 
        return cnst;
 }
@@ -2926,8 +3060,8 @@ static expression_t *parse_string_const(void)
 static expression_t *parse_wide_string_const(void)
 {
        expression_t *const cnst = allocate_expression_zero(EXPR_WIDE_STRING_LITERAL);
-       cnst->base.datatype      = type_wchar_t_ptr;
-       cnst->wide_string.value  = token.v.wide_string; /* TODO concatenate */
+       cnst->base.type         = type_wchar_t_ptr;
+       cnst->wide_string.value = token.v.wide_string; /* TODO concatenate */
        next_token();
        return cnst;
 }
@@ -2938,7 +3072,7 @@ static expression_t *parse_wide_string_const(void)
 static expression_t *parse_int_const(void)
 {
        expression_t *cnst       = allocate_expression_zero(EXPR_CONST);
-       cnst->base.datatype      = token.datatype;
+       cnst->base.type          = token.datatype;
        cnst->conste.v.int_value = token.v.intvalue;
 
        next_token();
@@ -2952,7 +3086,7 @@ static expression_t *parse_int_const(void)
 static expression_t *parse_float_const(void)
 {
        expression_t *cnst         = allocate_expression_zero(EXPR_CONST);
-       cnst->base.datatype        = token.datatype;
+       cnst->base.type            = token.datatype;
        cnst->conste.v.float_value = token.v.floatvalue;
 
        next_token();
@@ -2977,18 +3111,18 @@ static declaration_t *create_implicit_function(symbol_t *symbol,
        declaration->type            = type;
        declaration->symbol          = symbol;
        declaration->source_position = source_position;
-       declaration->parent_context  = global_context;
+       declaration->parent_scope  = global_scope;
 
-       context_t *old_context = context;
-       set_context(global_context);
+       scope_t *old_scope = scope;
+       set_scope(global_scope);
 
        environment_push(declaration);
-       /* prepend the declaration to the global declarations list */
-       declaration->next     = context->declarations;
-       context->declarations = declaration;
+       /* prepends the declaration to the global declarations list */
+       declaration->next   = scope->declarations;
+       scope->declarations = declaration;
 
-       assert(context == global_context);
-       set_context(old_context);
+       assert(scope == global_scope);
+       set_scope(old_scope);
 
        return declaration;
 }
@@ -3030,11 +3164,11 @@ static type_t *get_builtin_symbol_type(symbol_t *symbol)
        case T___builtin_alloca:
                return make_function_1_type(type_void_ptr, type_size_t);
        case T___builtin_nan:
-               return make_function_1_type(type_double, type_string);
+               return make_function_1_type(type_double, type_char_ptr);
        case T___builtin_nanf:
-               return make_function_1_type(type_float, type_string);
+               return make_function_1_type(type_float, type_char_ptr);
        case T___builtin_nand:
-               return make_function_1_type(type_long_double, type_string);
+               return make_function_1_type(type_long_double, type_char_ptr);
        case T___builtin_va_end:
                return make_function_1_type(type_void, type_valist);
        default:
@@ -3077,7 +3211,7 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
 
                case EXPR_UNARY_DEREFERENCE: {
                        const expression_t *const value = expression->unary.value;
-                       type_t             *const type  = skip_typeref(value->base.datatype);
+                       type_t             *const type  = skip_typeref(value->base.type);
                        assert(is_type_pointer(type));
                        return type->pointer.points_to;
                }
@@ -3086,8 +3220,8 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
                        return get_builtin_symbol_type(expression->builtin_symbol.symbol);
 
                case EXPR_ARRAY_ACCESS: {
-                       const expression_t *const array_ref = expression->array_access.array_ref;
-                       type_t             *const type_left = skip_typeref(array_ref->base.datatype);
+                       const expression_t *array_ref = expression->array_access.array_ref;
+                       type_t             *type_left = skip_typeref(array_ref->base.type);
                        if (!is_type_valid(type_left))
                                return type_left;
                        assert(is_type_pointer(type_left));
@@ -3097,7 +3231,7 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
                default: break;
        }
 
-       return expression->base.datatype;
+       return expression->base.type;
 }
 
 static expression_t *parse_reference(void)
@@ -3134,8 +3268,11 @@ static expression_t *parse_reference(void)
         * code to revert this! */
        type = automatic_type_conversion(type);
 
-       ref->declaration         = declaration;
-       ref->expression.datatype = type;
+       ref->declaration = declaration;
+       ref->base.type   = type;
+
+       /* this declaration is used */
+       declaration->used = true;
 
        return expression;
 }
@@ -3160,8 +3297,8 @@ static expression_t *parse_cast(void)
 
        check_cast_allowed(value, type);
 
-       cast->base.datatype = type;
-       cast->unary.value   = value;
+       cast->base.type   = type;
+       cast->unary.value = value;
 
        return cast;
 }
@@ -3182,12 +3319,12 @@ static expression_t *parse_statement_expression(void)
                        stmt = stmt->base.next;
 
                if (stmt->kind == STATEMENT_EXPRESSION) {
-                       type = stmt->expression.expression->base.datatype;
+                       type = stmt->expression.expression->base.type;
                }
        } else {
                warningf(expression->base.source_position, "empty statement expression ({})");
        }
-       expression->base.datatype = type;
+       expression->base.type = type;
 
        expect(')');
 
@@ -3227,13 +3364,10 @@ static expression_t *parse_function_keyword(void)
                errorf(HERE, "'__func__' used outside of a function");
        }
 
-       string_literal_expression_t *expression
-               = allocate_ast_zero(sizeof(expression[0]));
+       expression_t *expression = allocate_expression_zero(EXPR_FUNCTION);
+       expression->base.type    = type_char_ptr;
 
-       expression->expression.kind     = EXPR_FUNCTION;
-       expression->expression.datatype = type_string;
-
-       return (expression_t*) expression;
+       return expression;
 }
 
 static expression_t *parse_pretty_function_keyword(void)
@@ -3245,13 +3379,10 @@ static expression_t *parse_pretty_function_keyword(void)
                errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function");
        }
 
-       string_literal_expression_t *expression
-               = allocate_ast_zero(sizeof(expression[0]));
+       expression_t *expression = allocate_expression_zero(EXPR_PRETTY_FUNCTION);
+       expression->base.type    = type_char_ptr;
 
-       expression->expression.kind     = EXPR_PRETTY_FUNCTION;
-       expression->expression.datatype = type_string;
-
-       return (expression_t*) expression;
+       return expression;
 }
 
 static designator_t *parse_designator(void)
@@ -3309,8 +3440,8 @@ static expression_t *parse_offsetof(void)
 {
        eat(T___builtin_offsetof);
 
-       expression_t *expression  = allocate_expression_zero(EXPR_OFFSETOF);
-       expression->base.datatype = type_size_t;
+       expression_t *expression = allocate_expression_zero(EXPR_OFFSETOF);
+       expression->base.type    = type_size_t;
 
        expect('(');
        expression->offsetofe.type = parse_typename();
@@ -3333,7 +3464,9 @@ static expression_t *parse_va_start(void)
        expression_t *const expr = parse_assignment_expression();
        if (expr->kind == EXPR_REFERENCE) {
                declaration_t *const decl = expr->reference.declaration;
-               if (decl->parent_context == &current_function->context &&
+               if (decl == NULL)
+                       return create_invalid_expression();
+               if (decl->parent_scope == &current_function->scope &&
                    decl->next == NULL) {
                        expression->va_starte.parameter = decl;
                        expect(')');
@@ -3354,7 +3487,7 @@ static expression_t *parse_va_arg(void)
        expect('(');
        expression->va_arge.ap = parse_assignment_expression();
        expect(',');
-       expression->base.datatype = parse_typename();
+       expression->base.type = parse_typename();
        expect(')');
 
        return expression;
@@ -3372,7 +3505,7 @@ static expression_t *parse_builtin_symbol(void)
        type_t *type = get_builtin_symbol_type(symbol);
        type = automatic_type_conversion(type);
 
-       expression->base.datatype = type;
+       expression->base.type = type;
        return expression;
 }
 
@@ -3385,7 +3518,7 @@ static expression_t *parse_builtin_constant(void)
        expect('(');
        expression->builtin_constant.value = parse_assignment_expression();
        expect(')');
-       expression->base.datatype = type_int;
+       expression->base.type = type_int;
 
        return expression;
 }
@@ -3407,7 +3540,7 @@ static expression_t *parse_builtin_prefetch(void)
                expression->builtin_prefetch.locality = parse_assignment_expression();
        }
        expect(')');
-       expression->base.datatype = type_void;
+       expression->base.type = type_void;
 
        return expression;
 }
@@ -3439,6 +3572,7 @@ static expression_t *parse_compare_builtin(void)
                panic("invalid compare builtin found");
                break;
        }
+       expression->base.source_position = HERE;
        next_token();
 
        expect('(');
@@ -3447,15 +3581,15 @@ static expression_t *parse_compare_builtin(void)
        expression->binary.right = parse_assignment_expression();
        expect(')');
 
-       type_t *const orig_type_left  = expression->binary.left->base.datatype;
-       type_t *const orig_type_right = expression->binary.right->base.datatype;
+       type_t *const orig_type_left  = expression->binary.left->base.type;
+       type_t *const orig_type_right = expression->binary.right->base.type;
 
        type_t *const type_left  = skip_typeref(orig_type_left);
        type_t *const type_right = skip_typeref(orig_type_right);
-       if(!is_type_floating(type_left) && !is_type_floating(type_right)) {
+       if(!is_type_float(type_left) && !is_type_float(type_right)) {
                if (is_type_valid(type_left) && is_type_valid(type_right)) {
                        type_error_incompatible("invalid operands in comparison",
-                               token.source_position, orig_type_left, orig_type_right);
+                               expression->base.source_position, orig_type_left, orig_type_right);
                }
        } else {
                semantic_comparison(&expression->binary);
@@ -3477,7 +3611,7 @@ static expression_t *parse_builtin_expect(void)
        expression->binary.right = parse_constant_expression();
        expect(')');
 
-       expression->base.datatype = expression->binary.left->base.datatype;
+       expression->base.type = expression->binary.left->base.type;
 
        return expression;
 }
@@ -3492,21 +3626,7 @@ static expression_t *parse_assume(void) {
        expression->unary.value = parse_assignment_expression();
        expect(')');
 
-       expression->base.datatype = type_void;
-       return expression;
-}
-
-static expression_t *parse_alignof(void) {
-       eat(T___alignof__);
-
-       expression_t *expression
-               = allocate_expression_zero(EXPR_ALIGNOF);
-
-       expect('(');
-       expression->alignofe.type = parse_typename();
-       expect(')');
-
-       expression->base.datatype = type_size_t;
+       expression->base.type = type_void;
        return expression;
 }
 
@@ -3551,8 +3671,6 @@ static expression_t *parse_primary_expression(void)
                return parse_builtin_constant();
        case T___builtin_prefetch:
                return parse_builtin_prefetch();
-       case T___alignof__:
-               return parse_alignof();
        case T_assume:
                return parse_assume();
 
@@ -3570,7 +3688,7 @@ static expression_t *parse_primary_expression(void)
  * Check if the expression has the character type and issue a warning then.
  */
 static void check_for_char_index_type(const expression_t *expression) {
-       type_t       *const type      = expression->base.datatype;
+       type_t       *const type      = expression->base.type;
        const type_t *const base_type = skip_typeref(type);
 
        if (is_type_atomic(base_type, ATOMIC_TYPE_CHAR) &&
@@ -3589,13 +3707,12 @@ static expression_t *parse_array_expression(unsigned precedence,
 
        expression_t *inside = parse_expression();
 
-       array_access_expression_t *array_access
-               = allocate_ast_zero(sizeof(array_access[0]));
+       expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS);
 
-       array_access->expression.kind = EXPR_ARRAY_ACCESS;
+       array_access_expression_t *array_access = &expression->array_access;
 
-       type_t *const orig_type_left   = left->base.datatype;
-       type_t *const orig_type_inside = inside->base.datatype;
+       type_t *const orig_type_left   = left->base.type;
+       type_t *const orig_type_inside = inside->base.type;
 
        type_t *const type_left   = skip_typeref(orig_type_left);
        type_t *const type_inside = skip_typeref(orig_type_inside);
@@ -3624,38 +3741,46 @@ static expression_t *parse_array_expression(unsigned precedence,
 
        if(token.type != ']') {
                parse_error_expected("Problem while parsing array access", ']', 0);
-               return (expression_t*) array_access;
+               return expression;
        }
        next_token();
 
-       return_type = automatic_type_conversion(return_type);
-       array_access->expression.datatype = return_type;
+       return_type           = automatic_type_conversion(return_type);
+       expression->base.type = return_type;
 
-       return (expression_t*) array_access;
+       return expression;
 }
 
-static expression_t *parse_sizeof(unsigned precedence)
+static expression_t *parse_typeprop(expression_kind_t kind, unsigned precedence)
 {
-       eat(T_sizeof);
-
-       sizeof_expression_t *sizeof_expression
-               = allocate_ast_zero(sizeof(sizeof_expression[0]));
-       sizeof_expression->expression.kind     = EXPR_SIZEOF;
-       sizeof_expression->expression.datatype = type_size_t;
+       expression_t *tp_expression = allocate_expression_zero(kind);
+       tp_expression->base.type    = type_size_t;
 
        if(token.type == '(' && is_declaration_specifier(look_ahead(1), true)) {
                next_token();
-               sizeof_expression->type = parse_typename();
+               tp_expression->typeprop.type = parse_typename();
                expect(')');
        } else {
-               expression_t *expression  = parse_sub_expression(precedence);
-               expression->base.datatype = revert_automatic_type_conversion(expression);
+               expression_t *expression = parse_sub_expression(precedence);
+               expression->base.type    = revert_automatic_type_conversion(expression);
 
-               sizeof_expression->type            = expression->base.datatype;
-               sizeof_expression->size_expression = expression;
+               tp_expression->typeprop.type          = expression->base.type;
+               tp_expression->typeprop.tp_expression = expression;
        }
 
-       return (expression_t*) sizeof_expression;
+       return tp_expression;
+}
+
+static expression_t *parse_sizeof(unsigned precedence)
+{
+       eat(T_sizeof);
+       return parse_typeprop(EXPR_SIZEOF, precedence);
+}
+
+static expression_t *parse_alignof(unsigned precedence)
+{
+       eat(T___alignof__);
+       return parse_typeprop(EXPR_SIZEOF, precedence);
 }
 
 static expression_t *parse_select_expression(unsigned precedence,
@@ -3678,7 +3803,7 @@ static expression_t *parse_select_expression(unsigned precedence,
        select->select.symbol = symbol;
        next_token();
 
-       type_t *const orig_type = compound->base.datatype;
+       type_t *const orig_type = compound->base.type;
        type_t *const type      = skip_typeref(orig_type);
 
        type_t *type_left = type;
@@ -3710,7 +3835,7 @@ static expression_t *parse_select_expression(unsigned precedence,
                return create_invalid_expression();
        }
 
-       declaration_t *iter = declaration->context.declarations;
+       declaration_t *iter = declaration->scope.declarations;
        for( ; iter != NULL; iter = iter->next) {
                if(iter->symbol == symbol) {
                        break;
@@ -3726,13 +3851,13 @@ static expression_t *parse_select_expression(unsigned precedence,
        type_t *expression_type = automatic_type_conversion(iter->type);
 
        select->select.compound_entry = iter;
-       select->base.datatype         = expression_type;
+       select->base.type             = expression_type;
 
        if(expression_type->kind == TYPE_BITFIELD) {
                expression_t *extract
                        = allocate_expression_zero(EXPR_UNARY_BITFIELD_EXTRACT);
-               extract->unary.value   = select;
-               extract->base.datatype = expression_type->bitfield.base;
+               extract->unary.value = select;
+               extract->base.type   = expression_type->bitfield.base;
 
                return extract;
        }
@@ -3754,7 +3879,7 @@ static expression_t *parse_call_expression(unsigned precedence,
        call_expression_t *call = &result->call;
        call->function          = expression;
 
-       type_t *const orig_type = expression->base.datatype;
+       type_t *const orig_type = expression->base.type;
        type_t *const type      = skip_typeref(orig_type);
 
        function_type_t *function_type = NULL;
@@ -3762,8 +3887,8 @@ static expression_t *parse_call_expression(unsigned precedence,
                type_t *const to_type = skip_typeref(type->pointer.points_to);
 
                if (is_type_function(to_type)) {
-                       function_type             = &to_type->function;
-                       call->expression.datatype = function_type->return_type;
+                       function_type   = &to_type->function;
+                       call->base.type = function_type->return_type;
                }
        }
 
@@ -3801,14 +3926,14 @@ static expression_t *parse_call_expression(unsigned precedence,
                for( ; parameter != NULL && argument != NULL;
                                parameter = parameter->next, argument = argument->next) {
                        type_t *expected_type = parameter->type;
-                       /* TODO report context in error messages */
+                       /* TODO report scope in error messages */
                        expression_t *const arg_expr = argument->expression;
                        type_t       *const res_type = semantic_assign(expected_type, arg_expr, "function call");
                        if (res_type == NULL) {
                                /* TODO improve error message */
                                errorf(arg_expr->base.source_position,
                                        "Cannot call function with argument '%E' of type '%T' where type '%T' is expected",
-                                       arg_expr, arg_expr->base.datatype, expected_type);
+                                       arg_expr, arg_expr->base.type, expected_type);
                        } else {
                                argument->expression = create_implicit_cast(argument->expression, expected_type);
                        }
@@ -3824,7 +3949,7 @@ static expression_t *parse_call_expression(unsigned precedence,
                        } else {
                                /* do default promotion */
                                for( ; argument != NULL; argument = argument->next) {
-                                       type_t *type = argument->expression->base.datatype;
+                                       type_t *type = argument->expression->base.type;
 
                                        type = skip_typeref(type);
                                        if(is_type_integer(type)) {
@@ -3873,7 +3998,7 @@ static expression_t *parse_conditional_expression(unsigned precedence,
        conditional->condition = expression;
 
        /* 6.5.15.2 */
-       type_t *const condition_type_orig = expression->base.datatype;
+       type_t *const condition_type_orig = expression->base.type;
        type_t *const condition_type      = skip_typeref(condition_type_orig);
        if (!is_type_scalar(condition_type) && is_type_valid(condition_type)) {
                type_error("expected a scalar type in conditional condition",
@@ -3887,8 +4012,8 @@ static expression_t *parse_conditional_expression(unsigned precedence,
        conditional->true_expression  = true_expression;
        conditional->false_expression = false_expression;
 
-       type_t *const orig_true_type  = true_expression->base.datatype;
-       type_t *const orig_false_type = false_expression->base.datatype;
+       type_t *const orig_true_type  = true_expression->base.type;
+       type_t *const orig_false_type = false_expression->base.type;
        type_t *const true_type       = skip_typeref(orig_true_type);
        type_t *const false_type      = skip_typeref(orig_false_type);
 
@@ -3900,9 +4025,9 @@ static expression_t *parse_conditional_expression(unsigned precedence,
                true_expression  = create_implicit_cast(true_expression, result_type);
                false_expression = create_implicit_cast(false_expression, result_type);
 
-               conditional->true_expression     = true_expression;
-               conditional->false_expression    = false_expression;
-               conditional->expression.datatype = result_type;
+               conditional->true_expression  = true_expression;
+               conditional->false_expression = false_expression;
+               conditional->base.type        = result_type;
        } else if (same_compound_type(true_type, false_type) || (
            is_type_atomic(true_type, ATOMIC_TYPE_VOID) &&
            is_type_atomic(false_type, ATOMIC_TYPE_VOID)
@@ -3923,7 +4048,7 @@ static expression_t *parse_conditional_expression(unsigned precedence,
                result_type = type_error_type;
        }
 
-       conditional->expression.datatype = result_type;
+       conditional->base.type = result_type;
        return result;
 }
 
@@ -3944,8 +4069,8 @@ static expression_t *parse_builtin_classify_type(const unsigned precedence)
 {
        eat(T___builtin_classify_type);
 
-       expression_t *result  = allocate_expression_zero(EXPR_CLASSIFY_TYPE);
-       result->base.datatype = type_int;
+       expression_t *result = allocate_expression_zero(EXPR_CLASSIFY_TYPE);
+       result->base.type    = type_int;
 
        expect('(');
        expression_t *expression = parse_sub_expression(precedence);
@@ -3957,7 +4082,7 @@ static expression_t *parse_builtin_classify_type(const unsigned precedence)
 
 static void semantic_incdec(unary_expression_t *expression)
 {
-       type_t *const orig_type = expression->value->base.datatype;
+       type_t *const orig_type = expression->value->base.type;
        type_t *const type      = skip_typeref(orig_type);
        /* TODO !is_type_real && !is_type_pointer */
        if(!is_type_arithmetic(type) && type->kind != TYPE_POINTER) {
@@ -3968,12 +4093,12 @@ static void semantic_incdec(unary_expression_t *expression)
                return;
        }
 
-       expression->expression.datatype = orig_type;
+       expression->base.type = orig_type;
 }
 
 static void semantic_unexpr_arithmetic(unary_expression_t *expression)
 {
-       type_t *const orig_type = expression->value->base.datatype;
+       type_t *const orig_type = expression->value->base.type;
        type_t *const type      = skip_typeref(orig_type);
        if(!is_type_arithmetic(type)) {
                if (is_type_valid(type)) {
@@ -3983,12 +4108,12 @@ static void semantic_unexpr_arithmetic(unary_expression_t *expression)
                return;
        }
 
-       expression->expression.datatype = orig_type;
+       expression->base.type = orig_type;
 }
 
 static void semantic_unexpr_scalar(unary_expression_t *expression)
 {
-       type_t *const orig_type = expression->value->base.datatype;
+       type_t *const orig_type = expression->value->base.type;
        type_t *const type      = skip_typeref(orig_type);
        if (!is_type_scalar(type)) {
                if (is_type_valid(type)) {
@@ -3997,12 +4122,12 @@ static void semantic_unexpr_scalar(unary_expression_t *expression)
                return;
        }
 
-       expression->expression.datatype = orig_type;
+       expression->base.type = orig_type;
 }
 
 static void semantic_unexpr_integer(unary_expression_t *expression)
 {
-       type_t *const orig_type = expression->value->base.datatype;
+       type_t *const orig_type = expression->value->base.type;
        type_t *const type      = skip_typeref(orig_type);
        if (!is_type_integer(type)) {
                if (is_type_valid(type)) {
@@ -4011,12 +4136,12 @@ static void semantic_unexpr_integer(unary_expression_t *expression)
                return;
        }
 
-       expression->expression.datatype = orig_type;
+       expression->base.type = orig_type;
 }
 
 static void semantic_dereference(unary_expression_t *expression)
 {
-       type_t *const orig_type = expression->value->base.datatype;
+       type_t *const orig_type = expression->value->base.type;
        type_t *const type      = skip_typeref(orig_type);
        if(!is_type_pointer(type)) {
                if (is_type_valid(type)) {
@@ -4025,9 +4150,9 @@ static void semantic_dereference(unary_expression_t *expression)
                return;
        }
 
-       type_t *result_type = type->pointer.points_to;
-       result_type = automatic_type_conversion(result_type);
-       expression->expression.datatype = result_type;
+       type_t *result_type   = type->pointer.points_to;
+       result_type           = automatic_type_conversion(result_type);
+       expression->base.type = result_type;
 }
 
 /**
@@ -4035,10 +4160,10 @@ static void semantic_dereference(unary_expression_t *expression)
  */
 static void semantic_take_addr(unary_expression_t *expression)
 {
-       expression_t *value  = expression->value;
-       value->base.datatype = revert_automatic_type_conversion(value);
+       expression_t *value = expression->value;
+       value->base.type    = revert_automatic_type_conversion(value);
 
-       type_t *orig_type = value->base.datatype;
+       type_t *orig_type = value->base.type;
        if(!is_type_valid(orig_type))
                return;
 
@@ -4046,7 +4171,7 @@ static void semantic_take_addr(unary_expression_t *expression)
                declaration_t *const declaration = value->reference.declaration;
                if(declaration != NULL) {
                        if (declaration->storage_class == STORAGE_CLASS_REGISTER) {
-                               errorf(expression->expression.source_position,
+                               errorf(expression->base.source_position,
                                        "address of register variable '%Y' requested",
                                        declaration->symbol);
                        }
@@ -4054,7 +4179,7 @@ static void semantic_take_addr(unary_expression_t *expression)
                }
        }
 
-       expression->expression.datatype = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
+       expression->base.type = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
 }
 
 #define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc)   \
@@ -4158,8 +4283,8 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
 {
        expression_t *const left            = expression->left;
        expression_t *const right           = expression->right;
-       type_t       *const orig_type_left  = left->base.datatype;
-       type_t       *const orig_type_right = right->base.datatype;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
        type_t       *const type_left       = skip_typeref(orig_type_left);
        type_t       *const type_right      = skip_typeref(orig_type_right);
 
@@ -4172,17 +4297,17 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
        }
 
        type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
-       expression->left  = create_implicit_cast(left, arithmetic_type);
-       expression->right = create_implicit_cast(right, arithmetic_type);
-       expression->expression.datatype = arithmetic_type;
+       expression->left      = create_implicit_cast(left, arithmetic_type);
+       expression->right     = create_implicit_cast(right, arithmetic_type);
+       expression->base.type = arithmetic_type;
 }
 
 static void semantic_shift_op(binary_expression_t *expression)
 {
        expression_t *const left            = expression->left;
        expression_t *const right           = expression->right;
-       type_t       *const orig_type_left  = left->base.datatype;
-       type_t       *const orig_type_right = right->base.datatype;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
        type_t       *      type_left       = skip_typeref(orig_type_left);
        type_t       *      type_right      = skip_typeref(orig_type_right);
 
@@ -4197,17 +4322,17 @@ static void semantic_shift_op(binary_expression_t *expression)
        type_left  = promote_integer(type_left);
        type_right = promote_integer(type_right);
 
-       expression->left  = create_implicit_cast(left, type_left);
-       expression->right = create_implicit_cast(right, type_right);
-       expression->expression.datatype = type_left;
+       expression->left      = create_implicit_cast(left, type_left);
+       expression->right     = create_implicit_cast(right, type_right);
+       expression->base.type = type_left;
 }
 
 static void semantic_add(binary_expression_t *expression)
 {
        expression_t *const left            = expression->left;
        expression_t *const right           = expression->right;
-       type_t       *const orig_type_left  = left->base.datatype;
-       type_t       *const orig_type_right = right->base.datatype;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
        type_t       *const type_left       = skip_typeref(orig_type_left);
        type_t       *const type_right      = skip_typeref(orig_type_right);
 
@@ -4216,12 +4341,12 @@ static void semantic_add(binary_expression_t *expression)
                type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
                expression->left  = create_implicit_cast(left, arithmetic_type);
                expression->right = create_implicit_cast(right, arithmetic_type);
-               expression->expression.datatype = arithmetic_type;
+               expression->base.type = arithmetic_type;
                return;
        } else if(is_type_pointer(type_left) && is_type_integer(type_right)) {
-               expression->expression.datatype = type_left;
+               expression->base.type = type_left;
        } else if(is_type_pointer(type_right) && is_type_integer(type_left)) {
-               expression->expression.datatype = type_right;
+               expression->base.type = type_right;
        } else if (is_type_valid(type_left) && is_type_valid(type_right)) {
                errorf(HERE, "invalid operands to binary + ('%T', '%T')", orig_type_left, orig_type_right);
        }
@@ -4231,47 +4356,69 @@ static void semantic_sub(binary_expression_t *expression)
 {
        expression_t *const left            = expression->left;
        expression_t *const right           = expression->right;
-       type_t       *const orig_type_left  = left->base.datatype;
-       type_t       *const orig_type_right = right->base.datatype;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
        type_t       *const type_left       = skip_typeref(orig_type_left);
        type_t       *const type_right      = skip_typeref(orig_type_right);
 
        /* ยง 5.6.5 */
        if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
                type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
-               expression->left  = create_implicit_cast(left, arithmetic_type);
-               expression->right = create_implicit_cast(right, arithmetic_type);
-               expression->expression.datatype = arithmetic_type;
+               expression->left        = create_implicit_cast(left, arithmetic_type);
+               expression->right       = create_implicit_cast(right, arithmetic_type);
+               expression->base.type =  arithmetic_type;
                return;
        } else if(is_type_pointer(type_left) && is_type_integer(type_right)) {
-               expression->expression.datatype = type_left;
+               expression->base.type = type_left;
        } else if(is_type_pointer(type_left) && is_type_pointer(type_right)) {
                if(!pointers_compatible(type_left, type_right)) {
-                       errorf(HERE, "pointers to incompatible objects to binary '-' ('%T', '%T')", orig_type_left, orig_type_right);
+                       errorf(HERE,
+                              "pointers to incompatible objects to binary '-' ('%T', '%T')",
+                              orig_type_left, orig_type_right);
                } else {
-                       expression->expression.datatype = type_ptrdiff_t;
+                       expression->base.type = type_ptrdiff_t;
                }
        } else if (is_type_valid(type_left) && is_type_valid(type_right)) {
-               errorf(HERE, "invalid operands to binary '-' ('%T', '%T')", orig_type_left, orig_type_right);
+               errorf(HERE, "invalid operands to binary '-' ('%T', '%T')",
+                      orig_type_left, orig_type_right);
        }
 }
 
+/**
+ * Check the semantics of comparison expressions.
+ *
+ * @param expression   The expression to check.
+ */
 static void semantic_comparison(binary_expression_t *expression)
 {
        expression_t *left            = expression->left;
        expression_t *right           = expression->right;
-       type_t       *orig_type_left  = left->base.datatype;
-       type_t       *orig_type_right = right->base.datatype;
+       type_t       *orig_type_left  = left->base.type;
+       type_t       *orig_type_right = right->base.type;
 
        type_t *type_left  = skip_typeref(orig_type_left);
        type_t *type_right = skip_typeref(orig_type_right);
 
        /* TODO non-arithmetic types */
        if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+               if (warning.sign_compare &&
+                   (expression->base.kind != EXPR_BINARY_EQUAL &&
+                    expression->base.kind != EXPR_BINARY_NOTEQUAL) &&
+                   (is_type_signed(type_left) != is_type_signed(type_right))) {
+                       warningf(expression->base.source_position,
+                                "comparison between signed and unsigned");
+               }
                type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
-               expression->left  = create_implicit_cast(left, arithmetic_type);
-               expression->right = create_implicit_cast(right, arithmetic_type);
-               expression->expression.datatype = arithmetic_type;
+               expression->left        = create_implicit_cast(left, arithmetic_type);
+               expression->right       = create_implicit_cast(right, arithmetic_type);
+               expression->base.type   = arithmetic_type;
+               if (warning.float_equal &&
+                   (expression->base.kind == EXPR_BINARY_EQUAL ||
+                    expression->base.kind == EXPR_BINARY_NOTEQUAL) &&
+                   is_type_float(arithmetic_type)) {
+                       warningf(expression->base.source_position,
+                                "comparing floating point with == or != is unsafe");
+               }
        } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
                /* TODO check compatibility */
        } else if (is_type_pointer(type_left)) {
@@ -4280,17 +4427,18 @@ static void semantic_comparison(binary_expression_t *expression)
                expression->left = create_implicit_cast(left, type_right);
        } else if (is_type_valid(type_left) && is_type_valid(type_right)) {
                type_error_incompatible("invalid operands in comparison",
-                                       token.source_position, type_left, type_right);
+                                       expression->base.source_position,
+                                       type_left, type_right);
        }
-       expression->expression.datatype = type_int;
+       expression->base.type = type_int;
 }
 
 static void semantic_arithmetic_assign(binary_expression_t *expression)
 {
        expression_t *left            = expression->left;
        expression_t *right           = expression->right;
-       type_t       *orig_type_left  = left->base.datatype;
-       type_t       *orig_type_right = right->base.datatype;
+       type_t       *orig_type_left  = left->base.type;
+       type_t       *orig_type_right = right->base.type;
 
        type_t *type_left  = skip_typeref(orig_type_left);
        type_t *type_right = skip_typeref(orig_type_right);
@@ -4309,15 +4457,15 @@ static void semantic_arithmetic_assign(binary_expression_t *expression)
         * for the arithmetic operation and create a cast by itself */
        type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
        expression->right       = create_implicit_cast(right, arithmetic_type);
-       expression->expression.datatype = type_left;
+       expression->base.type   = type_left;
 }
 
 static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression)
 {
        expression_t *const left            = expression->left;
        expression_t *const right           = expression->right;
-       type_t       *const orig_type_left  = left->base.datatype;
-       type_t       *const orig_type_right = right->base.datatype;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
        type_t       *const type_left       = skip_typeref(orig_type_left);
        type_t       *const type_right      = skip_typeref(orig_type_right);
 
@@ -4327,10 +4475,10 @@ static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression)
                 * The ast2firm pass has to know that left_type must be right_type
                 * for the arithmetic operation and create a cast by itself */
                type_t *const arithmetic_type = semantic_arithmetic(type_left, type_right);
-               expression->right = create_implicit_cast(right, arithmetic_type);
-               expression->expression.datatype = type_left;
+               expression->right     = create_implicit_cast(right, arithmetic_type);
+               expression->base.type = type_left;
        } else if (is_type_pointer(type_left) && is_type_integer(type_right)) {
-               expression->expression.datatype = type_left;
+               expression->base.type = type_left;
        } else if (is_type_valid(type_left) && is_type_valid(type_right)) {
                errorf(HERE, "incompatible types '%T' and '%T' in assignment", orig_type_left, orig_type_right);
        }
@@ -4343,8 +4491,8 @@ static void semantic_logical_op(binary_expression_t *expression)
 {
        expression_t *const left            = expression->left;
        expression_t *const right           = expression->right;
-       type_t       *const orig_type_left  = left->base.datatype;
-       type_t       *const orig_type_right = right->base.datatype;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
        type_t       *const type_left       = skip_typeref(orig_type_left);
        type_t       *const type_right      = skip_typeref(orig_type_right);
 
@@ -4356,7 +4504,7 @@ static void semantic_logical_op(binary_expression_t *expression)
                return;
        }
 
-       expression->expression.datatype = type_int;
+       expression->base.type = type_int;
 }
 
 /**
@@ -4364,8 +4512,8 @@ static void semantic_logical_op(binary_expression_t *expression)
  */
 static bool has_const_fields(const compound_type_t *type)
 {
-       const context_t     *context = &type->declaration->context;
-       const declaration_t *declaration = context->declarations;
+       const scope_t       *scope       = &type->declaration->scope;
+       const declaration_t *declaration = scope->declarations;
 
        for (; declaration != NULL; declaration = declaration->next) {
                if (declaration->namespc != NAMESPACE_NORMAL)
@@ -4385,7 +4533,7 @@ static bool has_const_fields(const compound_type_t *type)
 static void semantic_binexpr_assign(binary_expression_t *expression)
 {
        expression_t *left           = expression->left;
-       type_t       *orig_type_left = left->base.datatype;
+       type_t       *orig_type_left = left->base.type;
 
        type_t *type_left = revert_automatic_type_conversion(left);
        type_left         = skip_typeref(orig_type_left);
@@ -4415,14 +4563,14 @@ static void semantic_binexpr_assign(binary_expression_t *expression)
        type_t *const res_type = semantic_assign(orig_type_left, expression->right,
                                                 "assignment");
        if (res_type == NULL) {
-               errorf(expression->expression.source_position,
+               errorf(expression->base.source_position,
                        "cannot assign to '%T' from '%T'",
-                       orig_type_left, expression->right->base.datatype);
+                       orig_type_left, expression->right->base.type);
        } else {
                expression->right = create_implicit_cast(expression->right, res_type);
        }
 
-       expression->expression.datatype = orig_type_left;
+       expression->base.type = orig_type_left;
 }
 
 static bool expression_has_effect(const expression_t *const expr)
@@ -4477,7 +4625,7 @@ static bool expression_has_effect(const expression_t *const expr)
                case EXPR_UNARY_PREFIX_INCREMENT:    return true;
                case EXPR_UNARY_PREFIX_DECREMENT:    return true;
                case EXPR_UNARY_CAST:
-                       return is_type_atomic(expr->base.datatype, ATOMIC_TYPE_VOID);
+                       return is_type_atomic(expr->base.type, ATOMIC_TYPE_VOID);
                case EXPR_UNARY_CAST_IMPLICIT:       return true;
                case EXPR_UNARY_ASSUME:              return true;
                case EXPR_UNARY_BITFIELD_EXTRACT:    return false;
@@ -4534,7 +4682,7 @@ static void semantic_comma(binary_expression_t *expression)
                        warningf(left->base.source_position, "left-hand operand of comma expression has no effect");
                }
        }
-       expression->expression.datatype = expression->right->base.datatype;
+       expression->base.type = expression->right->base.type;
 }
 
 #define CREATE_BINEXPR_PARSER(token_type, binexpression_type, sfunc, lr)  \
@@ -4542,10 +4690,12 @@ static expression_t *parse_##binexpression_type(unsigned precedence,      \
                                                 expression_t *left)       \
 {                                                                         \
        eat(token_type);                                                      \
+       source_position_t pos = HERE;                                         \
                                                                           \
        expression_t *right = parse_sub_expression(precedence + lr);          \
                                                                           \
        expression_t *binexpr = allocate_expression_zero(binexpression_type); \
+       binexpr->base.source_position = pos;                                  \
        binexpr->binary.left  = left;                                         \
        binexpr->binary.right = right;                                        \
        sfunc(&binexpr->binary);                                              \
@@ -4761,7 +4911,8 @@ static void init_expression_parsers(void)
                                                                  T_PLUSPLUS,   25);
        register_expression_parser(parse_EXPR_UNARY_PREFIX_DECREMENT,
                                                                  T_MINUSMINUS, 25);
-       register_expression_parser(parse_sizeof,                  T_sizeof,     25);
+       register_expression_parser(parse_sizeof,                      T_sizeof, 25);
+       register_expression_parser(parse_alignof,                T___alignof__, 25);
        register_expression_parser(parse_extension,            T___extension__, 25);
        register_expression_parser(parse_builtin_classify_type,
                                                     T___builtin_classify_type, 25);
@@ -4912,7 +5063,7 @@ static statement_t *parse_case_statement(void)
                                "case label not within a switch statement");
                }
        }
-       statement->case_label.label_statement = parse_statement();
+       statement->case_label.statement = parse_statement();
 
        return statement;
 }
@@ -4948,7 +5099,7 @@ static statement_t *parse_default_statement(void)
                const case_label_statement_t *def_label = find_default_label(current_switch);
                if (def_label != NULL) {
                        errorf(HERE, "multiple default labels in one switch");
-                       errorf(def_label->statement.source_position,
+                       errorf(def_label->base.source_position,
                                "this is the first default label");
                } else {
                        /* link all cases into the switch statement */
@@ -4963,7 +5114,7 @@ static statement_t *parse_default_statement(void)
                errorf(statement->base.source_position,
                        "'default' label not within a switch statement");
        }
-       statement->label.label_statement = parse_statement();
+       statement->label.statement = parse_statement();
 
        return statement;
 }
@@ -4978,7 +5129,7 @@ static declaration_t *get_label(symbol_t *symbol)
        /* if we found a label in the same function, then we already created the
         * declaration */
        if(candidate != NULL
-                       && candidate->parent_context == &current_function->context) {
+                       && candidate->parent_scope == &current_function->scope) {
                return candidate;
        }
 
@@ -5013,18 +5164,17 @@ static statement_t *parse_label_statement(void)
                label->source_position = token.source_position;
        }
 
-       label_statement_t *label_statement = allocate_ast_zero(sizeof(label[0]));
+       statement_t *statement = allocate_statement_zero(STATEMENT_LABEL);
 
-       label_statement->statement.kind            = STATEMENT_LABEL;
-       label_statement->statement.source_position = token.source_position;
-       label_statement->label                     = label;
+       statement->base.source_position = token.source_position;
+       statement->label.label          = label;
 
        eat(':');
 
        if(token.type == '}') {
                /* TODO only warn? */
                errorf(HERE, "label at end of compound statement");
-               return (statement_t*) label_statement;
+               return statement;
        } else {
                if (token.type == ';') {
                        /* eat an empty statement here, to avoid the warning about an empty
@@ -5032,11 +5182,19 @@ static statement_t *parse_label_statement(void)
                         * a }. */
                        next_token();
                } else {
-                       label_statement->label_statement = parse_statement();
+                       statement->label.statement = parse_statement();
                }
        }
 
-       return (statement_t*) label_statement;
+       /* remember the labels's in a list for later checking */
+       if (label_last == NULL) {
+               label_first = &statement->label;
+       } else {
+               label_last->next = &statement->label;
+       }
+       label_last = &statement->label;
+
+       return statement;
 }
 
 /**
@@ -5046,21 +5204,20 @@ static statement_t *parse_if(void)
 {
        eat(T_if);
 
-       if_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.kind            = STATEMENT_IF;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement          = allocate_statement_zero(STATEMENT_IF);
+       statement->base.source_position = token.source_position;
 
        expect('(');
-       statement->condition = parse_expression();
+       statement->ifs.condition = parse_expression();
        expect(')');
 
-       statement->true_statement = parse_statement();
+       statement->ifs.true_statement = parse_statement();
        if(token.type == T_else) {
                next_token();
-               statement->false_statement = parse_statement();
+               statement->ifs.false_statement = parse_statement();
        }
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 /**
@@ -5070,39 +5227,42 @@ static statement_t *parse_switch(void)
 {
        eat(T_switch);
 
-       switch_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.kind            = STATEMENT_SWITCH;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement          = allocate_statement_zero(STATEMENT_SWITCH);
+       statement->base.source_position = token.source_position;
 
        expect('(');
        expression_t *const expr = parse_expression();
-       type_t       *      type = skip_typeref(expr->base.datatype);
+       type_t       *      type = skip_typeref(expr->base.type);
        if (is_type_integer(type)) {
                type = promote_integer(type);
        } else if (is_type_valid(type)) {
-               errorf(expr->base.source_position, "switch quantity is not an integer, but '%T'", type);
+               errorf(expr->base.source_position,
+                      "switch quantity is not an integer, but '%T'", type);
                type = type_error_type;
        }
-       statement->expression = create_implicit_cast(expr, type);
+       statement->switchs.expression = create_implicit_cast(expr, type);
        expect(')');
 
        switch_statement_t *rem = current_switch;
-       current_switch  = statement;
-       statement->body = parse_statement();
-       current_switch  = rem;
+       current_switch          = &statement->switchs;
+       statement->switchs.body = parse_statement();
+       current_switch          = rem;
 
-       if (warning.switch_default && find_default_label(statement) == NULL) {
-               warningf(statement->statement.source_position, "switch has no default case");
+       if (warning.switch_default
+                       && find_default_label(&statement->switchs) == NULL) {
+               warningf(statement->base.source_position, "switch has no default case");
        }
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 static statement_t *parse_loop_body(statement_t *const loop)
 {
        statement_t *const rem = current_loop;
        current_loop = loop;
+
        statement_t *const body = parse_statement();
+
        current_loop = rem;
        return body;
 }
@@ -5114,17 +5274,16 @@ static statement_t *parse_while(void)
 {
        eat(T_while);
 
-       while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.kind            = STATEMENT_WHILE;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement          = allocate_statement_zero(STATEMENT_WHILE);
+       statement->base.source_position = token.source_position;
 
        expect('(');
-       statement->condition = parse_expression();
+       statement->whiles.condition = parse_expression();
        expect(')');
 
-       statement->body = parse_loop_body((statement_t*)statement);
+       statement->whiles.body = parse_loop_body(statement);
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 /**
@@ -5134,18 +5293,19 @@ static statement_t *parse_do(void)
 {
        eat(T_do);
 
-       do_while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.kind            = STATEMENT_DO_WHILE;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement = allocate_statement_zero(STATEMENT_DO_WHILE);
+
+       statement->base.source_position = token.source_position;
+
+       statement->do_while.body = parse_loop_body(statement);
 
-       statement->body = parse_loop_body((statement_t*)statement);
        expect(T_while);
        expect('(');
-       statement->condition = parse_expression();
+       statement->do_while.condition = parse_expression();
        expect(')');
        expect(';');
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 /**
@@ -5155,21 +5315,20 @@ static statement_t *parse_for(void)
 {
        eat(T_for);
 
-       for_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-       statement->statement.kind            = STATEMENT_FOR;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement          = allocate_statement_zero(STATEMENT_FOR);
+       statement->base.source_position = token.source_position;
 
        expect('(');
 
-       int         top          = environment_top();
-       context_t  *last_context = context;
-       set_context(&statement->context);
+       int      top        = environment_top();
+       scope_t *last_scope = scope;
+       set_scope(&statement->fors.scope);
 
        if(token.type != ';') {
                if(is_declaration_specifier(&token, false)) {
                        parse_declaration(record_declaration);
                } else {
-                       statement->initialisation = parse_expression();
+                       statement->fors.initialisation = parse_expression();
                        expect(';');
                }
        } else {
@@ -5177,20 +5336,20 @@ static statement_t *parse_for(void)
        }
 
        if(token.type != ';') {
-               statement->condition = parse_expression();
+               statement->fors.condition = parse_expression();
        }
        expect(';');
        if(token.type != ')') {
-               statement->step = parse_expression();
+               statement->fors.step = parse_expression();
        }
        expect(')');
-       statement->body = parse_loop_body((statement_t*)statement);
+       statement->fors.body = parse_loop_body(statement);
 
-       assert(context == &statement->context);
-       set_context(last_context);
+       assert(scope == &statement->fors.scope);
+       set_scope(last_scope);
        environment_pop_to(top);
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 /**
@@ -5210,23 +5369,22 @@ static statement_t *parse_goto(void)
 
        declaration_t *label = get_label(symbol);
 
-       goto_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-
-       statement->statement.kind            = STATEMENT_GOTO;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement          = allocate_statement_zero(STATEMENT_GOTO);
+       statement->base.source_position = token.source_position;
 
-       statement->label = label;
+       statement->gotos.label = label;
 
        /* remember the goto's in a list for later checking */
        if (goto_last == NULL) {
-               goto_first = goto_last = statement;
+               goto_first = &statement->gotos;
        } else {
-               goto_last->next = statement;
+               goto_last->next = &statement->gotos;
        }
+       goto_last = &statement->gotos;
 
        expect(';');
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 /**
@@ -5291,6 +5449,31 @@ static bool is_local_var_declaration(const declaration_t *declaration) {
        }
 }
 
+/**
+ * Check if a given declaration represents a variable.
+ */
+static bool is_var_declaration(const declaration_t *declaration) {
+       switch ((storage_class_tag_t) declaration->storage_class) {
+       case STORAGE_CLASS_NONE:
+       case STORAGE_CLASS_EXTERN:
+       case STORAGE_CLASS_STATIC:
+       case STORAGE_CLASS_AUTO:
+       case STORAGE_CLASS_REGISTER:
+       case STORAGE_CLASS_THREAD:
+       case STORAGE_CLASS_THREAD_EXTERN:
+       case STORAGE_CLASS_THREAD_STATIC: {
+               const type_t *type = skip_typeref(declaration->type);
+               if(is_type_function(type)) {
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+       default:
+               return false;
+       }
+}
+
 /**
  * Check if a given expression represents a local variable.
  */
@@ -5303,6 +5486,21 @@ static bool is_local_variable(const expression_t *expression)
        return is_local_var_declaration(declaration);
 }
 
+/**
+ * Check if a given expression represents a local variable and
+ * return its declaration then, else return NULL.
+ */
+declaration_t *expr_is_variable(const expression_t *expression)
+{
+       if (expression->base.kind != EXPR_REFERENCE) {
+               return NULL;
+       }
+       declaration_t *declaration = expression->reference.declaration;
+       if (is_var_declaration(declaration))
+               return declaration;
+       return NULL;
+}
+
 /**
  * Parse a return statement.
  */
@@ -5310,10 +5508,8 @@ static statement_t *parse_return(void)
 {
        eat(T_return);
 
-       return_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
-
-       statement->statement.kind            = STATEMENT_RETURN;
-       statement->statement.source_position = token.source_position;
+       statement_t *statement          = allocate_statement_zero(STATEMENT_RETURN);
+       statement->base.source_position = token.source_position;
 
        expression_t *return_value = NULL;
        if(token.type != ';') {
@@ -5326,20 +5522,20 @@ static statement_t *parse_return(void)
        type_t *const return_type = skip_typeref(func_type->function.return_type);
 
        if(return_value != NULL) {
-               type_t *return_value_type = skip_typeref(return_value->base.datatype);
+               type_t *return_value_type = skip_typeref(return_value->base.type);
 
                if(is_type_atomic(return_type, ATOMIC_TYPE_VOID)
                                && !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) {
-                       warningf(statement->statement.source_position,
-                               "'return' with a value, in function returning void");
+                       warningf(statement->base.source_position,
+                                "'return' with a value, in function returning void");
                        return_value = NULL;
                } else {
                        type_t *const res_type = semantic_assign(return_type,
                                return_value, "'return'");
                        if (res_type == NULL) {
-                               errorf(statement->statement.source_position,
-                                       "cannot return something of type '%T' in function returning '%T'",
-                                       return_value->base.datatype, return_type);
+                               errorf(statement->base.source_position,
+                                      "cannot return something of type '%T' in function returning '%T'",
+                                      return_value->base.type, return_type);
                        } else {
                                return_value = create_implicit_cast(return_value, res_type);
                        }
@@ -5348,19 +5544,19 @@ static statement_t *parse_return(void)
                if (return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
                        const expression_t *expression = return_value->unary.value;
                        if (is_local_variable(expression)) {
-                               warningf(statement->statement.source_position,
-                                       "function returns address of local variable");
+                               warningf(statement->base.source_position,
+                                        "function returns address of local variable");
                        }
                }
        } else {
                if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
-                       warningf(statement->statement.source_position,
-                               "'return' without value, in function returning non-void");
+                       warningf(statement->base.source_position,
+                                "'return' without value, in function returning non-void");
                }
        }
-       statement->return_value = return_value;
+       statement->returns.value = return_value;
 
-       return (statement_t*) statement;
+       return statement;
 }
 
 /**
@@ -5376,7 +5572,7 @@ static statement_t *parse_declaration_statement(void)
        parse_declaration(record_declaration);
 
        if(before == NULL) {
-               statement->declaration.declarations_begin = context->declarations;
+               statement->declaration.declarations_begin = scope->declarations;
        } else {
                statement->declaration.declarations_begin = before->next;
        }
@@ -5517,47 +5713,47 @@ static statement_t *parse_statement(void)
  */
 static statement_t *parse_compound_statement(void)
 {
-       compound_statement_t *const compound_statement
-               = allocate_ast_zero(sizeof(compound_statement[0]));
-       compound_statement->statement.kind            = STATEMENT_COMPOUND;
-       compound_statement->statement.source_position = token.source_position;
+       statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND);
+
+       statement->base.source_position = token.source_position;
 
        eat('{');
 
-       int        top          = environment_top();
-       context_t *last_context = context;
-       set_context(&compound_statement->context);
+       int      top        = environment_top();
+       scope_t *last_scope = scope;
+       set_scope(&statement->compound.scope);
 
        statement_t *last_statement = NULL;
 
        while(token.type != '}' && token.type != T_EOF) {
-               statement_t *statement = parse_statement();
-               if(statement == NULL)
+               statement_t *sub_statement = parse_statement();
+               if(sub_statement == NULL)
                        continue;
 
                if(last_statement != NULL) {
-                       last_statement->base.next = statement;
+                       last_statement->base.next = sub_statement;
                } else {
-                       compound_statement->statements = statement;
+                       statement->compound.statements = sub_statement;
                }
 
-               while(statement->base.next != NULL)
-                       statement = statement->base.next;
+               while(sub_statement->base.next != NULL)
+                       sub_statement = sub_statement->base.next;
 
-               last_statement = statement;
+               last_statement = sub_statement;
        }
 
        if(token.type == '}') {
                next_token();
        } else {
-               errorf(compound_statement->statement.source_position, "end of file while looking for closing '}'");
+               errorf(statement->base.source_position,
+                      "end of file while looking for closing '}'");
        }
 
-       assert(context == &compound_statement->context);
-       set_context(last_context);
+       assert(scope == &statement->compound.scope);
+       set_scope(last_scope);
        environment_pop_to(top);
 
-       return (statement_t*) compound_statement;
+       return statement;
 }
 
 /**
@@ -5580,6 +5776,37 @@ static void initialize_builtin_types(void)
        type_wchar_t_ptr   = make_pointer_type(type_wchar_t,   TYPE_QUALIFIER_NONE);
 }
 
+/**
+ * Check for unused global static functions and variables
+ */
+static void check_unused_globals(void)
+{
+       if (!warning.unused_function && !warning.unused_variable)
+               return;
+
+       for (const declaration_t *decl = global_scope->declarations; decl != NULL; decl = decl->next) {
+               if (decl->used || decl->storage_class != STORAGE_CLASS_STATIC)
+                       continue;
+
+               type_t *const type = decl->type;
+               const char *s;
+               if (is_type_function(skip_typeref(type))) {
+                       if (!warning.unused_function || decl->is_inline)
+                               continue;
+
+                       s = (decl->init.statement != NULL ? "defined" : "declared");
+               } else {
+                       if (!warning.unused_variable)
+                               continue;
+
+                       s = "defined";
+               }
+
+               warningf(decl->source_position, "'%#T' %s but not used",
+                       type, decl->symbol, s);
+       }
+}
+
 /**
  * Parse a translation unit.
  */
@@ -5587,11 +5814,11 @@ static translation_unit_t *parse_translation_unit(void)
 {
        translation_unit_t *unit = allocate_ast_zero(sizeof(unit[0]));
 
-       assert(global_context == NULL);
-       global_context = &unit->context;
+       assert(global_scope == NULL);
+       global_scope = &unit->scope;
 
-       assert(context == NULL);
-       set_context(&unit->context);
+       assert(scope == NULL);
+       set_scope(&unit->scope);
 
        initialize_builtin_types();
 
@@ -5605,12 +5832,13 @@ static translation_unit_t *parse_translation_unit(void)
                }
        }
 
-       assert(context == &unit->context);
-       context          = NULL;
+       assert(scope == &unit->scope);
+       scope          = NULL;
        last_declaration = NULL;
 
-       assert(global_context == &unit->context);
-       global_context = NULL;
+       assert(global_scope == &unit->scope);
+       check_unused_globals();
+       global_scope = NULL;
 
        return unit;
 }