X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=225f3b494f4af3566b37925b9f20d50857dbd4c5;hb=c91a949920b54a81853baa202dc1373194825def;hp=68a7d17d9619f6a9c03db6c59c32d75556b3fc7b;hpb=aa371747ce0d09b35d53a2a8d74861b44df4bd45;p=cparser diff --git a/parser.c b/parser.c index 68a7d17..225f3b4 100644 --- a/parser.c +++ b/parser.c @@ -100,34 +100,34 @@ typedef struct parse_initializer_env_t { typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition); /** The current token. */ -static token_t token; +static token_t token; /** The lookahead ring-buffer. */ -static token_t lookahead_buffer[MAX_LOOKAHEAD]; +static token_t lookahead_buffer[MAX_LOOKAHEAD]; /** Position of the next token in the lookahead buffer. */ -static int lookahead_bufpos; -static stack_entry_t *environment_stack = NULL; -static stack_entry_t *label_stack = NULL; -static scope_t *file_scope = NULL; -static scope_t *current_scope = NULL; +static int lookahead_bufpos; +static stack_entry_t *environment_stack = NULL; +static stack_entry_t *label_stack = NULL; +static scope_t *file_scope = NULL; +static scope_t *current_scope = NULL; /** Point to the current function declaration if inside a function. */ -static function_t *current_function = NULL; -static entity_t *current_init_decl = NULL; -static switch_statement_t *current_switch = NULL; -static statement_t *current_loop = NULL; -static statement_t *current_parent = NULL; -static ms_try_statement_t *current_try = NULL; -static linkage_kind_t current_linkage = LINKAGE_INVALID; -static goto_statement_t *goto_first = NULL; -static goto_statement_t *goto_last = NULL; -static label_statement_t *label_first = NULL; -static label_statement_t *label_last = NULL; +static function_t *current_function = NULL; +static entity_t *current_init_decl = NULL; +static switch_statement_t *current_switch = NULL; +static statement_t *current_loop = NULL; +static statement_t *current_parent = NULL; +static ms_try_statement_t *current_try = NULL; +static linkage_kind_t current_linkage = LINKAGE_INVALID; +static goto_statement_t *goto_first = NULL; +static goto_statement_t **goto_anchor = NULL; +static label_statement_t *label_first = NULL; +static label_statement_t **label_anchor = NULL; /** current translation unit. */ -static translation_unit_t *unit = NULL; +static translation_unit_t *unit = NULL; /** true if we are in a type property context (evaluation only for type. */ -static bool in_type_prop = false; +static bool in_type_prop = false; /** true in we are in a __extension__ context. */ -static bool in_gcc_extension = false; -static struct obstack temp_obst; +static bool in_gcc_extension = false; +static struct obstack temp_obst; #define PUSH_PARENT(stmt) \ @@ -3629,7 +3629,6 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) break; case T_long: - next_token(); if (type_specifiers & SPECIFIER_LONG_LONG) { errorf(HERE, "multiple type specifiers given"); } else if (type_specifiers & SPECIFIER_LONG) { @@ -3637,6 +3636,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) } else { type_specifiers |= SPECIFIER_LONG; } + next_token(); break; case T_struct: { @@ -5272,8 +5272,6 @@ static void check_labels(void) "label '%Y' used but not defined", label->base.symbol); } } - goto_first = NULL; - goto_last = NULL; if (warning.unused_label) { for (const label_statement_t *label_statement = label_first; @@ -5288,7 +5286,6 @@ static void check_labels(void) } } } - label_first = label_last = NULL; } static void warn_unused_decl(entity_t *entity, entity_t *end, @@ -5969,7 +5966,12 @@ static void parse_external_declaration(void) current_function = function; current_parent = NULL; - statement_t *const body = parse_compound_statement(false); + goto_first = NULL; + goto_anchor = &goto_first; + label_first = NULL; + label_anchor = &label_first; + + statement_t *const body = parse_compound_statement(false); function->statement = body; first_err = true; check_labels(); @@ -6312,10 +6314,10 @@ static expression_t *parse_character_constant(void) cnst->conste.v.character = token.v.string; if (cnst->conste.v.character.size != 1) { - if (warning.multichar && GNU_MODE) { + if (!GNU_MODE) { + errorf(HERE, "more than 1 character in character constant"); + } else if (warning.multichar) { warningf(HERE, "multi-character character constant"); - } else { - errorf(HERE, "more than 1 characters in character constant"); } } next_token(); @@ -6333,10 +6335,10 @@ static expression_t *parse_wide_character_constant(void) cnst->conste.v.wide_character = token.v.wide_string; if (cnst->conste.v.wide_character.size != 1) { - if (warning.multichar && GNU_MODE) { + if (!GNU_MODE) { + errorf(HERE, "more than 1 character in character constant"); + } else if (warning.multichar) { warningf(HERE, "multi-character character constant"); - } else { - errorf(HERE, "more than 1 characters in character constant"); } } next_token(); @@ -7440,8 +7442,6 @@ static expression_t *parse_typeprop(expression_kind_t const kind) eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__); - char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; - /* we only refer to a type property, mark this case */ bool old = in_type_prop; in_type_prop = true; @@ -7479,6 +7479,7 @@ typeprop_expression: type->kind == TYPE_BITFIELD ? "bitfield" : NULL; if (wrong_type != NULL) { + char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; errorf(&tp_expression->base.source_position, "operand of %s expression must not be of %s type '%T'", what, wrong_type, orig_type); @@ -7746,6 +7747,48 @@ static bool same_compound_type(const type_t *type1, const type_t *type2) type1->compound.compound == type2->compound.compound; } +static expression_t const *get_reference_address(expression_t const *expr) +{ + bool regular_take_address = true; + for (;;) { + if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { + expr = expr->unary.value; + } else { + regular_take_address = false; + } + + if (expr->kind != EXPR_UNARY_DEREFERENCE) + break; + + expr = expr->unary.value; + } + + if (expr->kind != EXPR_REFERENCE) + return NULL; + + /* special case for functions which are automatically converted to a + * pointer to function without an extra TAKE_ADDRESS operation */ + if (!regular_take_address && + expr->reference.entity->kind != ENTITY_FUNCTION) { + return NULL; + } + + return expr; +} + +static void warn_reference_address_as_bool(expression_t const* expr) +{ + if (!warning.address) + return; + + expr = get_reference_address(expr); + if (expr != NULL) { + warningf(&expr->base.source_position, + "the address of '%Y' will always evaluate as 'true'", + expr->reference.entity->base.symbol); + } +} + /** * Parse a conditional expression, ie. 'expression ? ... : ...'. * @@ -7758,6 +7801,8 @@ static expression_t *parse_conditional_expression(expression_t *expression) conditional_expression_t *conditional = &result->conditional; conditional->condition = expression; + warn_reference_address_as_bool(expression); + eat('?'); add_anchor_token(':'); @@ -8096,45 +8141,6 @@ static void semantic_unexpr_plus(unary_expression_t *expression) "traditional C rejects the unary plus operator"); } -static expression_t const *get_reference_address(expression_t const *expr) -{ - bool regular_take_address = true; - for (;;) { - if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { - expr = expr->unary.value; - } else { - regular_take_address = false; - } - - if (expr->kind != EXPR_UNARY_DEREFERENCE) - break; - - expr = expr->unary.value; - } - - /* special case for functions which are automatically converted to a - * pointer to function without an extra TAKE_ADDRESS operation */ - if (!regular_take_address && expr->kind == EXPR_REFERENCE - && expr->reference.entity->kind == ENTITY_FUNCTION) { - return expr; - } - - return NULL; -} - -static void warn_function_address_as_bool(expression_t const* expr) -{ - if (!warning.address) - return; - - expr = get_reference_address(expr); - if (expr != NULL) { - warningf(&expr->base.source_position, - "the address of '%Y' will always evaluate as 'true'", - expr->reference.entity->base.symbol); - } -} - static void semantic_not(unary_expression_t *expression) { type_t *const orig_type = expression->value->base.type; @@ -8144,7 +8150,7 @@ static void semantic_not(unary_expression_t *expression) "operand of ! must be of scalar type"); } - warn_function_address_as_bool(expression->value); + warn_reference_address_as_bool(expression->value); expression->base.type = c_mode & _CXX ? type_bool : type_int; } @@ -8221,11 +8227,8 @@ static void semantic_take_addr(unary_expression_t *expression) return; /* §6.5.3.2 */ - if (value->kind != EXPR_ARRAY_ACCESS - && value->kind != EXPR_UNARY_DEREFERENCE - && !is_lvalue(value)) { - errorf(&expression->base.source_position, - "'&' requires an lvalue"); + if (!is_lvalue(value)) { + errorf(&expression->base.source_position, "'&' requires an lvalue"); } if (type->kind == TYPE_BITFIELD) { errorf(&expression->base.source_position, @@ -8744,8 +8747,8 @@ static void semantic_logical_op(binary_expression_t *expression) type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_right = skip_typeref(orig_type_right); - warn_function_address_as_bool(left); - warn_function_address_as_bool(right); + warn_reference_address_as_bool(left); + warn_reference_address_as_bool(right); if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) { /* TODO: improve error message */ @@ -9129,8 +9132,8 @@ static void init_expression_parsers(void) */ static asm_argument_t *parse_asm_arguments(bool is_out) { - asm_argument_t *result = NULL; - asm_argument_t *last = NULL; + asm_argument_t *result = NULL; + asm_argument_t **anchor = &result; while (token.type == T_STRING_LITERAL || token.type == '[') { asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0])); @@ -9213,12 +9216,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out) set_address_taken(expression, true); - if (last != NULL) { - last->next = argument; - } else { - result = argument; - } - last = argument; + *anchor = argument; + anchor = &argument->next; if (token.type != ',') break; @@ -9510,12 +9509,8 @@ static statement_t *parse_label_statement(void) } /* remember the labels in a list for later checking */ - if (label_last == NULL) { - label_first = &statement->label; - } else { - label_last->next = &statement->label; - } - label_last = &statement->label; + *label_anchor = &statement->label; + label_anchor = &statement->label.next; POP_PARENT; return statement; @@ -9538,6 +9533,7 @@ static statement_t *parse_if(void) add_anchor_token(')'); expression_t *const expr = parse_expression(); statement->ifs.condition = expr; + warn_reference_address_as_bool(expr); mark_vars_read(expr, NULL); rem_anchor_token(')'); expect(')'); @@ -9678,6 +9674,7 @@ static statement_t *parse_while(void) add_anchor_token(')'); expression_t *const cond = parse_expression(); statement->whiles.condition = cond; + warn_reference_address_as_bool(cond); mark_vars_read(cond, NULL); rem_anchor_token(')'); expect(')'); @@ -9711,6 +9708,7 @@ static statement_t *parse_do(void) add_anchor_token(')'); expression_t *const cond = parse_expression(); statement->do_while.condition = cond; + warn_reference_address_as_bool(cond); mark_vars_read(cond, NULL); rem_anchor_token(')'); expect(')'); @@ -9763,6 +9761,7 @@ static statement_t *parse_for(void) add_anchor_token(';'); expression_t *const cond = parse_expression(); statement->fors.condition = cond; + warn_reference_address_as_bool(cond); mark_vars_read(cond, NULL); rem_anchor_token(';'); } @@ -9810,8 +9809,8 @@ static statement_t *parse_goto(void) expression_t *expression = parse_expression(); mark_vars_read(expression, NULL); - /* Argh: although documentation say the expression must be of type void *, - * gcc excepts anything that can be casted into void * without error */ + /* Argh: although documentation says the expression must be of type void*, + * gcc accepts anything that can be casted into void* without error */ type_t *type = expression->base.type; if (type != type_error_type) { @@ -9842,12 +9841,8 @@ static statement_t *parse_goto(void) } /* remember the goto's in a list for later checking */ - if (goto_last == NULL) { - goto_first = &statement->gotos; - } else { - goto_last->next = &statement->gotos; - } - goto_last = &statement->gotos; + *goto_anchor = &statement->gotos; + goto_anchor = &statement->gotos.next; expect(';');