len * sizeof(initializers[0]));
DEL_ARR_F(initializers);
- ascend_to(path, top_path_level);
+ ascend_to(path, top_path_level+1);
return result;
end_error:
skip_initializers();
DEL_ARR_F(initializers);
- ascend_to(path, top_path_level);
+ ascend_to(path, top_path_level+1);
return NULL;
}
const symbol_t *const symbol = declaration->symbol;
const namespace_t namespc = (namespace_t)declaration->namespc;
+ assert(declaration->symbol != NULL);
+ declaration_t *previous_declaration = get_declaration(symbol, namespc);
+
type_t *const orig_type = declaration->type;
type_t *const type = skip_typeref(orig_type);
if (is_type_function(type) &&
type->function.unspecified_parameters &&
- warning.strict_prototypes) {
+ warning.strict_prototypes &&
+ previous_declaration == NULL) {
warningf(&declaration->source_position,
"function declaration '%#T' is not a prototype",
orig_type, declaration->symbol);
check_type_of_main(declaration, &type->function);
}
- assert(declaration->symbol != NULL);
- declaration_t *previous_declaration = get_declaration(symbol, namespc);
-
assert(declaration != previous_declaration);
if (previous_declaration != NULL) {
if (previous_declaration->parent_scope == scope) {
}
}
+static type_t *get_default_promoted_type(type_t *orig_type)
+{
+ type_t *result = orig_type;
+
+ type_t *type = skip_typeref(orig_type);
+ if(is_type_integer(type)) {
+ result = promote_integer(type);
+ } else if(type == type_float) {
+ result = type_double;
+ }
+
+ return result;
+}
+
static void parse_kr_declaration_list(declaration_t *declaration)
{
type_t *type = skip_typeref(declaration->type);
semantic_parameter(parameter_declaration);
parameter_type = parameter_declaration->type;
+ /*
+ * we need the default promoted types for the function type
+ */
+ parameter_type = get_default_promoted_type(parameter_type);
+
function_parameter_t *function_parameter
= obstack_alloc(type_obst, sizeof(function_parameter[0]));
memset(function_parameter, 0, sizeof(function_parameter[0]));
/* ยง 6.9.1.7: A K&R style parameter list does NOT act as a function
* prototype */
- new_type->function.parameters = parameters;
+ new_type->function.parameters = parameters;
new_type->function.unspecified_parameters = true;
type = typehash_insert(new_type);
}
}
-/**
- * check all returns vor matching type.
- */
-static bool search_return_statements(statement_t *statement) {
- switch(statement->kind) {
- case STATEMENT_RETURN:
- /* ok, found a return */
- return true;
- case STATEMENT_IF: {
- /* return must be found on then and else */
- if_statement_t *if_stat = &statement->ifs;
- if(if_stat->true_statement != NULL && if_stat->false_statement != NULL) {
- return search_return_statements(if_stat->true_statement) &&
- search_return_statements(if_stat->false_statement);
- }
- break;
- }
- case STATEMENT_DO_WHILE: {
- do_while_statement_t *do_stmt = &statement->do_while;
- if(do_stmt->body != NULL) {
- if (search_return_statements(do_stmt->body))
- return true;
- }
- break;
- }
- case STATEMENT_COMPOUND: {
- /* search the last statement */
- compound_statement_t *compound = &statement->compound;
- statement_t *statement = compound->statements;
- if(statement == NULL)
- return false;
- for( ; statement != NULL; statement = statement->base.next) {
- if (search_return_statements(statement))
- return true;
- }
- break;
- }
- default:
- break;
- }
- return false;
-}
-
-/**
- * Check returns of a function.
- */
-static void check_return_type(declaration_t *declaration) {
- function_type_t *function_type = &declaration->type->function;
- type_t *ret_type = function_type->return_type;
-
- if (ret_type != type_void) {
- if (! search_return_statements(declaration->init.statement)) {
- warningf(HERE, "missing return statement at end of non-void function '%Y'",
- declaration->symbol);
- }
- }
-}
-
static void parse_external_declaration(void)
{
/* function-definitions and declarations both start with declaration
assert(current_function == declaration);
current_function = old_current_function;
label_pop_to(label_stack_top);
- check_return_type(declaration);
}
end_of_parse_external_declaration:
rem_anchor_token(')');
expect(')');
- if(function_type != NULL) {
- function_parameter_t *parameter = function_type->parameters;
- call_argument_t *argument = call->arguments;
+ if(function_type == NULL)
+ return result;
+
+ function_parameter_t *parameter = function_type->parameters;
+ call_argument_t *argument = call->arguments;
+ if (!function_type->unspecified_parameters) {
for( ; parameter != NULL && argument != NULL;
parameter = parameter->next, argument = argument->next) {
type_t *expected_type = parameter->type;
/* TODO report scope in error messages */
expression_t *const arg_expr = argument->expression;
type_t *const res_type = semantic_assign(expected_type, arg_expr,
- "function call",
- &arg_expr->base.source_position);
+ "function call",
+ &arg_expr->base.source_position);
if (res_type == NULL) {
/* TODO improve error message */
errorf(&arg_expr->base.source_position,
argument->expression = create_implicit_cast(argument->expression, expected_type);
}
}
- /* too few parameters */
- if(parameter != NULL) {
+
+ if (parameter != NULL) {
errorf(HERE, "too few arguments to function '%E'", expression);
- } else if(argument != NULL) {
- /* too many parameters */
- if(!function_type->variadic
- && !function_type->unspecified_parameters) {
- errorf(HERE, "too many arguments to function '%E'", expression);
- } else {
- /* do default promotion */
- for( ; argument != NULL; argument = argument->next) {
- type_t *type = argument->expression->base.type;
-
- type = skip_typeref(type);
- if(is_type_integer(type)) {
- type = promote_integer(type);
- } else if(type == type_float) {
- type = type_double;
- }
+ } else if (argument != NULL && !function_type->variadic) {
+ errorf(HERE, "too many arguments to function '%E'", expression);
+ }
+ }
- argument->expression
- = create_implicit_cast(argument->expression, type);
- }
+ /* do default promotion */
+ for( ; argument != NULL; argument = argument->next) {
+ type_t *type = argument->expression->base.type;
- check_format(&result->call);
- }
- } else {
- check_format(&result->call);
- }
+ type = get_default_promoted_type(type);
+
+ argument->expression
+ = create_implicit_cast(argument->expression, type);
}
+ check_format(&result->call);
+
return result;
end_error:
return create_invalid_expression();
register_infix_parser(parse_EXPR_UNARY_POSTFIX_DECREMENT,
T_MINUSMINUS, 30);
- register_infix_parser(parse_EXPR_BINARY_MUL, '*', 16);
- register_infix_parser(parse_EXPR_BINARY_DIV, '/', 16);
- register_infix_parser(parse_EXPR_BINARY_MOD, '%', 16);
- register_infix_parser(parse_EXPR_BINARY_SHIFTLEFT, T_LESSLESS, 16);
- register_infix_parser(parse_EXPR_BINARY_SHIFTRIGHT, T_GREATERGREATER, 16);
- register_infix_parser(parse_EXPR_BINARY_ADD, '+', 15);
- register_infix_parser(parse_EXPR_BINARY_SUB, '-', 15);
+ register_infix_parser(parse_EXPR_BINARY_MUL, '*', 17);
+ register_infix_parser(parse_EXPR_BINARY_DIV, '/', 17);
+ register_infix_parser(parse_EXPR_BINARY_MOD, '%', 17);
+ register_infix_parser(parse_EXPR_BINARY_ADD, '+', 16);
+ register_infix_parser(parse_EXPR_BINARY_SUB, '-', 16);
+ register_infix_parser(parse_EXPR_BINARY_SHIFTLEFT, T_LESSLESS, 15);
+ register_infix_parser(parse_EXPR_BINARY_SHIFTRIGHT, T_GREATERGREATER, 15);
register_infix_parser(parse_EXPR_BINARY_LESS, '<', 14);
register_infix_parser(parse_EXPR_BINARY_GREATER, '>', 14);
register_infix_parser(parse_EXPR_BINARY_LESSEQUAL, T_LESSEQUAL, 14);