X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=parser.c;h=d1221c66c9b0ceb9a3fbabc00bae38d131076f19;hb=582d43e9816467c5f2562371c9d59ee2de5154be;hp=d0d3ddb83bfa4268dbaa2162ade55c487c0b2455;hpb=c1f09ffd706bd46c9785ccb187da54536f566e2e;p=cparser diff --git a/parser.c b/parser.c index d0d3ddb..d1221c6 100644 --- a/parser.c +++ b/parser.c @@ -140,7 +140,7 @@ static void *allocate_ast_zero(size_t size) static declaration_t *allocate_declaration_zero(void) { - declaration_t *declaration = allocate_ast_zero(sizeof(*allocate_declaration_zero())); + declaration_t *declaration = allocate_ast_zero(sizeof(declaration_t)); declaration->type = type_error_type; return declaration; } @@ -744,10 +744,15 @@ static type_t *semantic_assign(type_t *orig_type_left, points_to_left = get_unqualified_type(points_to_left); points_to_right = get_unqualified_type(points_to_right); - if(!is_type_atomic(points_to_left, ATOMIC_TYPE_VOID) - && !is_type_atomic(points_to_right, ATOMIC_TYPE_VOID) - && !types_compatible(points_to_left, points_to_right)) { - return NULL; + if (is_type_atomic(points_to_left, ATOMIC_TYPE_VOID) || + is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)) { + return orig_type_left; + } + + if (!types_compatible(points_to_left, points_to_right)) { + warningf(right->base.source_position, + "destination type '%T' in %s is incompatible with '%E' of type '%T'", + orig_type_left, context, right, orig_type_right); } return orig_type_left; @@ -1610,7 +1615,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) break; } case T_union: { - type = allocate_type_zero(TYPE_COMPOUND_STRUCT); + type = allocate_type_zero(TYPE_COMPOUND_UNION); type->compound.declaration = parse_compound_type_specifier(false); break; @@ -2315,8 +2320,8 @@ static declaration_t *internal_record_declaration( const symbol_t *const symbol = declaration->symbol; const namespace_t namespc = (namespace_t)declaration->namespc; - type_t *const orig_type = declaration->type; - const type_t *const type = skip_typeref(orig_type); + 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) { @@ -2338,18 +2343,27 @@ static declaration_t *internal_record_declaration( previous_declaration->type = declaration->type; } - const type_t *const prev_type = skip_typeref(previous_declaration->type); + const type_t *prev_type = skip_typeref(previous_declaration->type); if (!types_compatible(type, prev_type)) { errorf(declaration->source_position, - "declaration '%#T' is incompatible with previous declaration '%#T'", - orig_type, symbol, previous_declaration->type, symbol); - errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol); + "declaration '%#T' is incompatible with " + "previous declaration '%#T'", + orig_type, symbol, previous_declaration->type, symbol); + errorf(previous_declaration->source_position, + "previous declaration of '%Y' was here", symbol); } else { - unsigned old_storage_class = previous_declaration->storage_class; + unsigned old_storage_class + = previous_declaration->storage_class; unsigned new_storage_class = declaration->storage_class; - /* pretend no storage class means extern for function declarations - * (except if the previous declaration is neither none nor extern) */ + if(is_type_incomplete(prev_type)) { + previous_declaration->type = type; + prev_type = type; + } + + /* pretend no storage class means extern for function + * declarations (except if the previous declaration is neither + * none nor extern) */ if (is_type_function(type)) { switch (old_storage_class) { case STORAGE_CLASS_NONE: @@ -2360,7 +2374,9 @@ static declaration_t *internal_record_declaration( if (warning.missing_prototypes && prev_type->function.unspecified_parameters && !is_sym_main(symbol)) { - warningf(declaration->source_position, "no previous prototype for '%#T'", orig_type, symbol); + warningf(declaration->source_position, + "no previous prototype for '%#T'", + orig_type, symbol); } } else if (new_storage_class == STORAGE_CLASS_NONE) { new_storage_class = STORAGE_CLASS_EXTERN; @@ -2375,14 +2391,20 @@ static declaration_t *internal_record_declaration( new_storage_class == STORAGE_CLASS_EXTERN) { warn_redundant_declaration: if (warning.redundant_decls) { - warningf(declaration->source_position, "redundant declaration for '%Y'", symbol); - warningf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol); + warningf(declaration->source_position, + "redundant declaration for '%Y'", symbol); + warningf(previous_declaration->source_position, + "previous declaration of '%Y' was here", + symbol); } } else if (current_function == NULL) { if (old_storage_class != STORAGE_CLASS_STATIC && new_storage_class == STORAGE_CLASS_STATIC) { - errorf(declaration->source_position, "static declaration of '%Y' follows non-static declaration", symbol); - errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol); + errorf(declaration->source_position, + "static declaration of '%Y' follows non-static declaration", + symbol); + errorf(previous_declaration->source_position, + "previous declaration of '%Y' was here", symbol); } else { if (old_storage_class != STORAGE_CLASS_EXTERN && !is_function_definition) { goto warn_redundant_declaration; @@ -2393,11 +2415,15 @@ warn_redundant_declaration: } } else { if (old_storage_class == new_storage_class) { - errorf(declaration->source_position, "redeclaration of '%Y'", symbol); + errorf(declaration->source_position, + "redeclaration of '%Y'", symbol); } else { - errorf(declaration->source_position, "redeclaration of '%Y' with different linkage", symbol); + errorf(declaration->source_position, + "redeclaration of '%Y' with different linkage", + symbol); } - errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol); + errorf(previous_declaration->source_position, + "previous declaration of '%Y' was here", symbol); } } return previous_declaration; @@ -2405,9 +2431,12 @@ warn_redundant_declaration: } else if (is_function_definition) { if (declaration->storage_class != STORAGE_CLASS_STATIC) { if (warning.missing_prototypes && !is_sym_main(symbol)) { - warningf(declaration->source_position, "no previous prototype for '%#T'", orig_type, symbol); + warningf(declaration->source_position, + "no previous prototype for '%#T'", orig_type, symbol); } else if (warning.missing_declarations && !is_sym_main(symbol)) { - warningf(declaration->source_position, "no previous declaration for '%#T'", orig_type, symbol); + warningf(declaration->source_position, + "no previous declaration for '%#T'", orig_type, + symbol); } } } else if (warning.missing_declarations && @@ -2416,7 +2445,8 @@ warn_redundant_declaration: declaration->storage_class == STORAGE_CLASS_NONE || declaration->storage_class == STORAGE_CLASS_THREAD )) { - warningf(declaration->source_position, "no previous declaration for '%#T'", orig_type, symbol); + warningf(declaration->source_position, + "no previous declaration for '%#T'", orig_type, symbol); } assert(declaration->parent_scope == NULL); @@ -2744,8 +2774,8 @@ static void check_labels(void) label->used = true; if (label->source_position.input_name == NULL) { print_in_function(); - errorf(goto_statement->statement.source_position, - "label '%Y' used but not defined", label->symbol); + errorf(goto_statement->base.source_position, + "label '%Y' used but not defined", label->symbol); } } goto_first = goto_last = NULL; @@ -2758,7 +2788,7 @@ static void check_labels(void) if (! label->used) { print_in_function(); - warningf(label_statement->statement.source_position, + warningf(label_statement->base.source_position, "label '%Y' defined but not used", label->symbol); } } @@ -3023,7 +3053,7 @@ static expression_t *expected_expression_error(void) static expression_t *parse_string_const(void) { expression_t *cnst = allocate_expression_zero(EXPR_STRING_LITERAL); - cnst->base.type = type_string; + cnst->base.type = type_char_ptr; cnst->string.value = parse_string_literals(); return cnst; @@ -3139,11 +3169,11 @@ static type_t *get_builtin_symbol_type(symbol_t *symbol) case T___builtin_alloca: return make_function_1_type(type_void_ptr, type_size_t); case T___builtin_nan: - return make_function_1_type(type_double, type_string); + return make_function_1_type(type_double, type_char_ptr); case T___builtin_nanf: - return make_function_1_type(type_float, type_string); + return make_function_1_type(type_float, type_char_ptr); case T___builtin_nand: - return make_function_1_type(type_long_double, type_string); + return make_function_1_type(type_long_double, type_char_ptr); case T___builtin_va_end: return make_function_1_type(type_void, type_valist); default: @@ -3340,7 +3370,7 @@ static expression_t *parse_function_keyword(void) } expression_t *expression = allocate_expression_zero(EXPR_FUNCTION); - expression->base.type = type_string; + expression->base.type = type_char_ptr; return expression; } @@ -3355,7 +3385,7 @@ static expression_t *parse_pretty_function_keyword(void) } expression_t *expression = allocate_expression_zero(EXPR_PRETTY_FUNCTION); - expression->base.type = type_string; + expression->base.type = type_char_ptr; return expression; } @@ -3631,8 +3661,10 @@ static expression_t *parse_primary_expression(void) return parse_va_arg(); case T___builtin_expect: return parse_builtin_expect(); - case T___builtin_nanf: case T___builtin_alloca: + case T___builtin_nan: + case T___builtin_nand: + case T___builtin_nanf: case T___builtin_va_end: return parse_builtin_symbol(); case T___builtin_isgreater: @@ -5038,7 +5070,7 @@ static statement_t *parse_case_statement(void) "case label not within a switch statement"); } } - statement->case_label.label_statement = parse_statement(); + statement->case_label.statement = parse_statement(); return statement; } @@ -5074,7 +5106,7 @@ static statement_t *parse_default_statement(void) const case_label_statement_t *def_label = find_default_label(current_switch); if (def_label != NULL) { errorf(HERE, "multiple default labels in one switch"); - errorf(def_label->statement.source_position, + errorf(def_label->base.source_position, "this is the first default label"); } else { /* link all cases into the switch statement */ @@ -5089,7 +5121,7 @@ static statement_t *parse_default_statement(void) errorf(statement->base.source_position, "'default' label not within a switch statement"); } - statement->label.label_statement = parse_statement(); + statement->label.statement = parse_statement(); return statement; } @@ -5139,18 +5171,17 @@ static statement_t *parse_label_statement(void) label->source_position = token.source_position; } - label_statement_t *label_statement = allocate_ast_zero(sizeof(label[0])); + statement_t *statement = allocate_statement_zero(STATEMENT_LABEL); - label_statement->statement.kind = STATEMENT_LABEL; - label_statement->statement.source_position = token.source_position; - label_statement->label = label; + statement->base.source_position = token.source_position; + statement->label.label = label; eat(':'); if(token.type == '}') { /* TODO only warn? */ errorf(HERE, "label at end of compound statement"); - return (statement_t*) label_statement; + return statement; } else { if (token.type == ';') { /* eat an empty statement here, to avoid the warning about an empty @@ -5158,19 +5189,19 @@ static statement_t *parse_label_statement(void) * a }. */ next_token(); } else { - label_statement->label_statement = parse_statement(); + statement->label.statement = parse_statement(); } } /* remember the labels's in a list for later checking */ if (label_last == NULL) { - label_first = label_statement; + label_first = &statement->label; } else { - label_last->next = label_statement; + label_last->next = &statement->label; } - label_last = label_statement; + label_last = &statement->label; - return (statement_t*) label_statement; + return statement; } /** @@ -5180,21 +5211,20 @@ static statement_t *parse_if(void) { eat(T_if); - if_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->statement.kind = STATEMENT_IF; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_IF); + statement->base.source_position = token.source_position; expect('('); - statement->condition = parse_expression(); + statement->ifs.condition = parse_expression(); expect(')'); - statement->true_statement = parse_statement(); + statement->ifs.true_statement = parse_statement(); if(token.type == T_else) { next_token(); - statement->false_statement = parse_statement(); + statement->ifs.false_statement = parse_statement(); } - return (statement_t*) statement; + return statement; } /** @@ -5204,9 +5234,8 @@ static statement_t *parse_switch(void) { eat(T_switch); - switch_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->statement.kind = STATEMENT_SWITCH; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_SWITCH); + statement->base.source_position = token.source_position; expect('('); expression_t *const expr = parse_expression(); @@ -5214,29 +5243,33 @@ static statement_t *parse_switch(void) if (is_type_integer(type)) { type = promote_integer(type); } else if (is_type_valid(type)) { - errorf(expr->base.source_position, "switch quantity is not an integer, but '%T'", type); + errorf(expr->base.source_position, + "switch quantity is not an integer, but '%T'", type); type = type_error_type; } - statement->expression = create_implicit_cast(expr, type); + statement->switchs.expression = create_implicit_cast(expr, type); expect(')'); switch_statement_t *rem = current_switch; - current_switch = statement; - statement->body = parse_statement(); - current_switch = rem; + current_switch = &statement->switchs; + statement->switchs.body = parse_statement(); + current_switch = rem; - if (warning.switch_default && find_default_label(statement) == NULL) { - warningf(statement->statement.source_position, "switch has no default case"); + if (warning.switch_default + && find_default_label(&statement->switchs) == NULL) { + warningf(statement->base.source_position, "switch has no default case"); } - return (statement_t*) statement; + return statement; } static statement_t *parse_loop_body(statement_t *const loop) { statement_t *const rem = current_loop; current_loop = loop; + statement_t *const body = parse_statement(); + current_loop = rem; return body; } @@ -5248,17 +5281,16 @@ static statement_t *parse_while(void) { eat(T_while); - while_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->statement.kind = STATEMENT_WHILE; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_WHILE); + statement->base.source_position = token.source_position; expect('('); - statement->condition = parse_expression(); + statement->whiles.condition = parse_expression(); expect(')'); - statement->body = parse_loop_body((statement_t*)statement); + statement->whiles.body = parse_loop_body(statement); - return (statement_t*) statement; + return statement; } /** @@ -5268,18 +5300,19 @@ static statement_t *parse_do(void) { eat(T_do); - do_while_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->statement.kind = STATEMENT_DO_WHILE; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_DO_WHILE); + + statement->base.source_position = token.source_position; + + statement->do_while.body = parse_loop_body(statement); - statement->body = parse_loop_body((statement_t*)statement); expect(T_while); expect('('); - statement->condition = parse_expression(); + statement->do_while.condition = parse_expression(); expect(')'); expect(';'); - return (statement_t*) statement; + return statement; } /** @@ -5289,21 +5322,20 @@ static statement_t *parse_for(void) { eat(T_for); - for_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - statement->statement.kind = STATEMENT_FOR; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_FOR); + statement->base.source_position = token.source_position; expect('('); int top = environment_top(); scope_t *last_scope = scope; - set_scope(&statement->scope); + set_scope(&statement->fors.scope); if(token.type != ';') { if(is_declaration_specifier(&token, false)) { parse_declaration(record_declaration); } else { - statement->initialisation = parse_expression(); + statement->fors.initialisation = parse_expression(); expect(';'); } } else { @@ -5311,20 +5343,20 @@ static statement_t *parse_for(void) } if(token.type != ';') { - statement->condition = parse_expression(); + statement->fors.condition = parse_expression(); } expect(';'); if(token.type != ')') { - statement->step = parse_expression(); + statement->fors.step = parse_expression(); } expect(')'); - statement->body = parse_loop_body((statement_t*)statement); + statement->fors.body = parse_loop_body(statement); - assert(scope == &statement->scope); + assert(scope == &statement->fors.scope); set_scope(last_scope); environment_pop_to(top); - return (statement_t*) statement; + return statement; } /** @@ -5344,24 +5376,22 @@ static statement_t *parse_goto(void) declaration_t *label = get_label(symbol); - goto_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - - statement->statement.kind = STATEMENT_GOTO; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_GOTO); + statement->base.source_position = token.source_position; - statement->label = label; + statement->gotos.label = label; /* remember the goto's in a list for later checking */ if (goto_last == NULL) { - goto_first = statement; + goto_first = &statement->gotos; } else { - goto_last->next = statement; + goto_last->next = &statement->gotos; } - goto_last = statement; + goto_last = &statement->gotos; expect(';'); - return (statement_t*) statement; + return statement; } /** @@ -5485,10 +5515,8 @@ static statement_t *parse_return(void) { eat(T_return); - return_statement_t *statement = allocate_ast_zero(sizeof(statement[0])); - - statement->statement.kind = STATEMENT_RETURN; - statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_RETURN); + statement->base.source_position = token.source_position; expression_t *return_value = NULL; if(token.type != ';') { @@ -5505,16 +5533,16 @@ 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(statement->statement.source_position, - "'return' with a value, in function returning void"); + warningf(statement->base.source_position, + "'return' with a value, in function returning void"); return_value = NULL; } else { type_t *const res_type = semantic_assign(return_type, return_value, "'return'"); if (res_type == NULL) { - errorf(statement->statement.source_position, - "cannot return something of type '%T' in function returning '%T'", - return_value->base.type, return_type); + errorf(statement->base.source_position, + "cannot return something of type '%T' in function returning '%T'", + return_value->base.type, return_type); } else { return_value = create_implicit_cast(return_value, res_type); } @@ -5523,19 +5551,19 @@ static statement_t *parse_return(void) 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"); + warningf(statement->base.source_position, + "function returns address of local variable"); } } } else { if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { - warningf(statement->statement.source_position, - "'return' without value, in function returning non-void"); + warningf(statement->base.source_position, + "'return' without value, in function returning non-void"); } } - statement->return_value = return_value; + statement->returns.value = return_value; - return (statement_t*) statement; + return statement; } /** @@ -5692,47 +5720,47 @@ static statement_t *parse_statement(void) */ static statement_t *parse_compound_statement(void) { - compound_statement_t *const compound_statement - = allocate_ast_zero(sizeof(compound_statement[0])); - compound_statement->statement.kind = STATEMENT_COMPOUND; - compound_statement->statement.source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND); + + statement->base.source_position = token.source_position; eat('{'); int top = environment_top(); scope_t *last_scope = scope; - set_scope(&compound_statement->scope); + set_scope(&statement->compound.scope); statement_t *last_statement = NULL; while(token.type != '}' && token.type != T_EOF) { - statement_t *statement = parse_statement(); - if(statement == NULL) + statement_t *sub_statement = parse_statement(); + if(sub_statement == NULL) continue; if(last_statement != NULL) { - last_statement->base.next = statement; + last_statement->base.next = sub_statement; } else { - compound_statement->statements = statement; + statement->compound.statements = sub_statement; } - while(statement->base.next != NULL) - statement = statement->base.next; + while(sub_statement->base.next != NULL) + sub_statement = sub_statement->base.next; - last_statement = statement; + last_statement = sub_statement; } if(token.type == '}') { next_token(); } else { - errorf(compound_statement->statement.source_position, "end of file while looking for closing '}'"); + errorf(statement->base.source_position, + "end of file while looking for closing '}'"); } - assert(scope == &compound_statement->scope); + assert(scope == &statement->compound.scope); set_scope(last_scope); environment_pop_to(top); - return (statement_t*) compound_statement; + return statement; } /**