X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=parser.c;h=0e454421263c656680ec640896556f8d56ee0884;hb=524755e6c9e00c7aa78ecd7da9ecc3b15e795a43;hp=0dfaec2025a06c3d45eae113836afcb71014534b;hpb=36a0416cf620ad733aecde8f378c794e9967c796;p=cparser diff --git a/parser.c b/parser.c index 0dfaec2..0e45442 100644 --- a/parser.c +++ b/parser.c @@ -628,7 +628,7 @@ static int get_rank(const type_t *type) assert(type->kind == TYPE_ATOMIC); const atomic_type_t *atomic_type = &type->atomic; - atomic_type_type_t atype = atomic_type->atype; + atomic_type_kind_t atype = atomic_type->akind; return atype; } @@ -1008,7 +1008,7 @@ static initializer_t *initializer_from_expression(type_t *type, if (element_type->kind == TYPE_ATOMIC) { switch (expression->kind) { case EXPR_STRING_LITERAL: - if (element_type->atomic.atype == ATOMIC_TYPE_CHAR) { + if (element_type->atomic.akind == ATOMIC_TYPE_CHAR) { return initializer_from_string(array_type, expression->string.value); } @@ -1439,7 +1439,9 @@ static type_t *parse_enum_specifier(void) if(declaration->init.is_defined) { errorf(HERE, "multiple definitions of enum %Y", symbol); } - environment_push(declaration); + if (symbol != NULL) { + environment_push(declaration); + } append_declaration(declaration); declaration->init.is_defined = 1; @@ -1715,7 +1717,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) finish_specifiers: if(type == NULL) { - atomic_type_type_t atomic_type; + atomic_type_kind_t atomic_type; /* match valid basic types */ switch(type_specifiers) { @@ -1826,7 +1828,7 @@ finish_specifiers: } type = allocate_type_zero(TYPE_ATOMIC); - type->atomic.atype = atomic_type; + type->atomic.akind = atomic_type; newtype = 1; } else { if(type_specifiers != 0) { @@ -2321,6 +2323,11 @@ static declaration_t *internal_record_declaration( assert(declaration != previous_declaration); if (previous_declaration != NULL && previous_declaration->parent_context == context) { + /* can happen for K&R style declarations */ + if(previous_declaration->type == NULL) { + previous_declaration->type = declaration->type; + } + const type_t *const prev_type = skip_typeref(previous_declaration->type); if (!types_compatible(type, prev_type)) { errorf(declaration->source_position, @@ -2556,11 +2563,32 @@ static void parse_declaration_rest(declaration_t *ndeclaration, static declaration_t *finished_kr_declaration(declaration_t *declaration) { - /* TODO: check that it was actually a parameter that gets a type */ + symbol_t *symbol = declaration->symbol; + if(symbol == NULL) { + errorf(HERE, "anonymous declaration not valid as function parameter"); + return declaration; + } + namespace_t namespc = (namespace_t) declaration->namespc; + if(namespc != NAMESPACE_NORMAL) { + return record_declaration(declaration); + } - /* we should have a declaration for the parameter in the current - * scope */ - return record_declaration(declaration); + declaration_t *previous_declaration = get_declaration(symbol, namespc); + if(previous_declaration == NULL || + previous_declaration->parent_context != context) { + errorf(HERE, "expected declaration of a function parameter, found '%Y'", + symbol); + return declaration; + } + + if(previous_declaration->type == NULL) { + previous_declaration->type = declaration->type; + previous_declaration->storage_class = declaration->storage_class; + previous_declaration->parent_context = context; + return previous_declaration; + } else { + return record_declaration(declaration); + } } static void parse_declaration(parsed_declaration_func finished_declaration) @@ -2697,7 +2725,8 @@ static void parse_external_declaration(void) /* 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) { - errorf(HERE, "declarator '%#T' has a body but is not a function type", type, ndeclaration->symbol); + errorf(HERE, "declarator '%#T' has a body but is not a function type", + type, ndeclaration->symbol); eat_block(); return; } @@ -2728,7 +2757,11 @@ static void parse_external_declaration(void) declaration_t *parameter = declaration->context.declarations; for( ; parameter != NULL; parameter = parameter->next) { - assert(parameter->parent_context == NULL || parameter->parent_context == context); + 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); } @@ -2950,10 +2983,17 @@ static declaration_t *create_implicit_function(symbol_t *symbol, declaration->source_position = source_position; declaration->parent_context = global_context; + context_t *old_context = context; + set_context(global_context); + environment_push(declaration); + /* prepend the declaration to the global declarations list */ declaration->next = context->declarations; context->declarations = declaration; + assert(context == global_context); + set_context(old_context); + return declaration; } @@ -3552,6 +3592,21 @@ static expression_t *parse_primary_expression(void) return create_invalid_expression(); } +/** + * Check if the expression has the character type and issue a warning then. + */ +static void check_for_char_index_type(const expression_t *expression) { + type_t *type = expression->base.datatype; + type_t *base_type = skip_typeref(type); + + if (base_type->base.kind == TYPE_ATOMIC) { + if (base_type->atomic.akind == ATOMIC_TYPE_CHAR) { + warningf(expression->base.source_position, + "array subscript has type '%T'", type); + } + } +} + static expression_t *parse_array_expression(unsigned precedence, expression_t *left) { @@ -3579,12 +3634,14 @@ static expression_t *parse_array_expression(unsigned precedence, return_type = pointer->points_to; array_access->array_ref = left; array_access->index = inside; + check_for_char_index_type(inside); } else if(is_type_pointer(type_inside)) { pointer_type_t *pointer = &type_inside->pointer; return_type = pointer->points_to; array_access->array_ref = inside; array_access->index = left; array_access->flipped = true; + check_for_char_index_type(left); } else { errorf(HERE, "array access on object with non-pointer types '%T', '%T'", type_left, type_inside); } @@ -4912,7 +4969,9 @@ static statement_t *parse_switch(void) statement->statement.source_position = token.source_position; expect('('); - statement->expression = parse_expression(); + expression_t *const expr = parse_expression(); + type_t *const type = promote_integer(skip_typeref(expr->base.datatype)); + statement->expression = create_implicit_cast(expr, type); expect(')'); statement->body = parse_statement(); @@ -5063,6 +5122,38 @@ static statement_t *parse_break(void) return statement; } +/** + * Check if a given declaration represents a local variable. + */ +static bool is_local_var_declaration(const declaration_t *declaration) { + switch ((storage_class_tag_t) declaration->storage_class) { + case STORAGE_CLASS_NONE: + case STORAGE_CLASS_AUTO: + case STORAGE_CLASS_REGISTER: { + const type_t *type = skip_typeref(declaration->type); + if(is_type_function(type)) { + return false; + } else { + return true; + } + } + default: + return false; + } +} + +/** + * Check if a given expression represents a local variable. + */ +static bool is_local_variable(const expression_t *expression) +{ + if (expression->base.kind != EXPR_REFERENCE) { + return false; + } + const declaration_t *declaration = expression->reference.declaration; + return is_local_var_declaration(declaration); +} + /** * Parse a return statement. */ @@ -5097,16 +5188,26 @@ static statement_t *parse_return(void) if(is_type_atomic(return_type, ATOMIC_TYPE_VOID) && !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) { - warningf(HERE, "'return' with a value, in function returning void"); + warningf(statement->statement.source_position, + "'return' with a value, in function returning void"); return_value = NULL; } else { if(return_type != NULL) { semantic_assign(return_type, &return_value, "'return'"); } } + /* check for returning address of a local var */ + if (return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) { + const expression_t *expression = return_value->unary.value; + if (is_local_variable(expression)) { + warningf(statement->statement.source_position, + "function returns address of local variable"); + } + } } else { if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { - warningf(HERE, "'return' without value, in function returning non-void"); + warningf(statement->statement.source_position, + "'return' without value, in function returning non-void"); } } statement->return_value = return_value;