Handle mangling of anonymous types, which only have a typedef name.
[cparser] / parser.c
index 0852cec..0325add 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -84,6 +84,7 @@ struct declaration_specifiers_t {
        symbol_t          *get_property_sym;  /**< the name of the get property if set. */
        symbol_t          *put_property_sym;  /**< the name of the put property if set. */
        type_t            *type;
+       variable_t        *based_variable;    /**< Microsoft __based variable. */
 };
 
 /**
@@ -100,34 +101,35 @@ typedef struct parse_initializer_env_t {
 typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition);
 
 /** The current token. */
-static token_t             token;
+static token_t              token;
 /** The lookahead ring-buffer. */
-static token_t             lookahead_buffer[MAX_LOOKAHEAD];
+static token_t              lookahead_buffer[MAX_LOOKAHEAD];
 /** Position of the next token in the lookahead buffer. */
-static int                 lookahead_bufpos;
-static stack_entry_t      *environment_stack = NULL;
-static stack_entry_t      *label_stack       = NULL;
-static scope_t            *file_scope        = NULL;
-static scope_t            *current_scope     = NULL;
+static int                  lookahead_bufpos;
+static stack_entry_t       *environment_stack = NULL;
+static stack_entry_t       *label_stack       = NULL;
+static scope_t             *file_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;
-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;
-static label_statement_t  *label_last        = NULL;
+static function_t          *current_function  = NULL;
+static entity_t            *current_init_decl = NULL;
+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_anchor       = NULL;
+static label_statement_t   *label_first       = NULL;
+static label_statement_t  **label_anchor      = NULL;
 /** current translation unit. */
-static translation_unit_t *unit              = NULL;
+static translation_unit_t  *unit              = NULL;
 /** true if we are in a type property context (evaluation only for type. */
-static bool                in_type_prop      = false;
+static bool                 in_type_prop      = false;
 /** true in we are in a __extension__ context. */
-static bool                in_gcc_extension  = false;
-static struct obstack      temp_obst;
+static bool                 in_gcc_extension  = false;
+static struct obstack       temp_obst;
+static entity_t            *anonymous_entity;
 
 
 #define PUSH_PARENT(stmt)                          \
@@ -794,7 +796,7 @@ 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) {
+       for (; entity != NULL; entity = entity->base.symbol_next) {
                if (entity->base.namespc == namespc)
                        return entity;
        }
@@ -871,7 +873,7 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top)
        if (new_top == top)
                return;
 
-       for(i = top; i > new_top; --i) {
+       for (i = top; i > new_top; --i) {
                stack_entry_t *entry = &stack[i - 1];
 
                entity_t           *old_entity = entry->old_entity;
@@ -1357,7 +1359,7 @@ static void parse_gnu_attribute_tls_model_arg(gnu_attribute_t *attribute)
        string_t string = { NULL, 0 };
        parse_gnu_attribute_string_arg(attribute, &string);
        if (string.begin != NULL) {
-               for(size_t i = 0; i < 4; ++i) {
+               for (size_t i = 0; i < 4; ++i) {
                        if (strcmp(tls_models[i], string.begin) == 0) {
                                attribute->u.value = i;
                                return;
@@ -1382,7 +1384,7 @@ static void parse_gnu_attribute_visibility_arg(gnu_attribute_t *attribute)
        string_t string = { NULL, 0 };
        parse_gnu_attribute_string_arg(attribute, &string);
        if (string.begin != NULL) {
-               for(size_t i = 0; i < 4; ++i) {
+               for (size_t i = 0; i < 4; ++i) {
                        if (strcmp(visibilities[i], string.begin) == 0) {
                                attribute->u.value = i;
                                return;
@@ -1406,7 +1408,7 @@ static void parse_gnu_attribute_model_arg(gnu_attribute_t *attribute)
        string_t string = { NULL, 0 };
        parse_gnu_attribute_string_arg(attribute, &string);
        if (string.begin != NULL) {
-               for(int i = 0; i < 3; ++i) {
+               for (int i = 0; i < 3; ++i) {
                        if (strcmp(visibilities[i], string.begin) == 0) {
                                attribute->u.value = i;
                                return;
@@ -1472,7 +1474,7 @@ static void parse_gnu_attribute_interrupt_arg(gnu_attribute_t *attribute)
        string_t string = { NULL, 0 };
        parse_gnu_attribute_string_arg(attribute, &string);
        if (string.begin != NULL) {
-               for(size_t i = 0; i < 5; ++i) {
+               for (size_t i = 0; i < 5; ++i) {
                        if (strcmp(interrupts[i], string.begin) == 0) {
                                attribute->u.value = i;
                                return;
@@ -1501,7 +1503,7 @@ static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute)
                goto end_error;
        }
        const char *name = token.v.symbol->string;
-       for(i = 0; i < 4; ++i) {
+       for (i = 0; i < 4; ++i) {
                if (strcmp_underscore(format_names[i], name) == 0)
                        break;
        }
@@ -1656,7 +1658,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes)
                        next_token();
 
                        int i;
-                       for(i = 0; i < GNU_AK_LAST; ++i) {
+                       for (i = 0; i < GNU_AK_LAST; ++i) {
                                if (strcmp_underscore(gnu_attribute_names[i], name) == 0)
                                        break;
                        }
@@ -2345,7 +2347,7 @@ static __attribute__((unused)) void debug_print_type_path(
 {
        size_t len = ARR_LEN(path->path);
 
-       for(size_t i = 0; i < len; ++i) {
+       for (size_t i = 0; i < len; ++i) {
                const type_path_entry_t *entry = & path->path[i];
 
                type_t *type = skip_typeref(entry->type);
@@ -2358,7 +2360,7 @@ static __attribute__((unused)) void debug_print_type_path(
                        fprintf(stderr, ".%s",
                                entry->v.compound_entry->base.symbol->string);
                } else if (is_type_array(type)) {
-                       fprintf(stderr, "[%zu]", entry->v.index);
+                       fprintf(stderr, "[%u]", (unsigned) entry->v.index);
                } else {
                        fprintf(stderr, "-INVALID-");
                }
@@ -2455,7 +2457,7 @@ static void ascend_to(type_path_t *path, size_t top_path_level)
 static bool walk_designator(type_path_t *path, const designator_t *designator,
                             bool used_in_offsetof)
 {
-       for; designator != NULL; designator = designator->next) {
+       for (; designator != NULL; designator = designator->next) {
                type_path_entry_t *top       = get_type_path_top(path);
                type_t            *orig_type = top->type;
 
@@ -2476,7 +2478,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                        } else {
                                compound_t *compound = type->compound.compound;
                                entity_t   *iter     = compound->members.entities;
-                               for; iter != NULL; iter = iter->base.next) {
+                               for (; iter != NULL; iter = iter->base.next) {
                                        if (iter->base.symbol == symbol) {
                                                break;
                                        }
@@ -2945,7 +2947,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                eat(T_union);
        }
 
-       symbol_t   *symbol      = NULL;
+       symbol_t   *symbol   = NULL;
        compound_t *compound = NULL;
 
        if (token.type == T___attribute__) {
@@ -3005,10 +3007,13 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
        }
 
        if (token.type == '{') {
-               compound->complete = true;
-
                parse_compound_type_entries(compound);
                modifiers |= parse_attributes(&attributes);
+
+               if (symbol == NULL) {
+                       assert(anonymous_entity == NULL);
+                       anonymous_entity = (entity_t*)compound;
+               }
        }
 
        compound->modifiers |= modifiers;
@@ -3020,8 +3025,8 @@ static void parse_enum_entries(type_t *const enum_type)
        eat('{');
 
        if (token.type == '}') {
-               next_token();
                errorf(HERE, "empty enum not allowed");
+               next_token();
                return;
        }
 
@@ -3110,7 +3115,12 @@ static type_t *parse_enum_specifier(void)
 
                parse_enum_entries(type);
                parse_attributes(&attributes);
-       } else if(!entity->enume.complete && !(c_mode & _GNUC)) {
+
+               if (symbol == NULL) {
+                       assert(anonymous_entity == NULL);
+                       anonymous_entity = entity;
+               }
+       } else if (!entity->enume.complete && !(c_mode & _GNUC)) {
                errorf(HERE, "enum %Y used before definition (incomplete enumes are a GNU extension)",
                       symbol);
        }
@@ -3404,6 +3414,40 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
        return entity;
 }
 
+static void parse_microsoft_based(declaration_specifiers_t *specifiers)
+{
+       if (token.type != T_IDENTIFIER) {
+               parse_error_expected("while parsing __based", T_IDENTIFIER, NULL);
+               return;
+       }
+       symbol_t *symbol = token.v.symbol;
+       entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
+
+       if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) {
+               errorf(HERE, "'%Y' is not a variable name.", symbol);
+               entity = create_error_entity(symbol, ENTITY_VARIABLE);
+       } else {
+               variable_t *variable = &entity->variable;
+
+               if (specifiers->based_variable != NULL) {
+                       errorf(HERE, "__based type qualifier specified more than once");
+               }
+               specifiers->based_variable = variable;
+
+               type_t *const type = variable->base.type;
+
+               if (is_type_valid(type)) {
+                       if (! is_type_pointer(skip_typeref(type))) {
+                               errorf(HERE, "variable in __based modifier must have pointer type instead of %T", type);
+                       }
+                       if (variable->base.base.parent_scope != file_scope) {
+                               errorf(HERE, "a nonstatic local variable may not be used in a __based specification");
+                       }
+               }
+       }
+       next_token();
+}
+
 /**
  * Finish the construction of a struct type by calculating
  * its size, offsets, alignment.
@@ -3547,6 +3591,15 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        expect(')');
                        break;
 
+               case T__based:
+                       next_token();
+                       expect('(');
+                       add_anchor_token(')');
+                       parse_microsoft_based(specifiers);
+                       rem_anchor_token(')');
+                       expect(')');
+                       break;
+
                case T___thread:
                        switch (specifiers->storage_class) {
                        case STORAGE_CLASS_NONE:
@@ -3592,12 +3645,12 @@ 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__Bool,      SPECIFIER_BOOL,      "_Bool");
@@ -3629,7 +3682,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) {
@@ -3637,6 +3689,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        } else {
                                type_specifiers |= SPECIFIER_LONG;
                        }
+                       next_token();
                        break;
 
                case T_struct: {
@@ -4016,6 +4069,7 @@ static entity_t *parse_parameter(void)
        parse_declaration_specifiers(&specifiers);
 
        entity_t *entity = parse_declarator(&specifiers, true, false);
+       anonymous_entity = NULL;
        return entity;
 }
 
@@ -4201,53 +4255,27 @@ end_error:
        return (construct_type_t*) array;
 }
 
-static construct_type_t *parse_function_declarator(scope_t *scope)
+static construct_type_t *parse_function_declarator(scope_t *scope,
+                                                   decl_modifiers_t modifiers)
 {
-       type_t *type = allocate_type_zero(TYPE_FUNCTION);
-
-       type->function.linkage = current_linkage;
+       type_t          *type  = allocate_type_zero(TYPE_FUNCTION);
+       function_type_t *ftype = &type->function;
 
-       /* TODO: revive this... once we know exactly how to do it */
-#if 0
-       decl_modifiers_t  modifiers = entity->declaration.modifiers;
+       ftype->linkage = current_linkage;
 
-       unsigned mask = modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL);
+       switch (modifiers & (DM_CDECL | DM_STDCALL | DM_FASTCALL | DM_THISCALL)) {
+               case DM_NONE:     break;
+               case DM_CDECL:    ftype->calling_convention = CC_CDECL;    break;
+               case DM_STDCALL:  ftype->calling_convention = CC_STDCALL;  break;
+               case DM_FASTCALL: ftype->calling_convention = CC_FASTCALL; break;
+               case DM_THISCALL: ftype->calling_convention = CC_THISCALL; break;
 
-       if (mask & (mask-1)) {
-               const char *first = NULL, *second = NULL;
-
-               /* more than one calling convention set */
-               if (modifiers & DM_CDECL) {
-                       if (first == NULL)       first = "cdecl";
-                       else if (second == NULL) second = "cdecl";
-               }
-               if (modifiers & DM_STDCALL) {
-                       if (first == NULL)       first = "stdcall";
-                       else if (second == NULL) second = "stdcall";
-               }
-               if (modifiers & DM_FASTCALL) {
-                       if (first == NULL)       first = "fastcall";
-                       else if (second == NULL) second = "fastcall";
-               }
-               if (modifiers & DM_THISCALL) {
-                       if (first == NULL)       first = "thiscall";
-                       else if (second == NULL) second = "thiscall";
-               }
-               errorf(&entity->base.source_position,
-                          "%s and %s attributes are not compatible", first, second);
+               default:
+                       errorf(HERE, "multiple calling conventions in declaration");
+                       break;
        }
 
-       if (modifiers & DM_CDECL)
-               type->function.calling_convention = CC_CDECL;
-       else if (modifiers & DM_STDCALL)
-               type->function.calling_convention = CC_STDCALL;
-       else if (modifiers & DM_FASTCALL)
-               type->function.calling_convention = CC_FASTCALL;
-       else if (modifiers & DM_THISCALL)
-               type->function.calling_convention = CC_THISCALL;
-#endif
-
-       parse_parameters(&type->function, scope);
+       parse_parameters(ftype, scope);
 
        construct_function_type_t *construct_function_type =
                obstack_alloc(&temp_obst, sizeof(construct_function_type[0]));
@@ -4292,8 +4320,10 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env,
                modifiers |= parse_attributes(&attributes);
        }
 
-       if (env != NULL)
-               env->modifiers |= modifiers;
+       if (env != NULL) {
+               modifiers      |= env->modifiers;
+               env->modifiers  = modifiers;
+       }
 
        construct_type_t *inner_types = NULL;
 
@@ -4328,7 +4358,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env,
 
        construct_type_t *p = last;
 
-       while(true) {
+       while (true) {
                construct_type_t *type;
                switch (token.type) {
                case '(': {
@@ -4336,7 +4366,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env,
                        if (env != NULL)
                                scope = &env->parameters;
 
-                       type = parse_function_declarator(scope);
+                       type = parse_function_declarator(scope, modifiers);
                        break;
                }
                case '[':
@@ -4448,10 +4478,10 @@ static void parse_declaration_attributes(entity_t *entity)
 }
 
 static type_t *construct_declarator_type(construct_type_t *construct_list,
-                                         type_t *type)
+                                         type_t *type, variable_t *variable)
 {
        construct_type_t *iter = construct_list;
-       for; iter != NULL; iter = iter->next) {
+       for (; iter != NULL; iter = iter->next) {
                switch (iter->kind) {
                case CONSTRUCT_INVALID:
                        internal_errorf(HERE, "invalid type construction found");
@@ -4482,7 +4512,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
 
                case CONSTRUCT_POINTER: {
                        parsed_pointer_t *parsed_pointer = (parsed_pointer_t*) iter;
-                       type = make_pointer_type(type, parsed_pointer->type_qualifiers);
+                       type = make_based_pointer_type(type, parsed_pointer->type_qualifiers, variable);
                        continue;
                }
 
@@ -4544,10 +4574,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
 {
        parse_declarator_env_t env;
        memset(&env, 0, sizeof(env));
+       env.modifiers = specifiers->modifiers;
 
        construct_type_t *construct_type
                = parse_inner_declarator(&env, may_be_abstract);
-       type_t *type = construct_declarator_type(construct_type, specifiers->type);
+       type_t *type = construct_declarator_type(construct_type, specifiers->type, specifiers->based_variable);
 
        if (construct_type != NULL) {
                obstack_free(&temp_obst, construct_type);
@@ -4559,6 +4590,21 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                entity->base.symbol          = env.symbol;
                entity->base.source_position = env.source_position;
                entity->typedefe.type        = type;
+
+               if (anonymous_entity != NULL) {
+                       if (is_type_compound(type)) {
+                               assert(anonymous_entity->compound.alias == NULL);
+                               assert(anonymous_entity->kind == ENTITY_STRUCT ||
+                                      anonymous_entity->kind == ENTITY_UNION);
+                               anonymous_entity->compound.alias = entity;
+                               anonymous_entity = NULL;
+                       } else if (is_type_enum(type)) {
+                               assert(anonymous_entity->enume.alias == NULL);
+                               assert(anonymous_entity->kind == ENTITY_ENUM);
+                               anonymous_entity->enume.alias = entity;
+                               anonymous_entity = NULL;
+                       }
+               }
        } else {
                if (create_compound_member) {
                        entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER);
@@ -4583,11 +4629,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                        }
                }
 
-               entity->base.source_position  = env.source_position;
-               entity->base.symbol           = env.symbol;
-               entity->base.namespc          = NAMESPACE_NORMAL;
-               entity->declaration.type      = type;
-               entity->declaration.modifiers = env.modifiers | specifiers->modifiers;
+               entity->base.source_position          = env.source_position;
+               entity->base.symbol                   = env.symbol;
+               entity->base.namespc                  = NAMESPACE_NORMAL;
+               entity->declaration.type              = type;
+               entity->declaration.modifiers         = env.modifiers;
                entity->declaration.deprecated_string = specifiers->deprecated_string;
 
                storage_class_t storage_class = specifiers->storage_class;
@@ -4609,7 +4655,7 @@ static type_t *parse_abstract_declarator(type_t *base_type)
 {
        construct_type_t *construct_type = parse_inner_declarator(NULL, 1);
 
-       type_t *result = construct_declarator_type(construct_type, base_type);
+       type_t *result = construct_declarator_type(construct_type, base_type, NULL);
        if (construct_type != NULL) {
                obstack_free(&temp_obst, construct_type);
        }
@@ -5063,7 +5109,7 @@ static void parse_declaration_rest(entity_t *ndeclaration,
 {
        add_anchor_token(';');
        add_anchor_token(',');
-       while(true) {
+       while (true) {
                entity_t *entity = finished_declaration(ndeclaration, token.type == '=');
 
                if (token.type == '=') {
@@ -5081,6 +5127,7 @@ static void parse_declaration_rest(entity_t *ndeclaration,
        expect(';');
 
 end_error:
+       anonymous_entity = NULL;
        rem_anchor_token(';');
        rem_anchor_token(',');
 }
@@ -5181,7 +5228,7 @@ static void parse_kr_declaration_list(entity_t *entity)
        function_parameter_t *last_parameter = NULL;
 
        entity_t *parameter_declaration = entity->function.parameters.entities;
-       for; parameter_declaration != NULL;
+       for (; parameter_declaration != NULL;
                        parameter_declaration = parameter_declaration->base.next) {
                type_t *parameter_type = parameter_declaration->declaration.type;
                if (parameter_type == NULL) {
@@ -5272,8 +5319,6 @@ static void check_labels(void)
                               "label '%Y' used but not defined", label->base.symbol);
                 }
        }
-       goto_first = NULL;
-       goto_last  = NULL;
 
        if (warning.unused_label) {
                for (const label_statement_t *label_statement = label_first;
@@ -5288,7 +5333,6 @@ static void check_labels(void)
                        }
                }
        }
-       label_first = label_last = NULL;
 }
 
 static void warn_unused_decl(entity_t *entity, entity_t *end,
@@ -5945,7 +5989,7 @@ static void parse_external_declaration(void)
        scope_push(&function->parameters);
 
        entity_t *parameter = function->parameters.entities;
-       for; parameter != NULL; parameter = parameter->base.next) {
+       for (; parameter != NULL; parameter = parameter->base.next) {
                if (parameter->base.parent_scope == &ndeclaration->function.parameters) {
                        parameter->base.parent_scope = current_scope;
                }
@@ -5969,7 +6013,12 @@ static void parse_external_declaration(void)
                current_function                 = function;
                current_parent                   = NULL;
 
-               statement_t *const body     = parse_compound_statement(false);
+               goto_first   = NULL;
+               goto_anchor  = &goto_first;
+               label_first  = NULL;
+               label_anchor = &label_first;
+
+               statement_t *const body = parse_compound_statement(false);
                function->statement = body;
                first_err = true;
                check_labels();
@@ -6025,14 +6074,11 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size,
                long v = fold_constant(size);
 
                if (v < 0) {
-                       errorf(source_position, "negative width in bit-field '%Y'",
-                               symbol);
+                       errorf(source_position, "negative width in bit-field '%Y'", symbol);
                } else if (v == 0) {
-                       errorf(source_position, "zero width for bit-field '%Y'",
-                               symbol);
+                       errorf(source_position, "zero width for bit-field '%Y'", symbol);
                } else if (bit_size > 0 && (il_size_t)v > bit_size) {
-                       errorf(source_position, "width of '%Y' exceeds its type",
-                               symbol);
+                       errorf(source_position, "width of '%Y' exceeds its type", symbol);
                } else {
                        type->bitfield.bit_size = v;
                }
@@ -6044,11 +6090,13 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size,
 static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol)
 {
        entity_t *iter = compound->members.entities;
-       for; iter != NULL; iter = iter->base.next) {
+       for (; iter != NULL; iter = iter->base.next) {
                if (iter->kind != ENTITY_COMPOUND_MEMBER)
                        continue;
 
-               if (iter->base.symbol == NULL) {
+               if (iter->base.symbol == symbol) {
+                       return iter;
+               } else if (iter->base.symbol == NULL) {
                        type_t *type = skip_typeref(iter->declaration.type);
                        if (is_type_compound(type)) {
                                entity_t *result
@@ -6058,10 +6106,6 @@ static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol)
                        }
                        continue;
                }
-
-               if (iter->base.symbol == symbol) {
-                       return iter;
-               }
        }
 
        return NULL;
@@ -6112,7 +6156,6 @@ static void parse_compound_declarators(compound_t *compound,
                        entity_t *prev = find_compound_entry(compound, symbol);
 
                        if (prev != NULL) {
-                               assert(prev->base.symbol == symbol);
                                errorf(&entity->base.source_position,
                                       "multiple declarations of symbol '%Y' (declared %P)",
                                       symbol, &prev->base.source_position);
@@ -6121,40 +6164,33 @@ static void parse_compound_declarators(compound_t *compound,
 
                append_entity(&compound->members, entity);
 
-               if (token.type != ',')
-                       break;
-               next_token();
-       }
-       expect(';');
-
-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);
+                       errorf(&entity->base.source_position,
+                                       "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) {
+                       /* §6.7.2.1:16 flexible array member */
+                       if (is_type_array(type) &&
+                                       token.type == ';'   &&
+                                       look_ahead(1)->type == '}') {
                                compound->has_flexible_member = true;
                        } else {
-                               errorf(HERE,
-                                      "compound member '%Y' has incomplete type '%T'",
-                                      entity->base.symbol, orig_type);
+                               errorf(&entity->base.source_position,
+                                               "compound member '%Y' has incomplete type '%T'",
+                                               entity->base.symbol, orig_type);
                        }
                }
+
+               if (token.type != ',')
+                       break;
+               next_token();
        }
+       expect(';');
+
+end_error:
+       anonymous_entity = NULL;
 }
 
 static void parse_compound_type_entries(compound_t *compound)
@@ -6173,9 +6209,11 @@ static void parse_compound_type_entries(compound_t *compound)
 
                parse_compound_declarators(compound, &specifiers);
        }
-       semantic_compound(compound);
        rem_anchor_token('}');
        next_token();
+
+       /* §6.7.2.1:7 */
+       compound->complete = true;
 }
 
 static type_t *parse_typename(void)
@@ -6312,10 +6350,10 @@ static expression_t *parse_character_constant(void)
        cnst->conste.v.character = token.v.string;
 
        if (cnst->conste.v.character.size != 1) {
-               if (warning.multichar && GNU_MODE) {
+               if (!GNU_MODE) {
+                       errorf(HERE, "more than 1 character in character constant");
+               } else if (warning.multichar) {
                        warningf(HERE, "multi-character character constant");
-               } else {
-                       errorf(HERE, "more than 1 characters in character constant");
                }
        }
        next_token();
@@ -6333,10 +6371,10 @@ static expression_t *parse_wide_character_constant(void)
        cnst->conste.v.wide_character = token.v.wide_string;
 
        if (cnst->conste.v.wide_character.size != 1) {
-               if (warning.multichar && GNU_MODE) {
+               if (!GNU_MODE) {
+                       errorf(HERE, "more than 1 character in character constant");
+               } else if (warning.multichar) {
                        warningf(HERE, "multi-character character constant");
-               } else {
-                       errorf(HERE, "more than 1 characters in character constant");
                }
        }
        next_token();
@@ -6909,7 +6947,7 @@ static designator_t *parse_designator(void)
        next_token();
 
        designator_t *last_designator = result;
-       while(true) {
+       while (true) {
                if (token.type == '.') {
                        next_token();
                        if (token.type != T_IDENTIFIER) {
@@ -7300,7 +7338,7 @@ static expression_t *parse_noop_expression(void)
                add_anchor_token(',');
 
                if (token.type != ')') {
-                       while(true) {
+                       while (true) {
                                (void)parse_assignment_expression();
                                if (token.type != ',')
                                        break;
@@ -7440,8 +7478,6 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
 
        eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__);
 
-       char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
-
        /* we only refer to a type property, mark this case */
        bool old     = in_type_prop;
        in_type_prop = true;
@@ -7479,6 +7515,7 @@ typeprop_expression:
                type->kind == TYPE_BITFIELD ? "bitfield"            :
                NULL;
        if (wrong_type != NULL) {
+               char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
                errorf(&tp_expression->base.source_position,
                                "operand of %s expression must not be of %s type '%T'",
                                what, wrong_type, orig_type);
@@ -7715,7 +7752,7 @@ static expression_t *parse_call_expression(expression_t *expression)
        }
 
        /* do default promotion */
-       for; argument != NULL; argument = argument->next) {
+       for (; argument != NULL; argument = argument->next) {
                type_t *type = argument->expression->base.type;
 
                type = get_default_promoted_type(type);
@@ -7746,6 +7783,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 ? ... : ...'.
  *
@@ -7758,6 +7837,8 @@ static expression_t *parse_conditional_expression(expression_t *expression)
        conditional_expression_t *conditional = &result->conditional;
        conditional->condition                = expression;
 
+       warn_reference_address_as_bool(expression);
+
        eat('?');
        add_anchor_token(':');
 
@@ -8096,45 +8177,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;
@@ -8144,7 +8186,7 @@ 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 = c_mode & _CXX ? type_bool : type_int;
 }
@@ -8221,11 +8263,8 @@ static void semantic_take_addr(unary_expression_t *expression)
                return;
 
        /* §6.5.3.2 */
-       if (value->kind != EXPR_ARRAY_ACCESS
-                       && value->kind != EXPR_UNARY_DEREFERENCE
-                       && !is_lvalue(value)) {
-               errorf(&expression->base.source_position,
-                      "'&' requires an lvalue");
+       if (!is_lvalue(value)) {
+               errorf(&expression->base.source_position, "'&' requires an lvalue");
        }
        if (type->kind == TYPE_BITFIELD) {
                errorf(&expression->base.source_position,
@@ -8744,8 +8783,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 */
@@ -8995,7 +9034,7 @@ static expression_t *parse_sub_expression(precedence_t precedence)
        assert(left != NULL);
        left->base.source_position = source_position;
 
-       while(true) {
+       while (true) {
                if (token.type < 0) {
                        return expected_expression_error();
                }
@@ -9129,8 +9168,8 @@ static void init_expression_parsers(void)
  */
 static asm_argument_t *parse_asm_arguments(bool is_out)
 {
-       asm_argument_t *result = NULL;
-       asm_argument_t *last   = NULL;
+       asm_argument_t  *result = NULL;
+       asm_argument_t **anchor = &result;
 
        while (token.type == T_STRING_LITERAL || token.type == '[') {
                asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
@@ -9213,12 +9252,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
 
                set_address_taken(expression, true);
 
-               if (last != NULL) {
-                       last->next = argument;
-               } else {
-                       result = argument;
-               }
-               last = argument;
+               *anchor = argument;
+               anchor  = &argument->next;
 
                if (token.type != ',')
                        break;
@@ -9238,7 +9273,7 @@ static asm_clobber_t *parse_asm_clobbers(void)
        asm_clobber_t *result = NULL;
        asm_clobber_t *last   = NULL;
 
-       while(token.type == T_STRING_LITERAL) {
+       while (token.type == T_STRING_LITERAL) {
                asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0]));
                clobber->clobber       = parse_string_literals();
 
@@ -9510,12 +9545,8 @@ static statement_t *parse_label_statement(void)
        }
 
        /* remember the labels in a list for later checking */
-       if (label_last == NULL) {
-               label_first = &statement->label;
-       } else {
-               label_last->next = &statement->label;
-       }
-       label_last = &statement->label;
+       *label_anchor = &statement->label;
+       label_anchor  = &statement->label.next;
 
        POP_PARENT;
        return statement;
@@ -9538,6 +9569,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(')');
@@ -9678,6 +9710,7 @@ static statement_t *parse_while(void)
        add_anchor_token(')');
        expression_t *const cond = parse_expression();
        statement->whiles.condition = cond;
+       warn_reference_address_as_bool(cond);
        mark_vars_read(cond, NULL);
        rem_anchor_token(')');
        expect(')');
@@ -9711,6 +9744,7 @@ static statement_t *parse_do(void)
        add_anchor_token(')');
        expression_t *const cond = parse_expression();
        statement->do_while.condition = cond;
+       warn_reference_address_as_bool(cond);
        mark_vars_read(cond, NULL);
        rem_anchor_token(')');
        expect(')');
@@ -9763,6 +9797,7 @@ static statement_t *parse_for(void)
                add_anchor_token(';');
                expression_t *const cond = parse_expression();
                statement->fors.condition = cond;
+               warn_reference_address_as_bool(cond);
                mark_vars_read(cond, NULL);
                rem_anchor_token(';');
        }
@@ -9810,8 +9845,8 @@ static statement_t *parse_goto(void)
                expression_t *expression = parse_expression();
                mark_vars_read(expression, NULL);
 
-               /* Argh: although documentation say the expression must be of type void *,
-                * gcc excepts anything that can be casted into void * without error */
+               /* Argh: although documentation says the expression must be of type void*,
+                * gcc accepts anything that can be casted into void* without error */
                type_t *type = expression->base.type;
 
                if (type != type_error_type) {
@@ -9842,12 +9877,8 @@ static statement_t *parse_goto(void)
        }
 
        /* remember the goto's in a list for later checking */
-       if (goto_last == NULL) {
-               goto_first = &statement->gotos;
-       } else {
-               goto_last->next = &statement->gotos;
-       }
-       goto_last = &statement->gotos;
+       *goto_anchor = &statement->gotos;
+       goto_anchor  = &statement->gotos.next;
 
        expect(';');
 
@@ -10384,7 +10415,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
        /* look over all statements again to produce no effect warnings */
        if (warning.unused_value) {
                statement_t *sub_statement = statement->compound.statements;
-               for; sub_statement != NULL; sub_statement = sub_statement->base.next) {
+               for (; sub_statement != NULL; sub_statement = sub_statement->base.next) {
                        if (sub_statement->kind != STATEMENT_EXPRESSION)
                                continue;
                        /* don't emit a warning for the last expression in an expression