+ declaration_t *parameter_declaration = declaration->context.declarations;
+ for( ; parameter_declaration != NULL;
+ parameter_declaration = parameter_declaration->next) {
+ type_t *parameter_type = parameter_declaration->type;
+ if(parameter_type == NULL) {
+ if (strict_mode) {
+ errorf(HERE, "no type specified for function parameter '%Y'",
+ parameter_declaration->symbol);
+ } else {
+ if (warning.implicit_int) {
+ warningf(HERE, "no type specified for function parameter '%Y', using 'int'",
+ parameter_declaration->symbol);
+ }
+ parameter_type = type_int;
+ parameter_declaration->type = parameter_type;
+ }
+ }
+
+ semantic_parameter(parameter_declaration);
+ parameter_type = parameter_declaration->type;
+
+ function_parameter_t *function_parameter
+ = obstack_alloc(type_obst, sizeof(function_parameter[0]));
+ memset(function_parameter, 0, sizeof(function_parameter[0]));
+
+ function_parameter->type = parameter_type;
+ if(last_parameter != NULL) {
+ last_parameter->next = function_parameter;
+ } else {
+ parameters = function_parameter;
+ }
+ last_parameter = function_parameter;
+ }
+ new_type->function.parameters = parameters;
+
+ type = typehash_insert(new_type);
+ if(type != new_type) {
+ obstack_free(type_obst, new_type);
+ }
+
+ declaration->type = type;
+}
+
+/**
+ * Check if all labels are defined in the current function.
+ */
+static void check_for_missing_labels(void)
+{
+ bool first_err = true;
+ for (const goto_statement_t *goto_statement = goto_first;
+ goto_statement != NULL;
+ goto_statement = goto_statement->next) {
+ const declaration_t *label = goto_statement->label;
+
+ if (label->source_position.input_name == NULL) {
+ if (first_err) {
+ first_err = false;
+ diagnosticf("%s: In function '%Y':\n",
+ current_function->source_position.input_name,
+ current_function->symbol);
+ }
+ errorf(goto_statement->statement.source_position,
+ "label '%Y' used but not defined", label->symbol);
+ }
+ }
+ goto_first = goto_last = NULL;
+}
+
+static void parse_external_declaration(void)
+{
+ /* function-definitions and declarations both start with declaration
+ * specifiers */
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+
+ /* must be a declaration */
+ if(token.type == ';') {
+ parse_anonymous_declaration_rest(&specifiers, append_declaration);
+ return;
+ }
+
+ /* declarator is common to both function-definitions and declarations */
+ declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
+
+ /* must be a declaration */
+ if(token.type == ',' || token.type == '=' || token.type == ';') {
+ parse_declaration_rest(ndeclaration, &specifiers, record_declaration);
+ return;
+ }
+
+ /* must be a function definition */
+ parse_kr_declaration_list(ndeclaration);
+
+ if(token.type != '{') {
+ parse_error_expected("while parsing function definition", '{', 0);
+ eat_statement();
+ return;
+ }
+
+ type_t *type = ndeclaration->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_valid(type)) {
+ errorf(HERE, "declarator '%#T' has a body but is not a function type",
+ type, ndeclaration->symbol);
+ }
+ eat_block();
+ return;
+ }
+
+ /* § 6.7.5.3 (14) a function definition with () means no
+ * parameters (and not unspecified parameters) */
+ if(type->function.unspecified_parameters) {
+ type_t *duplicate = duplicate_type(type);
+ duplicate->function.unspecified_parameters = false;
+
+ type = typehash_insert(duplicate);
+ if(type != duplicate) {
+ obstack_free(type_obst, duplicate);
+ }
+ ndeclaration->type = type;
+ }
+
+ declaration_t *const declaration = record_function_definition(ndeclaration);
+ if(ndeclaration != declaration) {
+ declaration->context = ndeclaration->context;
+ }
+ type = skip_typeref(declaration->type);
+
+ /* push function parameters and switch context */
+ int top = environment_top();
+ context_t *last_context = context;
+ set_context(&declaration->context);
+
+ declaration_t *parameter = declaration->context.declarations;
+ for( ; parameter != NULL; parameter = parameter->next) {
+ if(parameter->parent_context == &ndeclaration->context) {
+ parameter->parent_context = context;
+ }
+ assert(parameter->parent_context == NULL
+ || parameter->parent_context == context);
+ parameter->parent_context = context;
+ environment_push(parameter);
+ }
+
+ if(declaration->init.statement != NULL) {
+ parser_error_multiple_definition(declaration, token.source_position);
+ eat_block();
+ goto end_of_parse_external_declaration;
+ } else {
+ /* parse function body */
+ int label_stack_top = label_top();
+ declaration_t *old_current_function = current_function;
+ current_function = declaration;
+
+ declaration->init.statement = parse_compound_statement();
+ check_for_missing_labels();
+
+ assert(current_function == declaration);
+ current_function = old_current_function;
+ label_pop_to(label_stack_top);
+ }
+
+end_of_parse_external_declaration:
+ assert(context == &declaration->context);
+ set_context(last_context);
+ environment_pop_to(top);
+}
+
+static type_t *make_bitfield_type(type_t *base, expression_t *size)
+{
+ type_t *type = allocate_type_zero(TYPE_BITFIELD);
+ type->bitfield.base = base;
+ type->bitfield.size = size;
+
+ return type;
+}
+
+static void parse_struct_declarators(const declaration_specifiers_t *specifiers)
+{
+ /* TODO: check constraints for struct declarations (in specifiers) */
+ while(1) {
+ declaration_t *declaration;
+
+ if(token.type == ':') {
+ next_token();
+
+ type_t *base_type = specifiers->type;
+ expression_t *size = parse_constant_expression();
+
+ type_t *type = make_bitfield_type(base_type, size);
+
+ declaration = allocate_declaration_zero();
+ declaration->namespc = NAMESPACE_NORMAL;
+ declaration->storage_class = STORAGE_CLASS_NONE;
+ declaration->source_position = token.source_position;
+ declaration->modifiers = specifiers->decl_modifiers;
+ declaration->type = type;
+ } else {
+ declaration = parse_declarator(specifiers,/*may_be_abstract=*/true);
+
+ if(token.type == ':') {
+ next_token();
+ expression_t *size = parse_constant_expression();
+
+ type_t *type = make_bitfield_type(declaration->type, size);
+ declaration->type = type;
+ }
+ }
+ record_declaration(declaration);
+
+ if(token.type != ',')
+ break;
+ next_token();
+ }
+ expect_void(';');
+}
+
+static void parse_compound_type_entries(void)
+{
+ eat('{');
+
+ while(token.type != '}' && token.type != T_EOF) {
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+
+ parse_struct_declarators(&specifiers);
+ }
+ if(token.type == T_EOF) {
+ errorf(HERE, "EOF while parsing struct");
+ }
+ next_token();
+}
+
+static type_t *parse_typename(void)
+{
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+ if(specifiers.storage_class != STORAGE_CLASS_NONE) {
+ /* TODO: improve error message, user does probably not know what a
+ * storage class is...
+ */
+ errorf(HERE, "typename may not have a storage class");
+ }
+
+ type_t *result = parse_abstract_declarator(specifiers.type);
+
+ return result;
+}
+
+
+
+
+typedef expression_t* (*parse_expression_function) (unsigned precedence);