Do not panic, when the expression walker of the statement walker encounters an invali...
[cparser] / parser.c
index 686912f..cb0147a 100644 (file)
--- a/parser.c
+++ b/parser.c
 #include "adt/error.h"
 #include "adt/array.h"
 
-/** if wchar_t is equal to unsigned short. */
-bool opt_short_wchar_t =
-#ifdef _WIN32
-       true;
-#else
-       false;
-#endif
-
 //#define PRINT_TOKENS
 #define MAX_LOOKAHEAD 2
 
 typedef struct {
-       entity_t    *old_entity;
-       symbol_t    *symbol;
-       namespace_t  namespc;
+       entity_t           *old_entity;
+       symbol_t           *symbol;
+       entity_namespace_t  namespc;
 } stack_entry_t;
 
 typedef struct argument_list_t argument_list_t;
@@ -115,11 +107,8 @@ 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 stack_entry_t      *local_label_stack = NULL;
-/** The global file scope. */
 static scope_t            *file_scope        = NULL;
-/** The current scope. */
-static scope_t            *scope             = NULL;
+static scope_t            *current_scope     = NULL;
 /** Point to the current function declaration if inside a function. */
 static function_t         *current_function  = NULL;
 static entity_t           *current_init_decl = NULL;
@@ -127,6 +116,7 @@ static switch_statement_t *current_switch    = NULL;
 static statement_t        *current_loop      = NULL;
 static statement_t        *current_parent    = NULL;
 static ms_try_statement_t *current_try       = NULL;
+static linkage_kind_t      current_linkage   = LINKAGE_INVALID;
 static goto_statement_t   *goto_first        = NULL;
 static goto_statement_t   *goto_last         = NULL;
 static label_statement_t  *label_first       = NULL;
@@ -185,6 +175,8 @@ static statement_t *parse_statement(void);
 static expression_t *parse_sub_expression(precedence_t);
 static expression_t *parse_expression(void);
 static type_t       *parse_typename(void);
+static void          parse_externals(void);
+static void          parse_external(void);
 
 static void parse_compound_type_entries(compound_t *compound_declaration);
 static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
@@ -202,6 +194,13 @@ static void semantic_comparison(binary_expression_t *expression);
        case T_register:        \
        case T___thread:
 
+#define STORAGE_CLASSES_NO_EXTERN \
+       case T_typedef:         \
+       case T_static:          \
+       case T_auto:            \
+       case T_register:        \
+       case T___thread:
+
 #define TYPE_QUALIFIERS     \
        case T_const:           \
        case T_restrict:        \
@@ -210,33 +209,29 @@ static void semantic_comparison(binary_expression_t *expression);
        case T__forceinline:    \
        case T___attribute__:
 
-#ifdef PROVIDE_COMPLEX
 #define COMPLEX_SPECIFIERS  \
        case T__Complex:
 #define IMAGINARY_SPECIFIERS \
        case T__Imaginary:
-#else
-#define COMPLEX_SPECIFIERS
-#define IMAGINARY_SPECIFIERS
-#endif
 
 #define TYPE_SPECIFIERS       \
-       case T_void:              \
+       case T__Bool:             \
+       case T___builtin_va_list: \
+       case T___typeof__:        \
+       case T__declspec:         \
+       case T_bool:              \
        case T_char:              \
-       case T_short:             \
+       case T_double:            \
+       case T_enum:              \
+       case T_float:             \
        case T_int:               \
        case T_long:              \
-       case T_float:             \
-       case T_double:            \
+       case T_short:             \
        case T_signed:            \
-       case T_unsigned:          \
-       case T__Bool:             \
        case T_struct:            \
        case T_union:             \
-       case T_enum:              \
-       case T___typeof__:        \
-       case T___builtin_va_list: \
-       case T__declspec:         \
+       case T_unsigned:          \
+       case T_void:              \
        COMPLEX_SPECIFIERS        \
        IMAGINARY_SPECIFIERS
 
@@ -245,6 +240,11 @@ static void semantic_comparison(binary_expression_t *expression);
        TYPE_QUALIFIERS         \
        TYPE_SPECIFIERS
 
+#define DECLARATION_START_NO_EXTERN \
+       STORAGE_CLASSES_NO_EXTERN       \
+       TYPE_QUALIFIERS                 \
+       TYPE_SPECIFIERS
+
 #define TYPENAME_START      \
        TYPE_QUALIFIERS         \
        TYPE_SPECIFIERS
@@ -296,9 +296,11 @@ static void semantic_comparison(binary_expression_t *expression);
        case T___func__:                 \
        case T___noop:                   \
        case T__assume:                  \
-       case T_sizeof:                   \
        case T_delete:                   \
-       case T_throw:
+       case T_false:                    \
+       case T_sizeof:                   \
+       case T_throw:                    \
+       case T_true:
 
 /**
  * Allocate an AST node with given size and
@@ -323,9 +325,10 @@ static size_t get_entity_struct_size(entity_kind_t kind)
                [ENTITY_ENUM]            = sizeof(enum_t),
                [ENTITY_ENUM_VALUE]      = sizeof(enum_value_t),
                [ENTITY_LABEL]           = sizeof(label_t),
-               [ENTITY_LOCAL_LABEL]     = sizeof(label_t)
+               [ENTITY_LOCAL_LABEL]     = sizeof(label_t),
+               [ENTITY_NAMESPACE]       = sizeof(namespace_t)
        };
-       assert(kind <= sizeof(sizes) / sizeof(sizes[0]));
+       assert(kind < sizeof(sizes) / sizeof(sizes[0]));
        assert(sizes[kind] != 0);
        return sizes[kind];
 }
@@ -367,7 +370,7 @@ static size_t get_statement_struct_size(statement_kind_t kind)
                [STATEMENT_MS_TRY]      = sizeof(ms_try_statement_t),
                [STATEMENT_LEAVE]       = sizeof(leave_statement_t)
        };
-       assert(kind <= sizeof(sizes) / sizeof(sizes[0]));
+       assert(kind < sizeof(sizes) / sizeof(sizes[0]));
        assert(sizes[kind] != 0);
        return sizes[kind];
 }
@@ -414,7 +417,7 @@ static size_t get_expression_struct_size(expression_kind_t kind)
        if (kind >= EXPR_BINARY_FIRST && kind <= EXPR_BINARY_LAST) {
                return sizes[EXPR_BINARY_FIRST];
        }
-       assert(kind <= sizeof(sizes) / sizeof(sizes[0]));
+       assert(kind < sizeof(sizes) / sizeof(sizes[0]));
        assert(sizes[kind] != 0);
        return sizes[kind];
 }
@@ -443,8 +446,9 @@ 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.type = type_error_type;
+       res->base.kind            = kind;
+       res->base.type            = type_error_type;
+       res->base.source_position = token.source_position;
        return res;
 }
 
@@ -453,9 +457,7 @@ static expression_t *allocate_expression_zero(expression_kind_t kind)
  */
 static expression_t *create_invalid_expression(void)
 {
-       expression_t *expression         = allocate_expression_zero(EXPR_INVALID);
-       expression->base.source_position = token.source_position;
-       return expression;
+       return allocate_expression_zero(EXPR_INVALID);
 }
 
 /**
@@ -573,14 +575,6 @@ static size_t label_top(void)
        return ARR_LEN(label_stack);
 }
 
-/**
- * Returns the index of the top element of the local label stack.
- */
-static size_t local_label_top(void)
-{
-       return ARR_LEN(local_label_stack);
-}
-
 /**
  * Return the next token.
  */
@@ -721,7 +715,7 @@ static void eat_block(void)
                next_token();
 }
 
-#define eat(token_type)  do { assert(token.type == token_type); next_token(); } while (0)
+#define eat(token_type)  do { assert(token.type == (token_type)); next_token(); } while (0)
 
 /**
  * Report a parse error because an expected token was not found.
@@ -781,22 +775,23 @@ static void type_error_incompatible(const char *msg,
 
 static void scope_push(scope_t *new_scope)
 {
-       if (scope != NULL) {
-               new_scope->depth = scope->depth + 1;
+       if (current_scope != NULL) {
+               new_scope->depth = current_scope->depth + 1;
        }
-       new_scope->parent = scope;
-       scope             = new_scope;
+       new_scope->parent = current_scope;
+       current_scope     = new_scope;
 }
 
 static void scope_pop(void)
 {
-       scope = scope->parent;
+       current_scope = current_scope->parent;
 }
 
 /**
  * Search an entity by its symbol in a given namespace.
  */
-static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc)
+static entity_t *get_entity(const symbol_t *const symbol,
+                            namespace_tag_t namespc)
 {
        entity_t *entity = symbol->entity;
        for( ; entity != NULL; entity = entity->base.symbol_next) {
@@ -813,8 +808,8 @@ static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc)
  */
 static void stack_push(stack_entry_t **stack_ptr, entity_t *entity)
 {
-       symbol_t    *symbol  = entity->base.symbol;
-       namespace_t  namespc = entity->base.namespc;
+       symbol_t           *symbol  = entity->base.symbol;
+       entity_namespace_t  namespc = entity->base.namespc;
        assert(namespc != NAMESPACE_INVALID);
 
        /* replace/add entity into entity list of the symbol */
@@ -863,18 +858,6 @@ static void label_push(entity_t *label)
        stack_push(&label_stack, label);
 }
 
-/**
- * Push a declaration of the local label stack.
- *
- * @param declaration  the declaration
- */
-static void local_label_push(entity_t *label)
-{
-       assert(label->base.parent_scope != NULL);
-       label->base.parent_scope = scope;
-       stack_push(&local_label_stack, label);
-}
-
 /**
  * pops symbols from the environment stack until @p new_top is the top element
  */
@@ -891,9 +874,9 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top)
        for(i = top; i > new_top; --i) {
                stack_entry_t *entry = &stack[i - 1];
 
-               entity_t    *old_entity = entry->old_entity;
-               symbol_t    *symbol     = entry->symbol;
-               namespace_t  namespc    = entry->namespc;
+               entity_t           *old_entity = entry->old_entity;
+               symbol_t           *symbol     = entry->symbol;
+               entity_namespace_t  namespc    = entry->namespc;
 
                /* replace with old_entity/remove */
                entity_t **anchor;
@@ -941,18 +924,6 @@ static void label_pop_to(size_t new_top)
        stack_pop_to(&label_stack, new_top);
 }
 
-/**
- * Pop all entries from the local label stack until the new_top
- * is reached.
- *
- * @param new_top  the new stack top
- */
-static void local_label_pop_to(size_t new_top)
-{
-       stack_pop_to(&local_label_stack, new_top);
-}
-
-
 static int get_akind_rank(atomic_type_kind_t akind)
 {
        return (int) akind;
@@ -1194,25 +1165,6 @@ static expression_t *parse_assignment_expression(void)
        return parse_sub_expression(PREC_ASSIGNMENT);
 }
 
-static type_t *make_global_typedef(const char *name, type_t *type)
-{
-       symbol_t *const symbol = symbol_table_insert(name);
-
-       entity_t *const entity       = allocate_entity_zero(ENTITY_TYPEDEF);
-       entity->base.symbol          = symbol;
-       entity->base.source_position = builtin_source_position;
-       entity->base.namespc         = NAMESPACE_NORMAL;
-       entity->typedefe.type        = type;
-       entity->typedefe.builtin     = true;
-
-       record_entity(entity, false);
-
-       type_t *typedef_type            = allocate_type_zero(TYPE_TYPEDEF);
-       typedef_type->typedeft.typedefe = &entity->typedefe;
-
-       return typedef_type;
-}
-
 static string_t parse_string_literals(void)
 {
        assert(token.type == T_STRING_LITERAL);
@@ -2926,7 +2878,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
                result = parse_scalar_initializer(type, env->must_be_constant);
        }
 
-       /* § 6.7.5 (22)  array initializers for arrays with unknown size determine
+       /* § 6.7.8 (22) array initializers for arrays with unknown size determine
         * the array type size */
        if (is_type_array(type) && type->array.size_expression == NULL
                        && result != NULL) {
@@ -2960,9 +2912,10 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
 
                type_t *new_type = duplicate_type(type);
 
-               new_type->array.size_expression = cnst;
-               new_type->array.size_constant   = true;
-               new_type->array.size            = size;
+               new_type->array.size_expression   = cnst;
+               new_type->array.size_constant     = true;
+               new_type->array.has_implicit_size = true;
+               new_type->array.size              = size;
                env->type = new_type;
        }
 
@@ -3003,20 +2956,20 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                symbol = token.v.symbol;
                next_token();
 
-               namespace_t const namespc =
+               namespace_tag_t const namespc =
                        is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION;
                entity_t *entity = get_entity(symbol, namespc);
                if (entity != NULL) {
                        assert(entity->kind == (is_struct ? ENTITY_STRUCT : ENTITY_UNION));
                        compound = &entity->compound;
-                       if (compound->base.parent_scope != scope &&
+                       if (compound->base.parent_scope != current_scope &&
                            (token.type == '{' || token.type == ';')) {
                                /* we're in an inner scope and have a definition. Override
                                   existing definition in outer scope */
                                compound = NULL;
                        } else if (compound->complete && token.type == '{') {
                                assert(symbol != NULL);
-                               errorf(HERE, "multiple definitions of '%s %Y' (previous definition at %P)",
+                               errorf(HERE, "multiple definitions of '%s %Y' (previous definition %P)",
                                       is_struct ? "struct" : "union", symbol,
                                       &compound->base.source_position);
                                /* clear members in the hope to avoid further errors */
@@ -3044,11 +2997,11 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                        (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION);
                compound->base.source_position = token.source_position;
                compound->base.symbol          = symbol;
-               compound->base.parent_scope    = scope;
+               compound->base.parent_scope    = current_scope;
                if (symbol != NULL) {
                        environment_push(entity);
                }
-               append_entity(scope, entity);
+               append_entity(current_scope, entity);
        }
 
        if (token.type == '{') {
@@ -3138,7 +3091,7 @@ static type_t *parse_enum_specifier(void)
                entity->base.namespc         = NAMESPACE_ENUM;
                entity->base.source_position = token.source_position;
                entity->base.symbol          = symbol;
-               entity->base.parent_scope    = scope;
+               entity->base.parent_scope    = current_scope;
        }
 
        type_t *const type = allocate_type_zero(TYPE_ENUM);
@@ -3146,13 +3099,13 @@ static type_t *parse_enum_specifier(void)
 
        if (token.type == '{') {
                if (entity->enume.complete) {
-                       errorf(HERE, "multiple definitions of enum %Y (previous definition at %P)",
+                       errorf(HERE, "multiple definitions of enum %Y (previous definition %P)",
                               symbol, &entity->base.source_position);
                }
                if (symbol != NULL) {
                        environment_push(entity);
                }
-               append_entity(scope, entity);
+               append_entity(current_scope, entity);
                entity->enume.complete = true;
 
                parse_enum_entries(type);
@@ -3442,7 +3395,10 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
        entity->base.source_position = *HERE;
        entity->base.symbol          = symbol;
        if (is_declaration(entity)) {
+               entity->declaration.type     = type_error_type;
                entity->declaration.implicit = true;
+       } else if (kind == ENTITY_TYPEDEF) {
+               entity->typedefe.type = type_error_type;
        }
        record_entity(entity, false);
        return entity;
@@ -3636,30 +3592,31 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                /* type specifiers */
 #define MATCH_SPECIFIER(token, specifier, name)                         \
                case token:                                                     \
-                       next_token();                                               \
                        if (type_specifiers & specifier) {                           \
                                errorf(HERE, "multiple " name " type specifiers given"); \
                        } else {                                                    \
                                type_specifiers |= specifier;                           \
                        }                                                           \
+                       next_token();                                               \
                        break
 
-               MATCH_SPECIFIER(T_void,       SPECIFIER_VOID,      "void");
-               MATCH_SPECIFIER(T_char,       SPECIFIER_CHAR,      "char");
-               MATCH_SPECIFIER(T_short,      SPECIFIER_SHORT,     "short");
-               MATCH_SPECIFIER(T_int,        SPECIFIER_INT,       "int");
-               MATCH_SPECIFIER(T_float,      SPECIFIER_FLOAT,     "float");
-               MATCH_SPECIFIER(T_double,     SPECIFIER_DOUBLE,    "double");
-               MATCH_SPECIFIER(T_signed,     SPECIFIER_SIGNED,    "signed");
-               MATCH_SPECIFIER(T_unsigned,   SPECIFIER_UNSIGNED,  "unsigned");
                MATCH_SPECIFIER(T__Bool,      SPECIFIER_BOOL,      "_Bool");
-               MATCH_SPECIFIER(T__int8,      SPECIFIER_INT8,      "_int8");
+               MATCH_SPECIFIER(T__Complex,   SPECIFIER_COMPLEX,   "_Complex");
+               MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary");
+               MATCH_SPECIFIER(T__int128,    SPECIFIER_INT128,    "_int128");
                MATCH_SPECIFIER(T__int16,     SPECIFIER_INT16,     "_int16");
                MATCH_SPECIFIER(T__int32,     SPECIFIER_INT32,     "_int32");
                MATCH_SPECIFIER(T__int64,     SPECIFIER_INT64,     "_int64");
-               MATCH_SPECIFIER(T__int128,    SPECIFIER_INT128,    "_int128");
-               MATCH_SPECIFIER(T__Complex,   SPECIFIER_COMPLEX,   "_Complex");
-               MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary");
+               MATCH_SPECIFIER(T__int8,      SPECIFIER_INT8,      "_int8");
+               MATCH_SPECIFIER(T_bool,       SPECIFIER_BOOL,      "bool");
+               MATCH_SPECIFIER(T_char,       SPECIFIER_CHAR,      "char");
+               MATCH_SPECIFIER(T_double,     SPECIFIER_DOUBLE,    "double");
+               MATCH_SPECIFIER(T_float,      SPECIFIER_FLOAT,     "float");
+               MATCH_SPECIFIER(T_int,        SPECIFIER_INT,       "int");
+               MATCH_SPECIFIER(T_short,      SPECIFIER_SHORT,     "short");
+               MATCH_SPECIFIER(T_signed,     SPECIFIER_SIGNED,    "signed");
+               MATCH_SPECIFIER(T_unsigned,   SPECIFIER_UNSIGNED,  "unsigned");
+               MATCH_SPECIFIER(T_void,       SPECIFIER_VOID,      "void");
 
                case T__forceinline:
                        /* only in microsoft mode */
@@ -3672,7 +3629,6 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        break;
 
                case T_long:
-                       next_token();
                        if (type_specifiers & SPECIFIER_LONG_LONG) {
                                errorf(HERE, "multiple type specifiers given");
                        } else if (type_specifiers & SPECIFIER_LONG) {
@@ -3680,6 +3636,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        } else {
                                type_specifiers |= SPECIFIER_LONG;
                        }
+                       next_token();
                        break;
 
                case T_struct: {
@@ -4248,6 +4205,8 @@ static construct_type_t *parse_function_declarator(scope_t *scope)
 {
        type_t *type = allocate_type_zero(TYPE_FUNCTION);
 
+       type->function.linkage = current_linkage;
+
        /* TODO: revive this... once we know exactly how to do it */
 #if 0
        decl_modifiers_t  modifiers = entity->declaration.modifiers;
@@ -4634,7 +4593,8 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                storage_class_t storage_class = specifiers->storage_class;
                entity->declaration.declared_storage_class = storage_class;
 
-               if (storage_class == STORAGE_CLASS_NONE && scope != file_scope) {
+               if (storage_class == STORAGE_CLASS_NONE
+                               && current_scope != file_scope) {
                        storage_class = STORAGE_CLASS_AUTO;
                }
                entity->declaration.storage_class = storage_class;
@@ -4726,6 +4686,34 @@ static bool is_sym_main(const symbol_t *const sym)
        return strcmp(sym->string, "main") == 0;
 }
 
+static const char *get_entity_kind_name(entity_kind_t kind)
+{
+       switch ((entity_kind_tag_t) kind) {
+       case ENTITY_FUNCTION:        return "function";
+       case ENTITY_VARIABLE:        return "variable";
+       case ENTITY_COMPOUND_MEMBER: return "compound type member";
+       case ENTITY_STRUCT:          return "struct";
+       case ENTITY_UNION:           return "union";
+       case ENTITY_ENUM:            return "enum";
+       case ENTITY_ENUM_VALUE:      return "enum value";
+       case ENTITY_LABEL:           return "label";
+       case ENTITY_LOCAL_LABEL:     return "local label";
+       case ENTITY_TYPEDEF:         return "typedef";
+       case ENTITY_NAMESPACE:       return "namespace";
+       case ENTITY_INVALID:         break;
+       }
+
+       panic("Invalid entity kind encountered in get_entity_kind_name");
+}
+
+static void error_redefined_as_different_kind(const source_position_t *pos,
+               const entity_t *old, entity_kind_t new_kind)
+{
+       errorf(pos, "redeclaration of %s '%Y' as %s (declared %P)",
+              get_entity_kind_name(old->kind), old->base.symbol,
+              get_entity_kind_name(new_kind), &old->base.source_position);
+}
+
 /**
  * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
  * for various problems that occur for multiple definitions
@@ -4733,7 +4721,7 @@ static bool is_sym_main(const symbol_t *const sym)
 static entity_t *record_entity(entity_t *entity, const bool is_definition)
 {
        const symbol_t *const    symbol  = entity->base.symbol;
-       const namespace_t        namespc = entity->base.namespc;
+       const namespace_tag_t    namespc = (namespace_tag_t)entity->base.namespc;
        const source_position_t *pos     = &entity->base.source_position;
 
        assert(symbol != NULL);
@@ -4753,7 +4741,8 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
                                         orig_type, symbol);
                }
 
-               if (warning.main && scope == file_scope && is_sym_main(symbol)) {
+               if (warning.main && current_scope == file_scope
+                               && is_sym_main(symbol)) {
                        check_type_of_main(entity);
                }
        }
@@ -4761,7 +4750,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
        if (is_declaration(entity)) {
                if (warning.nested_externs
                                && entity->declaration.storage_class == STORAGE_CLASS_EXTERN
-                               && scope != file_scope) {
+                               && current_scope != file_scope) {
                        warningf(pos, "nested extern declaration of '%#T'",
                                 entity->declaration.type, symbol);
                }
@@ -4769,7 +4758,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
 
        if (previous_entity != NULL
            && previous_entity->base.parent_scope == &current_function->parameters
-               && scope->depth == previous_entity->base.parent_scope->depth + 1) {
+               && current_scope->depth == previous_entity->base.parent_scope->depth+1){
 
                assert(previous_entity->kind == ENTITY_VARIABLE);
                errorf(pos,
@@ -4781,12 +4770,11 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
        }
 
        if (previous_entity != NULL
-                       && previous_entity->base.parent_scope == scope) {
+                       && previous_entity->base.parent_scope == current_scope) {
 
                if (previous_entity->kind != entity->kind) {
-                       errorf(pos,
-                              "redeclaration of '%Y' as different kind of symbol (declared %P)",
-                              symbol, &previous_entity->base.source_position);
+                       error_redefined_as_different_kind(pos, previous_entity,
+                                                         entity->kind);
                        goto finish;
                }
                if (previous_entity->kind == ENTITY_ENUM_VALUE) {
@@ -4943,7 +4931,7 @@ error_redeclaration:
                }
        } else if (warning.missing_declarations
                        && entity->kind == ENTITY_VARIABLE
-                       && scope == file_scope) {
+                       && current_scope == file_scope) {
                declaration_t *declaration = &entity->declaration;
                if (declaration->storage_class == STORAGE_CLASS_NONE ||
                                declaration->storage_class == STORAGE_CLASS_THREAD) {
@@ -4954,12 +4942,12 @@ error_redeclaration:
 
 finish:
        assert(entity->base.parent_scope == NULL);
-       assert(scope != NULL);
+       assert(current_scope != NULL);
 
-       entity->base.parent_scope = scope;
+       entity->base.parent_scope = current_scope;
        entity->base.namespc      = NAMESPACE_NORMAL;
        environment_push(entity);
-       append_entity(scope, entity);
+       append_entity(current_scope, entity);
 
        return entity;
 }
@@ -5108,7 +5096,7 @@ static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition)
        assert(entity->base.namespc == NAMESPACE_NORMAL);
        entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL);
        if (previous_entity == NULL
-                       || previous_entity->base.parent_scope != scope) {
+                       || previous_entity->base.parent_scope != current_scope) {
                errorf(HERE, "expected declaration of a function parameter, found '%Y'",
                       symbol);
                return entity;
@@ -5172,7 +5160,7 @@ static void parse_kr_declaration_list(entity_t *entity)
        entity_t *parameter = entity->function.parameters.entities;
        for ( ; parameter != NULL; parameter = parameter->base.next) {
                assert(parameter->base.parent_scope == NULL);
-               parameter->base.parent_scope = scope;
+               parameter->base.parent_scope = current_scope;
                environment_push(parameter);
        }
 
@@ -5182,7 +5170,7 @@ static void parse_kr_declaration_list(entity_t *entity)
        }
 
        /* pop function parameters */
-       assert(scope == &entity->function.parameters);
+       assert(current_scope == &entity->function.parameters);
        scope_pop();
        environment_pop_to(top);
 
@@ -5417,6 +5405,7 @@ static bool expression_returns(expression_t const *const expr)
                case EXPR_BUILTIN_CONSTANT_P:
                case EXPR_BUILTIN_PREFETCH:
                case EXPR_OFFSETOF:
+               case EXPR_INVALID:
                case EXPR_STATEMENT: // TODO implement
                        return true;
 
@@ -5455,7 +5444,6 @@ static bool expression_returns(expression_t const *const expr)
                                expression_returns(expr->binary.right);
 
                case EXPR_UNKNOWN:
-               case EXPR_INVALID:
                        break;
        }
 
@@ -5901,11 +5889,9 @@ static void parse_external_declaration(void)
        }
 
        assert(is_declaration(ndeclaration));
-       type_t *type = ndeclaration->declaration.type;
+       type_t *type = skip_typeref(ndeclaration->declaration.type);
 
-       /* note that we don't skip typerefs: the standard doesn't allow them here
-        * (so we can't use is_type_function here) */
-       if (type->kind != TYPE_FUNCTION) {
+       if (!is_type_function(type)) {
                if (is_type_valid(type)) {
                        errorf(HERE, "declarator '%#T' has a body but is not a function type",
                               type, ndeclaration->base.symbol);
@@ -5961,11 +5947,11 @@ static void parse_external_declaration(void)
        entity_t *parameter = function->parameters.entities;
        for( ; parameter != NULL; parameter = parameter->base.next) {
                if (parameter->base.parent_scope == &ndeclaration->function.parameters) {
-                       parameter->base.parent_scope = scope;
+                       parameter->base.parent_scope = current_scope;
                }
                assert(parameter->base.parent_scope == NULL
-                               || parameter->base.parent_scope == scope);
-               parameter->base.parent_scope = scope;
+                               || parameter->base.parent_scope == current_scope);
+               parameter->base.parent_scope = current_scope;
                if (parameter->base.symbol == NULL) {
                        errorf(&parameter->base.source_position, "parameter name omitted");
                        continue;
@@ -6011,7 +5997,7 @@ static void parse_external_declaration(void)
                label_pop_to(label_stack_top);
        }
 
-       assert(scope == &function->parameters);
+       assert(current_scope == &function->parameters);
        scope_pop();
        environment_pop_to(top);
 }
@@ -6106,30 +6092,17 @@ static void parse_compound_declarators(compound_t *compound,
                        entity->declaration.type                   = type;
                } else {
                        entity = parse_declarator(specifiers,/*may_be_abstract=*/true, true);
-
-                       assert(is_declaration(entity));
-                       type_t *orig_type = entity->declaration.type;
-                       type_t *type      = skip_typeref(orig_type);
+                       assert(entity->kind == ENTITY_COMPOUND_MEMBER);
 
                        if (token.type == ':') {
                                source_position_t source_position = *HERE;
                                next_token();
                                expression_t *size = parse_constant_expression();
 
-                               type_t *bitfield_type = make_bitfield_type(orig_type, size,
+                               type_t *type = entity->declaration.type;
+                               type_t *bitfield_type = make_bitfield_type(type, size,
                                                &source_position, entity->base.symbol);
                                entity->declaration.type = bitfield_type;
-                       } else {
-                               /* TODO we ignore arrays for now... what is missing is a check
-                                * that they're at the end of the struct */
-                               if (is_type_incomplete(type) && !is_type_array(type)) {
-                                       errorf(HERE,
-                                              "compound member '%Y' has incomplete type '%T'",
-                                              entity->base.symbol, orig_type);
-                               } else if (is_type_function(type)) {
-                                       errorf(HERE, "compound member '%Y' must not have function type '%T'",
-                                              entity->base.symbol, orig_type);
-                               }
                        }
                }
 
@@ -6158,6 +6131,32 @@ end_error:
        ;
 }
 
+static void semantic_compound(compound_t *compound)
+{
+       entity_t *entity = compound->members.entities;
+       for ( ; entity != NULL; entity = entity->base.next) {
+               assert(entity->kind == ENTITY_COMPOUND_MEMBER);
+
+               type_t *orig_type = entity->declaration.type;
+               type_t *type      = skip_typeref(orig_type);
+
+               if (is_type_function(type)) {
+                       errorf(HERE,
+                              "compound member '%Y' must not have function type '%T'",
+                              entity->base.symbol, orig_type);
+               } else if (is_type_incomplete(type)) {
+                       /* §6.7.2.1 (16) flexible array member */
+                       if (is_type_array(type) && entity->base.next == NULL) {
+                               compound->has_flexible_member = true;
+                       } else {
+                               errorf(HERE,
+                                      "compound member '%Y' has incomplete type '%T'",
+                                      entity->base.symbol, orig_type);
+                       }
+               }
+       }
+}
+
 static void parse_compound_type_entries(compound_t *compound)
 {
        eat('{');
@@ -6174,6 +6173,7 @@ static void parse_compound_type_entries(compound_t *compound)
 
                parse_compound_declarators(compound, &specifiers);
        }
+       semantic_compound(compound);
        rem_anchor_token('}');
        next_token();
 }
@@ -6274,15 +6274,28 @@ static expression_t *parse_string_const(void)
        }
 }
 
+/**
+ * Parse a boolean constant.
+ */
+static expression_t *parse_bool_const(bool value)
+{
+       expression_t *cnst       = allocate_expression_zero(EXPR_CONST);
+       cnst->base.type          = type_bool;
+       cnst->conste.v.int_value = value;
+
+       next_token();
+
+       return cnst;
+}
+
 /**
  * Parse an integer constant.
  */
 static expression_t *parse_int_const(void)
 {
-       expression_t *cnst         = allocate_expression_zero(EXPR_CONST);
-       cnst->base.source_position = *HERE;
-       cnst->base.type            = token.datatype;
-       cnst->conste.v.int_value   = token.v.intvalue;
+       expression_t *cnst       = allocate_expression_zero(EXPR_CONST);
+       cnst->base.type          = token.datatype;
+       cnst->conste.v.int_value = token.v.intvalue;
 
        next_token();
 
@@ -6295,10 +6308,8 @@ static expression_t *parse_int_const(void)
 static expression_t *parse_character_constant(void)
 {
        expression_t *cnst = allocate_expression_zero(EXPR_CHARACTER_CONSTANT);
-
-       cnst->base.source_position = *HERE;
-       cnst->base.type            = token.datatype;
-       cnst->conste.v.character   = token.v.string;
+       cnst->base.type          = token.datatype;
+       cnst->conste.v.character = token.v.string;
 
        if (cnst->conste.v.character.size != 1) {
                if (warning.multichar && GNU_MODE) {
@@ -6318,8 +6329,6 @@ static expression_t *parse_character_constant(void)
 static expression_t *parse_wide_character_constant(void)
 {
        expression_t *cnst = allocate_expression_zero(EXPR_WIDE_CHARACTER_CONSTANT);
-
-       cnst->base.source_position    = *HERE;
        cnst->base.type               = token.datatype;
        cnst->conste.v.wide_character = token.v.wide_string;
 
@@ -6594,6 +6603,11 @@ static expression_t *parse_reference(void)
                orig_type = entity->declaration.type;
        } else if (entity->kind == ENTITY_ENUM_VALUE) {
                orig_type = entity->enum_value.enum_type;
+       } else if (entity->kind == ENTITY_TYPEDEF) {
+               errorf(HERE, "encountered typedef name '%Y' while parsing expression",
+                       symbol);
+               next_token();
+               return create_invalid_expression();
        } else {
                panic("expected declaration or enum value in reference");
        }
@@ -6730,7 +6744,7 @@ static expression_t *parse_cast(void)
 
        source_position_t source_position = token.source_position;
 
-       type_t *type  = parse_typename();
+       type_t *type = parse_typename();
 
        rem_anchor_token(')');
        expect(')');
@@ -6764,9 +6778,8 @@ static expression_t *parse_statement_expression(void)
 
        expression_t *expression = allocate_expression_zero(EXPR_STATEMENT);
 
-       statement_t *statement           = parse_compound_statement(true);
-       expression->statement.statement  = statement;
-       expression->base.source_position = statement->base.source_position;
+       statement_t *statement          = parse_compound_statement(true);
+       expression->statement.statement = statement;
 
        /* find last statement and use its type */
        type_t *type = type_void;
@@ -6822,7 +6835,6 @@ end_error:
 
 static expression_t *parse_function_keyword(void)
 {
-       next_token();
        /* TODO */
 
        if (current_function == NULL) {
@@ -6833,13 +6845,13 @@ static expression_t *parse_function_keyword(void)
        expression->base.type     = type_char_ptr;
        expression->funcname.kind = FUNCNAME_FUNCTION;
 
+       next_token();
+
        return expression;
 }
 
 static expression_t *parse_pretty_function_keyword(void)
 {
-       eat(T___PRETTY_FUNCTION__);
-
        if (current_function == NULL) {
                errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function");
        }
@@ -6848,13 +6860,13 @@ static expression_t *parse_pretty_function_keyword(void)
        expression->base.type     = type_char_ptr;
        expression->funcname.kind = FUNCNAME_PRETTY_FUNCTION;
 
+       eat(T___PRETTY_FUNCTION__);
+
        return expression;
 }
 
 static expression_t *parse_funcsig_keyword(void)
 {
-       eat(T___FUNCSIG__);
-
        if (current_function == NULL) {
                errorf(HERE, "'__FUNCSIG__' used outside of a function");
        }
@@ -6863,13 +6875,13 @@ static expression_t *parse_funcsig_keyword(void)
        expression->base.type     = type_char_ptr;
        expression->funcname.kind = FUNCNAME_FUNCSIG;
 
+       eat(T___FUNCSIG__);
+
        return expression;
 }
 
 static expression_t *parse_funcdname_keyword(void)
 {
-       eat(T___FUNCDNAME__);
-
        if (current_function == NULL) {
                errorf(HERE, "'__FUNCDNAME__' used outside of a function");
        }
@@ -6878,6 +6890,8 @@ static expression_t *parse_funcdname_keyword(void)
        expression->base.type     = type_char_ptr;
        expression->funcname.kind = FUNCNAME_FUNCDNAME;
 
+       eat(T___FUNCDNAME__);
+
        return expression;
 }
 
@@ -6941,11 +6955,11 @@ end_error:
  */
 static expression_t *parse_offsetof(void)
 {
-       eat(T___builtin_offsetof);
-
        expression_t *expression = allocate_expression_zero(EXPR_OFFSETOF);
        expression->base.type    = type_size_t;
 
+       eat(T___builtin_offsetof);
+
        expect('(');
        add_anchor_token(',');
        type_t *type = parse_typename();
@@ -6982,10 +6996,10 @@ end_error:
  */
 static expression_t *parse_va_start(void)
 {
-       eat(T___builtin_va_start);
-
        expression_t *expression = allocate_expression_zero(EXPR_VA_START);
 
+       eat(T___builtin_va_start);
+
        expect('(');
        add_anchor_token(',');
        expression->va_starte.ap = parse_assignment_expression();
@@ -7015,10 +7029,10 @@ end_error:
  */
 static expression_t *parse_va_arg(void)
 {
-       eat(T___builtin_va_arg);
-
        expression_t *expression = allocate_expression_zero(EXPR_VA_ARG);
 
+       eat(T___builtin_va_arg);
+
        expect('(');
        expression->va_arge.ap = parse_assignment_expression();
        expect(',');
@@ -7051,10 +7065,10 @@ static expression_t *parse_builtin_symbol(void)
  */
 static expression_t *parse_builtin_constant(void)
 {
-       eat(T___builtin_constant_p);
-
        expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_CONSTANT_P);
 
+       eat(T___builtin_constant_p);
+
        expect('(');
        add_anchor_token(')');
        expression->builtin_constant.value = parse_assignment_expression();
@@ -7072,10 +7086,10 @@ end_error:
  */
 static expression_t *parse_builtin_prefetch(void)
 {
-       eat(T___builtin_prefetch);
-
        expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_PREFETCH);
 
+       eat(T___builtin_prefetch);
+
        expect('(');
        add_anchor_token(')');
        expression->builtin_prefetch.adr = parse_assignment_expression();
@@ -7159,11 +7173,11 @@ end_error:
  */
 static expression_t *parse_builtin_expect(void)
 {
-       eat(T___builtin_expect);
-
        expression_t *expression
                = allocate_expression_zero(EXPR_BINARY_BUILTIN_EXPECT);
 
+       eat(T___builtin_expect);
+
        expect('(');
        expression->binary.left = parse_assignment_expression();
        expect(',');
@@ -7183,10 +7197,9 @@ end_error:
  */
 static expression_t *parse_assume(void)
 {
-       eat(T__assume);
+       expression_t *expression = allocate_expression_zero(EXPR_UNARY_ASSUME);
 
-       expression_t *expression
-               = allocate_expression_zero(EXPR_UNARY_ASSUME);
+       eat(T__assume);
 
        expect('(');
        add_anchor_token(')');
@@ -7210,11 +7223,11 @@ static label_t *get_label(symbol_t *symbol)
        entity_t *label;
        assert(current_function != NULL);
 
-       label = get_entity(symbol, NAMESPACE_LOCAL_LABEL);
+       label = get_entity(symbol, NAMESPACE_LABEL);
        /* if we found a local label, we already created the declaration */
        if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
-               if (label->base.parent_scope != scope) {
-                       assert(label->base.parent_scope->depth < scope->depth);
+               if (label->base.parent_scope != current_scope) {
+                       assert(label->base.parent_scope->depth < current_scope->depth);
                        current_function->goto_to_outer = true;
                }
                return &label->label;
@@ -7272,7 +7285,12 @@ end_error:
  */
 static expression_t *parse_noop_expression(void)
 {
-       source_position_t source_position = *HERE;
+       /* the result is a (int)0 */
+       expression_t *cnst         = allocate_expression_zero(EXPR_CONST);
+       cnst->base.type            = type_int;
+       cnst->conste.v.int_value   = 0;
+       cnst->conste.is_ms_noop    = true;
+
        eat(T___noop);
 
        if (token.type == '(') {
@@ -7294,17 +7312,8 @@ static expression_t *parse_noop_expression(void)
        rem_anchor_token(')');
        expect(')');
 
-       /* the result is a (int)0 */
-       expression_t *cnst         = allocate_expression_zero(EXPR_CONST);
-       cnst->base.source_position = source_position;
-       cnst->base.type            = type_int;
-       cnst->conste.v.int_value   = 0;
-       cnst->conste.is_ms_noop    = true;
-
-       return cnst;
-
 end_error:
-       return create_invalid_expression();
+       return cnst;
 }
 
 /**
@@ -7313,6 +7322,8 @@ end_error:
 static expression_t *parse_primary_expression(void)
 {
        switch (token.type) {
+               case T_false:                    return parse_bool_const(false);
+               case T_true:                     return parse_bool_const(true);
                case T_INTEGER:                  return parse_int_const();
                case T_CHARACTER_CONSTANT:       return parse_character_constant();
                case T_WIDE_CHARACTER_CONSTANT:  return parse_wide_character_constant();
@@ -7377,22 +7388,21 @@ static void check_for_char_index_type(const expression_t *expression)
 
 static expression_t *parse_array_expression(expression_t *left)
 {
+       expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS);
+
        eat('[');
        add_anchor_token(']');
 
        expression_t *inside = parse_expression();
 
-       expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS);
-
-       array_access_expression_t *array_access = &expression->array_access;
-
        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);
 
-       type_t *return_type;
+       type_t                    *return_type;
+       array_access_expression_t *array_access = &expression->array_access;
        if (is_type_pointer(type_left)) {
                return_type             = type_left->pointer.points_to;
                array_access->array_ref = left;
@@ -7418,20 +7428,17 @@ static expression_t *parse_array_expression(expression_t *left)
        expression->base.type = automatic_type_conversion(return_type);
 
        rem_anchor_token(']');
-       if (token.type == ']') {
-               next_token();
-       } else {
-               parse_error_expected("Problem while parsing array access", ']', NULL);
-       }
+       expect(']');
+end_error:
        return expression;
 }
 
-static expression_t *parse_typeprop(expression_kind_t const kind,
-                                    source_position_t const pos)
+static expression_t *parse_typeprop(expression_kind_t const kind)
 {
        expression_t  *tp_expression = allocate_expression_zero(kind);
-       tp_expression->base.type            = type_size_t;
-       tp_expression->base.source_position = pos;
+       tp_expression->base.type     = type_size_t;
+
+       eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__);
 
        char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
 
@@ -7472,7 +7479,8 @@ typeprop_expression:
                type->kind == TYPE_BITFIELD ? "bitfield"            :
                NULL;
        if (wrong_type != NULL) {
-               errorf(&pos, "operand of %s expression must not be of %s type '%T'",
+               errorf(&tp_expression->base.source_position,
+                               "operand of %s expression must not be of %s type '%T'",
                                what, wrong_type, orig_type);
        }
 
@@ -7483,28 +7491,23 @@ end_error:
 
 static expression_t *parse_sizeof(void)
 {
-       source_position_t pos = *HERE;
-       eat(T_sizeof);
-       return parse_typeprop(EXPR_SIZEOF, pos);
+       return parse_typeprop(EXPR_SIZEOF);
 }
 
 static expression_t *parse_alignof(void)
 {
-       source_position_t pos = *HERE;
-       eat(T___alignof__);
-       return parse_typeprop(EXPR_ALIGNOF, pos);
+       return parse_typeprop(EXPR_ALIGNOF);
 }
 
 static expression_t *parse_select_expression(expression_t *compound)
 {
-       assert(token.type == '.' || token.type == T_MINUSGREATER);
+       expression_t *select    = allocate_expression_zero(EXPR_SELECT);
+       select->select.compound = compound;
 
+       assert(token.type == '.' || token.type == T_MINUSGREATER);
        bool is_pointer = (token.type == T_MINUSGREATER);
        next_token();
 
-       expression_t *select    = allocate_expression_zero(EXPR_SELECT);
-       select->select.compound = compound;
-
        if (token.type != T_IDENTIFIER) {
                parse_error_expected("while parsing select", T_IDENTIFIER, NULL);
                return select;
@@ -7644,11 +7647,9 @@ static void check_call_argument(const function_parameter_t *parameter,
  */
 static expression_t *parse_call_expression(expression_t *expression)
 {
-       expression_t *result = allocate_expression_zero(EXPR_CALL);
-       result->base.source_position = expression->base.source_position;
-
-       call_expression_t *call = &result->call;
-       call->function          = expression;
+       expression_t      *result = allocate_expression_zero(EXPR_CALL);
+       call_expression_t *call   = &result->call;
+       call->function            = expression;
 
        type_t *const orig_type = expression->base.type;
        type_t *const type      = skip_typeref(orig_type);
@@ -7745,6 +7746,48 @@ static bool same_compound_type(const type_t *type1, const type_t *type2)
                type1->compound.compound == type2->compound.compound;
 }
 
+static expression_t const *get_reference_address(expression_t const *expr)
+{
+       bool regular_take_address = true;
+       for (;;) {
+               if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) {
+                       expr = expr->unary.value;
+               } else {
+                       regular_take_address = false;
+               }
+
+               if (expr->kind != EXPR_UNARY_DEREFERENCE)
+                       break;
+
+               expr = expr->unary.value;
+       }
+
+       if (expr->kind != EXPR_REFERENCE)
+               return NULL;
+
+       /* special case for functions which are automatically converted to a
+        * pointer to function without an extra TAKE_ADDRESS operation */
+       if (!regular_take_address &&
+                       expr->reference.entity->kind != ENTITY_FUNCTION) {
+               return NULL;
+       }
+
+       return expr;
+}
+
+static void warn_reference_address_as_bool(expression_t const* expr)
+{
+       if (!warning.address)
+               return;
+
+       expr = get_reference_address(expr);
+       if (expr != NULL) {
+               warningf(&expr->base.source_position,
+                        "the address of '%Y' will always evaluate as 'true'",
+                        expr->reference.entity->base.symbol);
+       }
+}
+
 /**
  * Parse a conditional expression, ie. 'expression ? ... : ...'.
  *
@@ -7755,8 +7798,9 @@ static expression_t *parse_conditional_expression(expression_t *expression)
        expression_t *result = allocate_expression_zero(EXPR_CONDITIONAL);
 
        conditional_expression_t *conditional = &result->conditional;
-       conditional->base.source_position = *HERE;
-       conditional->condition            = expression;
+       conditional->condition                = expression;
+
+       warn_reference_address_as_bool(expression);
 
        eat('?');
        add_anchor_token(':');
@@ -7773,8 +7817,9 @@ static expression_t *parse_conditional_expression(expression_t *expression)
        bool          gnu_cond = false;
        if (GNU_MODE && token.type == ':') {
                gnu_cond = true;
-       } else
+       } else {
                true_expression = parse_expression();
+       }
        rem_anchor_token(':');
        expect(':');
        expression_t *false_expression =
@@ -7908,11 +7953,11 @@ static expression_t *parse_extension(void)
  */
 static expression_t *parse_builtin_classify_type(void)
 {
-       eat(T___builtin_classify_type);
-
        expression_t *result = allocate_expression_zero(EXPR_CLASSIFY_TYPE);
        result->base.type    = type_int;
 
+       eat(T___builtin_classify_type);
+
        expect('(');
        add_anchor_token(')');
        expression_t *expression = parse_expression();
@@ -7932,8 +7977,7 @@ end_error:
 static expression_t *parse_delete(void)
 {
        expression_t *const result = allocate_expression_zero(EXPR_UNARY_DELETE);
-       result->base.source_position = *HERE;
-       result->base.type            = type_void;
+       result->base.type          = type_void;
 
        eat(T_delete);
 
@@ -7967,8 +8011,7 @@ end_error:;
 static expression_t *parse_throw(void)
 {
        expression_t *const result = allocate_expression_zero(EXPR_UNARY_THROW);
-       result->base.source_position = *HERE;
-       result->base.type            = type_void;
+       result->base.type          = type_void;
 
        eat(T_throw);
 
@@ -8097,45 +8140,6 @@ static void semantic_unexpr_plus(unary_expression_t *expression)
                        "traditional C rejects the unary plus operator");
 }
 
-static expression_t const *get_reference_address(expression_t const *expr)
-{
-       bool regular_take_address = true;
-       for (;;) {
-               if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) {
-                       expr = expr->unary.value;
-               } else {
-                       regular_take_address = false;
-               }
-
-               if (expr->kind != EXPR_UNARY_DEREFERENCE)
-                       break;
-
-               expr = expr->unary.value;
-       }
-
-       /* special case for functions which are automatically converted to a
-        * pointer to function without an extra TAKE_ADDRESS operation */
-       if (!regular_take_address && expr->kind == EXPR_REFERENCE
-                       && expr->reference.entity->kind == ENTITY_FUNCTION) {
-               return expr;
-       }
-
-       return NULL;
-}
-
-static void warn_function_address_as_bool(expression_t const* expr)
-{
-       if (!warning.address)
-               return;
-
-       expr = get_reference_address(expr);
-       if (expr != NULL) {
-               warningf(&expr->base.source_position,
-                        "the address of '%Y' will always evaluate as 'true'",
-                        expr->reference.entity->base.symbol);
-       }
-}
-
 static void semantic_not(unary_expression_t *expression)
 {
        type_t *const orig_type = expression->value->base.type;
@@ -8145,9 +8149,9 @@ static void semantic_not(unary_expression_t *expression)
                       "operand of ! must be of scalar type");
        }
 
-       warn_function_address_as_bool(expression->value);
+       warn_reference_address_as_bool(expression->value);
 
-       expression->base.type = type_int;
+       expression->base.type = c_mode & _CXX ? type_bool : type_int;
 }
 
 static void semantic_unexpr_integer(unary_expression_t *expression)
@@ -8244,7 +8248,6 @@ static expression_t *parse_##unexpression_type(void)                         \
 {                                                                            \
        expression_t *unary_expression                                           \
                = allocate_expression_zero(unexpression_type);                       \
-       unary_expression->base.source_position = *HERE;                          \
        eat(token_type);                                                         \
        unary_expression->unary.value = parse_sub_expression(PREC_UNARY);        \
                                                                                 \
@@ -8276,9 +8279,8 @@ static expression_t *parse_##unexpression_type(expression_t *left)            \
 {                                                                             \
        expression_t *unary_expression                                            \
                = allocate_expression_zero(unexpression_type);                        \
-       unary_expression->base.source_position = *HERE;                           \
        eat(token_type);                                                          \
-       unary_expression->unary.value          = left;                            \
+       unary_expression->unary.value = left;                                     \
                                                                                  \
        sfunc(&unary_expression->unary);                                          \
                                                                               \
@@ -8610,7 +8612,7 @@ static void semantic_comparison(binary_expression_t *expression)
                                        &expression->base.source_position,
                                        type_left, type_right);
        }
-       expression->base.type = type_int;
+       expression->base.type = c_mode & _CXX ? type_bool : type_int;
 }
 
 /**
@@ -8747,8 +8749,8 @@ static void semantic_logical_op(binary_expression_t *expression)
        type_t       *const type_left       = skip_typeref(orig_type_left);
        type_t       *const type_right      = skip_typeref(orig_type_right);
 
-       warn_function_address_as_bool(left);
-       warn_function_address_as_bool(right);
+       warn_reference_address_as_bool(left);
+       warn_reference_address_as_bool(right);
 
        if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) {
                /* TODO: improve error message */
@@ -8759,7 +8761,7 @@ static void semantic_logical_op(binary_expression_t *expression)
                return;
        }
 
-       expression->base.type = type_int;
+       expression->base.type = c_mode & _CXX ? type_bool : type_int;
 }
 
 /**
@@ -8936,8 +8938,7 @@ static void semantic_comma(binary_expression_t *expression)
 static expression_t *parse_##binexpression_type(expression_t *left)          \
 {                                                                            \
        expression_t *binexpr = allocate_expression_zero(binexpression_type);    \
-       binexpr->base.source_position = *HERE;                                   \
-       binexpr->binary.left          = left;                                    \
+       binexpr->binary.left  = left;                                            \
        eat(token_type);                                                         \
                                                                              \
        expression_t *right = parse_sub_expression(prec_r);                      \
@@ -9542,6 +9543,7 @@ static statement_t *parse_if(void)
        add_anchor_token(')');
        expression_t *const expr = parse_expression();
        statement->ifs.condition = expr;
+       warn_reference_address_as_bool(expr);
        mark_vars_read(expr, NULL);
        rem_anchor_token(')');
        expect(')');
@@ -9784,7 +9786,7 @@ static statement_t *parse_for(void)
        rem_anchor_token(')');
        statement->fors.body = parse_loop_body(statement);
 
-       assert(scope == &statement->fors.scope);
+       assert(current_scope == &statement->fors.scope);
        scope_pop();
        environment_pop_to(top);
 
@@ -9794,7 +9796,7 @@ static statement_t *parse_for(void)
 end_error:
        POP_PARENT;
        rem_anchor_token(')');
-       assert(scope == &statement->fors.scope);
+       assert(current_scope == &statement->fors.scope);
        scope_pop();
        environment_pop_to(top);
 
@@ -9980,7 +9982,7 @@ static statement_t *parse_return(void)
                mark_vars_read(return_value, NULL);
        }
 
-       const type_t *const func_type = current_function->base.type;
+       const type_t *const func_type = skip_typeref(current_function->base.type);
        assert(is_type_function(func_type));
        type_t *const return_type = skip_typeref(func_type->function.return_type);
 
@@ -10028,18 +10030,18 @@ static statement_t *parse_declaration_statement(void)
 {
        statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION);
 
-       entity_t *before = scope->last_entity;
+       entity_t *before = current_scope->last_entity;
        if (GNU_MODE)
                parse_external_declaration();
        else
                parse_declaration(record_entity);
 
        if (before == NULL) {
-               statement->declaration.declarations_begin = scope->entities;
+               statement->declaration.declarations_begin = current_scope->entities;
        } else {
                statement->declaration.declarations_begin = before->base.next;
        }
-       statement->declaration.declarations_end = scope->last_entity;
+       statement->declaration.declarations_end = current_scope->last_entity;
 
        return statement;
 }
@@ -10134,14 +10136,15 @@ static statement_t *parse_local_label_declaration(void)
                        goto end_error;
                }
                symbol_t *symbol = token.v.symbol;
-               entity_t *entity = get_entity(symbol, NAMESPACE_LOCAL_LABEL);
-               if (entity != NULL) {
-                       errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition at %P)",
+               entity_t *entity = get_entity(symbol, NAMESPACE_LABEL);
+               if (entity != NULL && entity->base.parent_scope == current_scope) {
+                       errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition %P)",
                               symbol, &entity->base.source_position);
                } else {
                        entity = allocate_entity_zero(ENTITY_LOCAL_LABEL);
 
-                       entity->base.namespc         = NAMESPACE_LOCAL_LABEL;
+                       entity->base.parent_scope    = current_scope;
+                       entity->base.namespc         = NAMESPACE_LABEL;
                        entity->base.source_position = token.source_position;
                        entity->base.symbol          = symbol;
 
@@ -10151,7 +10154,7 @@ static statement_t *parse_local_label_declaration(void)
                        if (begin == NULL)
                                begin = entity;
 
-                       local_label_push(entity);
+                       environment_push(entity);
                }
                next_token();
 
@@ -10166,6 +10169,55 @@ end_error:
        return statement;
 }
 
+static void parse_namespace_definition(void)
+{
+       eat(T_namespace);
+
+       entity_t *entity = NULL;
+       symbol_t *symbol = NULL;
+
+       if (token.type == T_IDENTIFIER) {
+               symbol = token.v.symbol;
+               next_token();
+
+               entity = get_entity(symbol, NAMESPACE_NORMAL);
+               if (entity != NULL && entity->kind != ENTITY_NAMESPACE
+                               && entity->base.parent_scope == current_scope) {
+                       error_redefined_as_different_kind(&token.source_position,
+                                                         entity, ENTITY_NAMESPACE);
+                       entity = NULL;
+               }
+       }
+
+       if (entity == NULL) {
+               entity                       = allocate_entity_zero(ENTITY_NAMESPACE);
+               entity->base.symbol          = symbol;
+               entity->base.source_position = token.source_position;
+               entity->base.namespc         = NAMESPACE_NORMAL;
+               entity->base.parent_scope    = current_scope;
+       }
+
+       if (token.type == '=') {
+               /* TODO: parse namespace alias */
+               panic("namespace alias definition not supported yet");
+       }
+
+       environment_push(entity);
+       append_entity(current_scope, entity);
+
+       size_t const top = environment_top();
+       scope_push(&entity->namespacee.members);
+
+       expect('{');
+       parse_externals();
+       expect('}');
+
+end_error:
+       assert(current_scope == &entity->namespacee.members);
+       scope_pop();
+       environment_pop_to(top);
+}
+
 /**
  * Parse a statement.
  * There's also parse_statement() which additionally checks for
@@ -10229,22 +10281,22 @@ expression_statment:
                statement = parse_local_label_declaration();
                break;
 
-       case ';':        statement = parse_empty_statement();         break;
-       case '{':        statement = parse_compound_statement(false); break;
-       case T___leave:  statement = parse_leave_statement();         break;
-       case T___try:    statement = parse_ms_try_statment();         break;
-       case T_asm:      statement = parse_asm_statement();           break;
-       case T_break:    statement = parse_break();                   break;
-       case T_case:     statement = parse_case_statement();          break;
-       case T_continue: statement = parse_continue();                break;
-       case T_default:  statement = parse_default_statement();       break;
-       case T_do:       statement = parse_do();                      break;
-       case T_for:      statement = parse_for();                     break;
-       case T_goto:     statement = parse_goto();                    break;
-       case T_if:       statement = parse_if();                      break;
-       case T_return:   statement = parse_return();                  break;
-       case T_switch:   statement = parse_switch();                  break;
-       case T_while:    statement = parse_while();                   break;
+       case ';':         statement = parse_empty_statement();         break;
+       case '{':         statement = parse_compound_statement(false); break;
+       case T___leave:   statement = parse_leave_statement();         break;
+       case T___try:     statement = parse_ms_try_statment();         break;
+       case T_asm:       statement = parse_asm_statement();           break;
+       case T_break:     statement = parse_break();                   break;
+       case T_case:      statement = parse_case_statement();          break;
+       case T_continue:  statement = parse_continue();                break;
+       case T_default:   statement = parse_default_statement();       break;
+       case T_do:        statement = parse_do();                      break;
+       case T_for:       statement = parse_for();                     break;
+       case T_goto:      statement = parse_goto();                    break;
+       case T_if:        statement = parse_if();                      break;
+       case T_return:    statement = parse_return();                  break;
+       case T_switch:    statement = parse_switch();                  break;
+       case T_while:     statement = parse_while();                   break;
 
        EXPRESSION_START
                statement = parse_expression_statement();
@@ -10298,8 +10350,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
        eat('{');
        add_anchor_token('}');
 
-       size_t const top       = environment_top();
-       size_t const top_local = local_label_top();
+       size_t const top = environment_top();
        scope_push(&statement->compound.scope);
 
        statement_t **anchor            = &statement->compound.statements;
@@ -10357,42 +10408,14 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
 
 end_error:
        rem_anchor_token('}');
-       assert(scope == &statement->compound.scope);
+       assert(current_scope == &statement->compound.scope);
        scope_pop();
        environment_pop_to(top);
-       local_label_pop_to(top_local);
 
        POP_PARENT;
        return statement;
 }
 
-/**
- * Initialize builtin types.
- */
-static void initialize_builtin_types(void)
-{
-       type_intmax_t    = make_global_typedef("__intmax_t__",      type_long_long);
-       type_size_t      = make_global_typedef("__SIZE_TYPE__",     type_unsigned_long);
-       type_ssize_t     = make_global_typedef("__SSIZE_TYPE__",    type_long);
-       type_ptrdiff_t   = make_global_typedef("__PTRDIFF_TYPE__",  type_long);
-       type_uintmax_t   = make_global_typedef("__uintmax_t__",     type_unsigned_long_long);
-       type_uptrdiff_t  = make_global_typedef("__UPTRDIFF_TYPE__", type_unsigned_long);
-       type_wchar_t     = make_global_typedef("__WCHAR_TYPE__",    opt_short_wchar_t ? type_unsigned_short : type_int);
-       type_wint_t      = make_global_typedef("__WINT_TYPE__",     type_int);
-
-       type_intmax_t_ptr  = make_pointer_type(type_intmax_t,  TYPE_QUALIFIER_NONE);
-       type_ptrdiff_t_ptr = make_pointer_type(type_ptrdiff_t, TYPE_QUALIFIER_NONE);
-       type_ssize_t_ptr   = make_pointer_type(type_ssize_t,   TYPE_QUALIFIER_NONE);
-       type_wchar_t_ptr   = make_pointer_type(type_wchar_t,   TYPE_QUALIFIER_NONE);
-
-       /* const version of wchar_t */
-       type_const_wchar_t = allocate_type_zero(TYPE_TYPEDEF);
-       type_const_wchar_t->typedeft.typedefe  = type_wchar_t->typedeft.typedefe;
-       type_const_wchar_t->base.qualifiers   |= TYPE_QUALIFIER_CONST;
-
-       type_const_wchar_t_ptr = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE);
-}
-
 /**
  * Check for unused global static functions and variables
  */
@@ -10447,18 +10470,94 @@ static void parse_global_asm(void)
 end_error:;
 }
 
-/**
- * Parse a translation unit.
- */
-static void parse_translation_unit(void)
+static void parse_linkage_specification(void)
+{
+       eat(T_extern);
+       assert(token.type == T_STRING_LITERAL);
+
+       const char *linkage = parse_string_literals().begin;
+
+       linkage_kind_t old_linkage = current_linkage;
+       linkage_kind_t new_linkage;
+       if (strcmp(linkage, "C") == 0) {
+               new_linkage = LINKAGE_C;
+       } else if (strcmp(linkage, "C++") == 0) {
+               new_linkage = LINKAGE_CXX;
+       } else {
+               errorf(HERE, "linkage string \"%s\" not recognized", linkage);
+               new_linkage = LINKAGE_INVALID;
+       }
+       current_linkage = new_linkage;
+
+       if (token.type == '{') {
+               next_token();
+               parse_externals();
+               expect('}');
+       } else {
+               parse_external();
+       }
+
+end_error:
+       assert(current_linkage == new_linkage);
+       current_linkage = old_linkage;
+}
+
+static void parse_external(void)
+{
+       switch (token.type) {
+               DECLARATION_START_NO_EXTERN
+               case T_IDENTIFIER:
+               case T___extension__:
+               case '(': /* for function declarations with implicit return type and
+                                  * parenthesized declarator, i.e. (f)(void); */
+                       parse_external_declaration();
+                       return;
+
+               case T_extern:
+                       if (look_ahead(1)->type == T_STRING_LITERAL) {
+                               parse_linkage_specification();
+                       } else {
+                               parse_external_declaration();
+                       }
+                       return;
+
+               case T_asm:
+                       parse_global_asm();
+                       return;
+
+               case T_namespace:
+                       parse_namespace_definition();
+                       return;
+
+               case ';':
+                       if (!strict_mode) {
+                               if (warning.other)
+                                       warningf(HERE, "stray ';' outside of function");
+                               next_token();
+                               return;
+                       }
+                       /* FALLTHROUGH */
+
+               default:
+                       errorf(HERE, "stray %K outside of function", &token);
+                       if (token.type == '(' || token.type == '{' || token.type == '[')
+                               eat_until_matching_token(token.type);
+                       next_token();
+                       return;
+       }
+}
+
+static void parse_externals(void)
 {
+       add_anchor_token('}');
        add_anchor_token(T_EOF);
 
 #ifndef NDEBUG
        unsigned char token_anchor_copy[T_LAST_TOKEN];
        memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
 #endif
-       for (;;) {
+
+       while (token.type != T_EOF && token.type != '}') {
 #ifndef NDEBUG
                bool anchor_leak = false;
                for (int i = 0; i != T_LAST_TOKEN; ++i) {
@@ -10477,37 +10576,30 @@ static void parse_translation_unit(void)
                        abort();
 #endif
 
-               switch (token.type) {
-                       DECLARATION_START
-                       case T_IDENTIFIER:
-                       case T___extension__:
-                               parse_external_declaration();
-                               break;
+               parse_external();
+       }
 
-                       case T_asm:
-                               parse_global_asm();
-                               break;
+       rem_anchor_token(T_EOF);
+       rem_anchor_token('}');
+}
 
-                       case T_EOF:
-                               rem_anchor_token(T_EOF);
-                               return;
+/**
+ * Parse a translation unit.
+ */
+static void parse_translation_unit(void)
+{
+       add_anchor_token(T_EOF);
 
-                       case ';':
-                               if (!strict_mode) {
-                                       if (warning.other)
-                                               warningf(HERE, "stray ';' outside of function");
-                                       next_token();
-                                       break;
-                               }
-                               /* FALLTHROUGH */
+       while (true) {
+               parse_externals();
 
-                       default:
-                               errorf(HERE, "stray %K outside of function", &token);
-                               if (token.type == '(' || token.type == '{' || token.type == '[')
-                                       eat_until_matching_token(token.type);
-                               next_token();
-                               break;
-               }
+               if (token.type == T_EOF)
+                       break;
+
+               errorf(HERE, "stray %K outside of function", &token);
+               if (token.type == '(' || token.type == '{' || token.type == '[')
+                       eat_until_matching_token(token.type);
+               next_token();
        }
 }
 
@@ -10520,7 +10612,6 @@ void start_parsing(void)
 {
        environment_stack = NEW_ARR_F(stack_entry_t, 0);
        label_stack       = NEW_ARR_F(stack_entry_t, 0);
-       local_label_stack = NEW_ARR_F(stack_entry_t, 0);
        diagnostic_count  = 0;
        error_count       = 0;
        warning_count     = 0;
@@ -10534,17 +10625,15 @@ void start_parsing(void)
        assert(file_scope == NULL);
        file_scope = &unit->scope;
 
-       assert(scope == NULL);
+       assert(current_scope == NULL);
        scope_push(&unit->scope);
-
-       initialize_builtin_types();
 }
 
 translation_unit_t *finish_parsing(void)
 {
        /* do NOT use scope_pop() here, this will crash, will it by hand */
-       assert(scope == &unit->scope);
-       scope            = NULL;
+       assert(current_scope == &unit->scope);
+       current_scope = NULL;
 
        assert(file_scope == &unit->scope);
        check_unused_globals();
@@ -10552,7 +10641,6 @@ translation_unit_t *finish_parsing(void)
 
        DEL_ARR_F(environment_stack);
        DEL_ARR_F(label_stack);
-       DEL_ARR_F(local_label_stack);
 
        translation_unit_t *result = unit;
        unit = NULL;
@@ -10565,6 +10653,7 @@ void parse(void)
        for (int i = 0; i < MAX_LOOKAHEAD + 2; ++i) {
                next_token();
        }
+       current_linkage = c_mode & _CXX ? LINKAGE_CXX : LINKAGE_C;
        parse_translation_unit();
 }