X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=497ecd634e8fd5e20c49bf69e2ddcf8166b2a9fb;hb=9e9141455d9e7a9028d7ffa1d5656b1e9bb25c74;hp=f14f2423265f72aac59a77df5f56edea10adb8ba;hpb=9d26a49e94a6cd2a4ad0d35faa6d7b0b628866d9;p=cparser diff --git a/parser.c b/parser.c index f14f242..497ecd6 100644 --- a/parser.c +++ b/parser.c @@ -115,7 +115,7 @@ static stack_entry_t *environment_stack = NULL; static stack_entry_t *label_stack = NULL; static stack_entry_t *local_label_stack = NULL; /** The global file scope. */ -static scope_t *global_scope = NULL; +static scope_t *file_scope = NULL; /** The current scope. */ static scope_t *scope = NULL; static declaration_t *last_declaration = NULL; @@ -356,8 +356,9 @@ static statement_t *allocate_statement_zero(statement_kind_t kind) size_t size = get_statement_struct_size(kind); statement_t *res = allocate_ast_zero(size); - res->base.kind = kind; - res->base.parent = current_parent; + res->base.kind = kind; + res->base.parent = current_parent; + res->base.source_position = token.source_position; return res; } @@ -390,9 +391,7 @@ static expression_t *create_invalid_expression(void) */ static statement_t *create_invalid_statement(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_INVALID); - statement->base.source_position = token.source_position; - return statement; + return allocate_statement_zero(STATEMENT_INVALID); } /** @@ -400,9 +399,7 @@ static statement_t *create_invalid_statement(void) */ static statement_t *create_empty_statement(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_EMPTY); - statement->base.source_position = token.source_position; - return statement; + return allocate_statement_zero(STATEMENT_EMPTY); } /** @@ -845,10 +842,14 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top) break; } - /* Because of scopes and appending other namespaces to the end of - * the list, this must hold. */ - assert((old_declaration != NULL ? old_declaration->symbol_next : NULL) == iter->symbol_next); - *anchor = old_declaration; + /* Not all declarations adhere scopes (e.g. jump labels), so this + * correction is necessary */ + if (old_declaration != NULL) { + old_declaration->symbol_next = iter->symbol_next; + *anchor = old_declaration; + } else { + *anchor = iter->symbol_next; + } } ARR_SHRINKLEN(*stack_ptr, (int) new_top); @@ -1661,7 +1662,6 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) } switch(kind) { - case GNU_AK_CONST: case GNU_AK_VOLATILE: case GNU_AK_NAKED: case GNU_AK_MALLOC: @@ -1701,6 +1701,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) case GNU_AK_UNUSED: modifiers |= DM_UNUSED; goto no_arg; case GNU_AK_USED: modifiers |= DM_USED; goto no_arg; case GNU_AK_PURE: modifiers |= DM_PURE; goto no_arg; + case GNU_AK_CONST: modifiers |= DM_CONST; goto no_arg; case GNU_AK_ALWAYS_INLINE: modifiers |= DM_FORCEINLINE; goto no_arg; case GNU_AK_DLLIMPORT: modifiers |= DM_DLLIMPORT; goto no_arg; case GNU_AK_DLLEXPORT: modifiers |= DM_DLLEXPORT; goto no_arg; @@ -1990,6 +1991,11 @@ static initializer_t *initializer_from_expression(type_t *orig_type, &expression->base.source_position); initializer_t *const result = allocate_initializer_zero(INITIALIZER_VALUE); +#if 0 + if (type->kind == TYPE_BITFIELD) { + type = type->bitfield.base_type; + } +#endif result->value.value = create_implicit_cast(expression, type); return result; @@ -2210,34 +2216,37 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, "'.%Y' designator used for non-compound type '%T'", symbol, orig_type); } - goto failed; - } - declaration_t *declaration = type->compound.declaration; - declaration_t *iter = declaration->scope.declarations; - for( ; iter != NULL; iter = iter->next) { - if (iter->symbol == symbol) { - break; + top->type = type_error_type; + top->v.compound_entry = NULL; + orig_type = type_error_type; + } else { + declaration_t *declaration = type->compound.declaration; + declaration_t *iter = declaration->scope.declarations; + for( ; iter != NULL; iter = iter->next) { + if (iter->symbol == symbol) { + break; + } } - } - if (iter == NULL) { - errorf(&designator->source_position, - "'%T' has no member named '%Y'", orig_type, symbol); - goto failed; - } - if (used_in_offsetof) { - type_t *real_type = skip_typeref(iter->type); - if (real_type->kind == TYPE_BITFIELD) { + if (iter == NULL) { errorf(&designator->source_position, - "offsetof designator '%Y' may not specify bitfield", - symbol); + "'%T' has no member named '%Y'", orig_type, symbol); goto failed; } - } + if (used_in_offsetof) { + type_t *real_type = skip_typeref(iter->type); + if (real_type->kind == TYPE_BITFIELD) { + errorf(&designator->source_position, + "offsetof designator '%Y' may not specify bitfield", + symbol); + goto failed; + } + } - top->type = orig_type; - top->v.compound_entry = iter; - orig_type = iter->type; + top->type = orig_type; + top->v.compound_entry = iter; + orig_type = iter->type; + } } else { expression_t *array_index = designator->array_index; assert(designator->array_index != NULL); @@ -2250,24 +2259,18 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, } goto failed; } - if (!is_type_valid(array_index->base.type)) { - goto failed; - } long index = fold_constant(array_index); if (!used_in_offsetof) { if (index < 0) { errorf(&designator->source_position, "array index [%E] must be positive", array_index); - goto failed; - } - if (type->array.size_constant == true) { + } else if (type->array.size_constant) { long array_size = type->array.size; if (index >= array_size) { errorf(&designator->source_position, "designator [%E] (%d) exceeds array size %d", array_index, index, array_size); - goto failed; } } } @@ -2305,7 +2308,7 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) path->top_type = entry->type; return; } - } else { + } else if (is_type_array(type)) { assert(is_type_array(type)); top->v.index++; @@ -2313,6 +2316,9 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) if (!type->array.size_constant || top->v.index < type->array.size) { return; } + } else { + assert(!is_type_valid(type)); + return; } /* we're past the last member of the current sub-aggregate, try if we @@ -2384,13 +2390,6 @@ static initializer_t *parse_sub_initializer(type_path_t *path, /* We are initializing an empty compound. */ } else { type = skip_typeref(orig_type); - - /* we can't do usefull stuff if we didn't even parse the type. Skip the - * initializers in this case. */ - if (!is_type_valid(type)) { - skip_initializers(); - return create_empty_initializer(); - } } initializer_t **initializers = NEW_ARR_F(initializer_t*, 0); @@ -2467,8 +2466,9 @@ finish_designator: if (type == NULL) { /* we are already outside, ... */ - if (is_type_compound(outer_type) && - !outer_type->compound.declaration->init.complete) { + type_t *const outer_type_skip = skip_typeref(outer_type); + if (is_type_compound(outer_type_skip) && + !outer_type_skip->compound.declaration->init.complete) { goto error_parse_next; } goto error_excess; @@ -3112,7 +3112,7 @@ static declaration_t *create_error_declaration(symbol_t *symbol, storage_class_t decl->source_position = *HERE; decl->declared_storage_class = storage_class; decl->storage_class = - storage_class != STORAGE_CLASS_NONE || scope == global_scope ? + storage_class != STORAGE_CLASS_NONE || scope == file_scope ? storage_class : STORAGE_CLASS_AUTO; decl->symbol = symbol; decl->implicit = true; @@ -3364,8 +3364,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) type->compound.declaration = parse_compound_type_specifier(false); if (type->compound.declaration->modifiers & DM_TRANSPARENT_UNION) modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; - break; finish_union_type(&type->compound); + break; } case T_enum: type = parse_enum_specifier(); @@ -4259,8 +4259,8 @@ static declaration_t *parse_declarator( declaration->is_inline = specifiers->is_inline; declaration->storage_class = specifiers->declared_storage_class; - if (declaration->storage_class == STORAGE_CLASS_NONE - && scope != global_scope) { + if (declaration->storage_class == STORAGE_CLASS_NONE && + scope != file_scope) { declaration->storage_class = STORAGE_CLASS_AUTO; } @@ -4396,7 +4396,7 @@ static declaration_t *record_declaration( if (warning.nested_externs && declaration->storage_class == STORAGE_CLASS_EXTERN && - scope != global_scope) { + scope != file_scope) { warningf(&declaration->source_position, "nested extern declaration of '%#T'", declaration->type, symbol); } @@ -4536,7 +4536,7 @@ warn_redundant_declaration: } } else { if (warning.missing_declarations && - scope == global_scope && ( + scope == file_scope && ( declaration->storage_class == STORAGE_CLASS_NONE || declaration->storage_class == STORAGE_CLASS_THREAD )) { @@ -4592,9 +4592,9 @@ static void parse_init_declarator_rest(declaration_t *declaration) } bool must_be_constant = false; - if (declaration->storage_class == STORAGE_CLASS_STATIC - || declaration->storage_class == STORAGE_CLASS_THREAD_STATIC - || declaration->parent_scope == global_scope) { + if (declaration->storage_class == STORAGE_CLASS_STATIC || + declaration->storage_class == STORAGE_CLASS_THREAD_STATIC || + declaration->parent_scope == file_scope) { must_be_constant = true; } @@ -6014,11 +6014,17 @@ static type_t *get_builtin_symbol_type(symbol_t *symbol) return make_function_1_type(type_void_ptr, type_size_t); case T___builtin_huge_val: return make_function_0_type(type_double); + case T___builtin_inf: + return make_function_0_type(type_double); + case T___builtin_inff: + return make_function_0_type(type_float); + case T___builtin_infl: + return make_function_0_type(type_long_double); case T___builtin_nan: return make_function_1_type(type_double, type_char_ptr); case T___builtin_nanf: return make_function_1_type(type_float, type_char_ptr); - case T___builtin_nand: + case T___builtin_nanl: 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); @@ -6139,7 +6145,7 @@ static expression_t *parse_reference(void) /* this declaration is used */ declaration->used = true; - if (declaration->parent_scope != global_scope && + if (declaration->parent_scope != file_scope && declaration->parent_scope->depth < current_function->scope.depth && is_type_valid(orig_type) && !is_type_function(orig_type)) { /* access of a variable from an outer function */ @@ -6639,7 +6645,6 @@ static expression_t *parse_compare_builtin(void) break; default: internal_errorf(HERE, "invalid compare builtin found"); - break; } expression->base.source_position = *HERE; next_token(); @@ -6847,9 +6852,12 @@ static expression_t *parse_primary_expression(void) case T___builtin_va_arg: return parse_va_arg(); case T___builtin_expect: case T___builtin_alloca: + case T___builtin_inf: + case T___builtin_inff: + case T___builtin_infl: case T___builtin_nan: - case T___builtin_nand: case T___builtin_nanf: + case T___builtin_nanl: case T___builtin_huge_val: case T___builtin_va_end: return parse_builtin_symbol(); case T___builtin_isgreater: @@ -7477,7 +7485,10 @@ static bool is_lvalue(const expression_t *expression) return true; default: - return false; + /* Claim it is an lvalue, if the type is invalid. There was a parse + * error before, which maybe prevented properly recognizing it as + * lvalue. */ + return !is_type_valid(skip_typeref(expression->base.type)); } } @@ -7647,7 +7658,7 @@ static void semantic_take_addr(unary_expression_t *expression) value->base.type = revert_automatic_type_conversion(value); type_t *orig_type = value->base.type; - if (!is_type_valid(orig_type)) + if (!is_type_valid(skip_typeref(orig_type))) return; set_address_taken(value, false); @@ -8709,13 +8720,11 @@ static asm_clobber_t *parse_asm_clobbers(void) */ static statement_t *parse_asm_statement(void) { - eat(T_asm); - - statement_t *statement = allocate_statement_zero(STATEMENT_ASM); - statement->base.source_position = token.source_position; - + statement_t *statement = allocate_statement_zero(STATEMENT_ASM); asm_statement_t *asm_statement = &statement->asms; + eat(T_asm); + if (token.type == T_volatile) { next_token(); asm_statement->is_volatile = true; @@ -8770,19 +8779,18 @@ end_error: */ static statement_t *parse_case_statement(void) { - eat(T_case); - statement_t *const statement = allocate_statement_zero(STATEMENT_CASE_LABEL); source_position_t *const pos = &statement->base.source_position; - *pos = token.source_position; + eat(T_case); + expression_t *const expression = parse_expression(); statement->case_label.expression = expression; if (!is_constant_expression(expression)) { /* This check does not prevent the error message in all cases of an * prior error while parsing the expression. At least it catches the * common case of a mistyped enum entry. */ - if (is_type_valid(expression->base.type)) { + if (is_type_valid(skip_typeref(expression->base.type))) { errorf(pos, "case label does not reduce to an integer constant"); } statement->case_label.is_bad = true; @@ -8801,7 +8809,7 @@ static statement_t *parse_case_statement(void) /* This check does not prevent the error message in all cases of an * prior error while parsing the expression. At least it catches the * common case of a mistyped enum entry. */ - if (is_type_valid(end_range->base.type)) { + if (is_type_valid(skip_typeref(end_range->base.type))) { errorf(pos, "case range does not reduce to an integer constant"); } statement->case_label.is_bad = true; @@ -8866,10 +8874,9 @@ end_error: */ static statement_t *parse_default_statement(void) { - eat(T_default); - statement_t *statement = allocate_statement_zero(STATEMENT_CASE_LABEL); - statement->base.source_position = token.source_position; + + eat(T_default); PUSH_PARENT(statement); @@ -8914,14 +8921,13 @@ end_error: static statement_t *parse_label_statement(void) { assert(token.type == T_IDENTIFIER); - symbol_t *symbol = token.v.symbol; - next_token(); - - declaration_t *label = get_label(symbol); + symbol_t *symbol = token.v.symbol; + declaration_t *label = get_label(symbol); statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL); - statement->base.source_position = token.source_position; - statement->label.label = label; + statement->label.label = label; + + next_token(); PUSH_PARENT(statement); @@ -8977,19 +8983,23 @@ static statement_t *parse_label_statement(void) */ static statement_t *parse_if(void) { - eat(T_if); + statement_t *statement = allocate_statement_zero(STATEMENT_IF); - statement_t *statement = allocate_statement_zero(STATEMENT_IF); - statement->base.source_position = token.source_position; + eat(T_if); PUSH_PARENT(statement); + add_anchor_token('{'); + expect('('); add_anchor_token(')'); statement->ifs.condition = parse_expression(); rem_anchor_token(')'); expect(')'); +end_error: + rem_anchor_token('{'); + add_anchor_token(T_else); statement->ifs.true_statement = parse_statement(); rem_anchor_token(T_else); @@ -9001,9 +9011,6 @@ static statement_t *parse_if(void) POP_PARENT; return statement; -end_error: - POP_PARENT; - return create_invalid_statement(); } /** @@ -9051,10 +9058,9 @@ static void check_enum_cases(const switch_statement_t *statement) { */ static statement_t *parse_switch(void) { - eat(T_switch); + statement_t *statement = allocate_statement_zero(STATEMENT_SWITCH); - statement_t *statement = allocate_statement_zero(STATEMENT_SWITCH); - statement->base.source_position = token.source_position; + eat(T_switch); PUSH_PARENT(statement); @@ -9115,10 +9121,9 @@ static statement_t *parse_loop_body(statement_t *const loop) */ static statement_t *parse_while(void) { - eat(T_while); + statement_t *statement = allocate_statement_zero(STATEMENT_WHILE); - statement_t *statement = allocate_statement_zero(STATEMENT_WHILE); - statement->base.source_position = token.source_position; + eat(T_while); PUSH_PARENT(statement); @@ -9142,10 +9147,9 @@ end_error: */ static statement_t *parse_do(void) { - eat(T_do); - statement_t *statement = allocate_statement_zero(STATEMENT_DO_WHILE); - statement->base.source_position = token.source_position; + + eat(T_do); PUSH_PARENT(statement) @@ -9173,10 +9177,9 @@ end_error: */ static statement_t *parse_for(void) { - eat(T_for); + statement_t *statement = allocate_statement_zero(STATEMENT_FOR); - statement_t *statement = allocate_statement_zero(STATEMENT_FOR); - statement->base.source_position = token.source_position; + eat(T_for); PUSH_PARENT(statement); @@ -9244,10 +9247,9 @@ end_error: */ static statement_t *parse_goto(void) { - source_position_t source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_GOTO); eat(T_goto); - statement_t *statement; if (GNU_MODE && token.type == '*') { next_token(); expression_t *expression = parse_expression(); @@ -9258,17 +9260,16 @@ static statement_t *parse_goto(void) if (type != type_error_type) { if (!is_type_pointer(type) && !is_type_integer(type)) { - errorf(&source_position, "cannot convert to a pointer type"); + errorf(&expression->base.source_position, + "cannot convert to a pointer type"); } else if (type != type_void_ptr) { - warningf(&source_position, + warningf(&expression->base.source_position, "type of computed goto expression should be 'void*' not '%T'", type); } expression = create_implicit_cast(expression, type_void_ptr); } - statement = allocate_statement_zero(STATEMENT_GOTO); - statement->base.source_position = source_position; - statement->gotos.expression = expression; + statement->gotos.expression = expression; } else { if (token.type != T_IDENTIFIER) { if (GNU_MODE) @@ -9281,9 +9282,7 @@ static statement_t *parse_goto(void) symbol_t *symbol = token.v.symbol; next_token(); - statement = allocate_statement_zero(STATEMENT_GOTO); - statement->base.source_position = source_position; - statement->gotos.label = get_label(symbol); + statement->gotos.label = get_label(symbol); if (statement->gotos.label->parent_scope->depth < current_function->scope.depth) { statement->gotos.outer_fkt_jmp = true; @@ -9315,7 +9314,6 @@ static statement_t *parse_continue(void) } statement_t *statement = allocate_statement_zero(STATEMENT_CONTINUE); - statement->base.source_position = token.source_position; eat(T_continue); expect(';'); @@ -9334,7 +9332,6 @@ static statement_t *parse_break(void) } statement_t *statement = allocate_statement_zero(STATEMENT_BREAK); - statement->base.source_position = token.source_position; eat(T_break); expect(';'); @@ -9353,7 +9350,6 @@ static statement_t *parse_leave_statement(void) } statement_t *statement = allocate_statement_zero(STATEMENT_LEAVE); - statement->base.source_position = token.source_position; eat(T___leave); expect(';'); @@ -9426,11 +9422,10 @@ declaration_t *expr_is_variable(const expression_t *expression) */ static statement_t *parse_return(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_RETURN); - statement->base.source_position = token.source_position; - eat(T_return); + statement_t *statement = allocate_statement_zero(STATEMENT_RETURN); + expression_t *return_value = NULL; if (token.type != ';') { return_value = parse_expression(); @@ -9484,8 +9479,6 @@ static statement_t *parse_declaration_statement(void) { statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION); - statement->base.source_position = token.source_position; - declaration_t *before = last_declaration; if (GNU_MODE) parse_external_declaration(); @@ -9509,7 +9502,6 @@ static statement_t *parse_expression_statement(void) { statement_t *statement = allocate_statement_zero(STATEMENT_EXPRESSION); - statement->base.source_position = token.source_position; expression_t *const expr = parse_expression(); statement->expression.expression = expr; @@ -9526,7 +9518,6 @@ end_error: static statement_t *parse_ms_try_statment(void) { statement_t *statement = allocate_statement_zero(STATEMENT_MS_TRY); - statement->base.source_position = token.source_position; eat(T___try); PUSH_PARENT(statement); @@ -9579,7 +9570,6 @@ static statement_t *parse_empty_statement(void) static statement_t *parse_local_label_declaration(void) { statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION); - statement->base.source_position = token.source_position; eat(T___label__); @@ -9730,9 +9720,12 @@ expression_statment: case T___builtin_islessequal: case T___builtin_islessgreater: case T___builtin_isunordered: + case T___builtin_inf: + case T___builtin_inff: + case T___builtin_infl: case T___builtin_nan: - case T___builtin_nand: case T___builtin_nanf: + case T___builtin_nanl: case T___builtin_offsetof: case T___builtin_prefetch: case T___builtin_va_arg: @@ -9786,7 +9779,6 @@ static statement_t *parse_statement(void) static statement_t *parse_compound_statement(bool inside_expression_statement) { statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND); - statement->base.source_position = token.source_position; PUSH_PARENT(statement); @@ -9896,7 +9888,7 @@ static void check_unused_globals(void) if (!warning.unused_function && !warning.unused_variable) return; - for (const declaration_t *decl = global_scope->declarations; decl != NULL; decl = decl->next) { + for (const declaration_t *decl = file_scope->declarations; decl != NULL; decl = decl->next) { if (decl->used || decl->modifiers & DM_UNUSED || decl->modifiers & DM_USED || @@ -9924,14 +9916,14 @@ static void check_unused_globals(void) static void parse_global_asm(void) { + statement_t *statement = allocate_statement_zero(STATEMENT_ASM); + eat(T_asm); expect('('); - statement_t *statement = allocate_statement_zero(STATEMENT_ASM); - statement->base.source_position = token.source_position; - statement->asms.asm_text = parse_string_literals(); - statement->base.next = unit->global_asm; - unit->global_asm = statement; + statement->asms.asm_text = parse_string_literals(); + statement->base.next = unit->global_asm; + unit->global_asm = statement; expect(')'); expect(';'); @@ -9981,13 +9973,16 @@ static void parse_translation_unit(void) break; case T_EOF: + rem_anchor_token(T_EOF); return; case ';': - /* TODO error in strict mode */ - warningf(HERE, "stray ';' outside of function"); - next_token(); - break; + if (!strict_mode) { + warningf(HERE, "stray ';' outside of function"); + next_token(); + break; + } + /* FALLTHROUGH */ default: errorf(HERE, "stray %K outside of function", &token); @@ -9997,8 +9992,6 @@ static void parse_translation_unit(void) break; } } - - rem_anchor_token(T_EOF); } /** @@ -10021,8 +10014,8 @@ void start_parsing(void) assert(unit == NULL); unit = allocate_ast_zero(sizeof(unit[0])); - assert(global_scope == NULL); - global_scope = &unit->scope; + assert(file_scope == NULL); + file_scope = &unit->scope; assert(scope == NULL); scope_push(&unit->scope); @@ -10037,9 +10030,9 @@ translation_unit_t *finish_parsing(void) scope = NULL; last_declaration = NULL; - assert(global_scope == &unit->scope); + assert(file_scope == &unit->scope); check_unused_globals(); - global_scope = NULL; + file_scope = NULL; DEL_ARR_F(environment_stack); DEL_ARR_F(label_stack);