X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=3fb68d89a9872d44feac0510e7ad825f61f16cf9;hb=99f5a3cd09e0d7d6127751fc9f6550b5dcbbbd33;hp=362082757eb1fd7cf95341a8c5fbb1565afbb462;hpb=9e3bfd2f0db0d19a6980b8698112d60039753de0;p=cparser diff --git a/parser.c b/parser.c index 3620827..3fb68d8 100644 --- a/parser.c +++ b/parser.c @@ -252,11 +252,8 @@ static void semantic_comparison(binary_expression_t *expression); case T_MINUSMINUS: \ case T_PLUSPLUS: \ case T_STRING_LITERAL: \ - case T_WIDE_CHARACTER_CONSTANT: \ - case T_WIDE_STRING_LITERAL: \ case T___FUNCDNAME__: \ case T___FUNCSIG__: \ - case T___FUNCTION__: \ case T___PRETTY_FUNCTION__: \ case T___alignof__: \ case T___builtin_classify_type: \ @@ -328,10 +325,8 @@ static size_t get_expression_struct_size(expression_kind_t kind) [EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t), [EXPR_LITERAL_FLOATINGPOINT] = sizeof(literal_expression_t), - [EXPR_LITERAL_CHARACTER] = sizeof(literal_expression_t), - [EXPR_LITERAL_WIDE_CHARACTER] = sizeof(literal_expression_t), + [EXPR_LITERAL_CHARACTER] = sizeof(string_literal_expression_t), [EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t), - [EXPR_WIDE_STRING_LITERAL] = sizeof(string_literal_expression_t), [EXPR_COMPOUND_LITERAL] = sizeof(compound_literal_expression_t), [EXPR_CALL] = sizeof(call_expression_t), [EXPR_UNARY_FIRST] = sizeof(unary_expression_t), @@ -375,7 +370,7 @@ static statement_t *allocate_statement_zero(statement_kind_t kind) res->base.kind = kind; res->base.parent = current_parent; - res->base.source_position = token.base.source_position; + res->base.source_position = *HERE; return res; } @@ -392,7 +387,7 @@ static expression_t *allocate_expression_zero(expression_kind_t kind) res->base.kind = kind; res->base.type = type_error_type; - res->base.source_position = token.base.source_position; + res->base.source_position = *HERE; return res; } @@ -432,8 +427,7 @@ static size_t get_initializer_size(initializer_kind_t kind) { static const size_t sizes[] = { [INITIALIZER_VALUE] = sizeof(initializer_value_t), - [INITIALIZER_STRING] = sizeof(initializer_string_t), - [INITIALIZER_WIDE_STRING] = sizeof(initializer_wide_string_t), + [INITIALIZER_STRING] = sizeof(initializer_value_t), [INITIALIZER_LIST] = sizeof(initializer_list_t), [INITIALIZER_DESIGNATOR] = sizeof(initializer_designator_t) }; @@ -487,10 +481,12 @@ static inline void next_token(void) #endif } +#define eat(token_kind) (assert(token.kind == (token_kind)), next_token()) + static inline bool next_if(token_kind_t const type) { if (token.kind == type) { - next_token(); + eat(type); return true; } else { return false; @@ -601,8 +597,6 @@ static void eat_block(void) next_if('}'); } -#define eat(token_kind) (assert(token.kind == (token_kind)), next_token()) - /** * Report a parse error because an expected token was not found. */ @@ -631,33 +625,33 @@ static void type_error_incompatible(const char *msg, msg, type1, type2); } -/** - * Expect the current token is the expected token. - * If not, generate an error and skip until the next anchor. - */ -static void expect(token_kind_t const expected) +static bool skip_till(token_kind_t const expected, char const *const context) { if (UNLIKELY(token.kind != expected)) { - parse_error_expected(NULL, expected, NULL); + parse_error_expected(context, expected, NULL); add_anchor_token(expected); eat_until_anchor(); rem_anchor_token(expected); if (token.kind != expected) - return; + return false; } - eat(expected); + return true; +} + +/** + * Expect the current token is the expected token. + * If not, generate an error and skip until the next anchor. + */ +static void expect(token_kind_t const expected) +{ + if (skip_till(expected, NULL)) + eat(expected); } static symbol_t *expect_identifier(char const *const context, source_position_t *const pos) { - if (token.kind != T_IDENTIFIER) { - parse_error_expected(context, T_IDENTIFIER, NULL); - add_anchor_token(T_IDENTIFIER); - eat_until_anchor(); - rem_anchor_token(T_IDENTIFIER); - if (token.kind != T_IDENTIFIER) - return NULL; - } + if (!skip_till(T_IDENTIFIER, context)) + return NULL; symbol_t *const sym = token.base.symbol; if (pos) *pos = *HERE; @@ -1037,27 +1031,64 @@ static expression_t *parse_assignment_expression(void) return parse_subexpression(PREC_ASSIGNMENT); } -static void warn_string_concat(const source_position_t *pos) +static void append_string(string_t const *const s) { - warningf(WARN_TRADITIONAL, pos, "traditional C rejects string constant concatenation"); + /* FIXME Using the ast_obstack is a hack. Using the symbol_obstack is not + * possible, because other tokens are grown there alongside. */ + obstack_grow(&ast_obstack, s->begin, s->size); } -static string_t parse_string_literals(void) +static string_t finish_string(void) { - assert(token.kind == T_STRING_LITERAL); - string_t result = token.string.string; + obstack_1grow(&ast_obstack, '\0'); + size_t const size = obstack_object_size(&ast_obstack) - 1; + char const *const string = obstack_finish(&ast_obstack); + return (string_t){ string, size }; +} - next_token(); +static string_t concat_string_literals(string_encoding_t *const out_enc) +{ + assert(token.kind == T_STRING_LITERAL); - while (token.kind == T_STRING_LITERAL) { - warn_string_concat(&token.base.source_position); - result = concat_strings(&result, &token.string.string); - next_token(); + string_t result; + string_encoding_t enc = token.string.encoding; + if (look_ahead(1)->kind == T_STRING_LITERAL) { + append_string(&token.string.string); + eat(T_STRING_LITERAL); + warningf(WARN_TRADITIONAL, HERE, "traditional C rejects string constant concatenation"); + do { + if (token.string.encoding != STRING_ENCODING_CHAR) { + enc = token.string.encoding; + } + append_string(&token.string.string); + eat(T_STRING_LITERAL); + } while (token.kind == T_STRING_LITERAL); + result = finish_string(); + } else { + result = token.string.string; + eat(T_STRING_LITERAL); } + *out_enc = enc; return result; } +static string_t parse_string_literals(char const *const context) +{ + if (!skip_till(T_STRING_LITERAL, context)) + return (string_t){ "", 0 }; + + string_encoding_t enc; + source_position_t const pos = *HERE; + string_t const res = concat_string_literals(&enc); + + if (enc != STRING_ENCODING_CHAR) { + errorf(&pos, "expected plain string literal, got wide string literal"); + } + + return res; +} + static attribute_t *allocate_attribute_zero(attribute_kind_t kind) { attribute_t *attribute = allocate_ast_zero(sizeof(*attribute)); @@ -1106,7 +1137,7 @@ static attribute_argument_t *parse_attribute_arguments(void) && (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) { argument->kind = ATTRIBUTE_ARGUMENT_SYMBOL; argument->v.symbol = token.base.symbol; - next_token(); + eat(T_IDENTIFIER); } else { /* must be an expression */ expression_t *expression = parse_assignment_expression(); @@ -1172,11 +1203,11 @@ static attribute_t *parse_attribute_gnu(void) attribute_t **anchor = &first; eat(T___attribute__); + add_anchor_token(')'); + add_anchor_token(','); expect('('); expect('('); - add_anchor_token(')'); - add_anchor_token(','); if (token.kind != ')') do { attribute_t *attribute = parse_attribute_gnu_single(); if (attribute) { @@ -1456,9 +1487,9 @@ unary: return; case EXPR_LITERAL_CASES: + case EXPR_LITERAL_CHARACTER: case EXPR_ERROR: case EXPR_STRING_LITERAL: - case EXPR_WIDE_STRING_LITERAL: case EXPR_COMPOUND_LITERAL: // TODO init? case EXPR_SIZEOF: case EXPR_CLASSIFY_TYPE: @@ -1486,8 +1517,8 @@ static designator_t *parse_designation(void) switch (token.kind) { case '[': designator = allocate_ast_zero(sizeof(designator[0])); - designator->source_position = token.base.source_position; - next_token(); + designator->source_position = *HERE; + eat('['); add_anchor_token(']'); designator->array_index = parse_constant_expression(); rem_anchor_token(']'); @@ -1495,8 +1526,8 @@ static designator_t *parse_designation(void) break; case '.': designator = allocate_ast_zero(sizeof(designator[0])); - designator->source_position = token.base.source_position; - next_token(); + designator->source_position = *HERE; + eat('.'); designator->symbol = expect_identifier("while parsing designator", NULL); if (!designator->symbol) return NULL; @@ -1512,31 +1543,6 @@ static designator_t *parse_designation(void) } } -static initializer_t *initializer_from_string(array_type_t *const type, - const string_t *const string) -{ - /* TODO: check len vs. size of array type */ - (void) type; - - initializer_t *initializer = allocate_initializer_zero(INITIALIZER_STRING); - initializer->string.string = *string; - - return initializer; -} - -static initializer_t *initializer_from_wide_string(array_type_t *const type, - const string_t *const string) -{ - /* TODO: check len vs. size of array type */ - (void) type; - - initializer_t *const initializer = - allocate_initializer_zero(INITIALIZER_WIDE_STRING); - initializer->wide_string.string = *string; - - return initializer; -} - /** * Build an initializer from a given expression. */ @@ -1545,39 +1551,32 @@ static initializer_t *initializer_from_expression(type_t *orig_type, { /* TODO check that expression is a constant expression */ - /* §6.7.8.14/15 char array may be initialized by string literals */ - type_t *type = skip_typeref(orig_type); - type_t *expr_type_orig = expression->base.type; - type_t *expr_type = skip_typeref(expr_type_orig); + type_t *const type = skip_typeref(orig_type); - if (is_type_array(type) && expr_type->kind == TYPE_POINTER) { + /* §6.7.8.14/15 char array may be initialized by string literals */ + if (expression->kind == EXPR_STRING_LITERAL && is_type_array(type)) { array_type_t *const array_type = &type->array; type_t *const element_type = skip_typeref(array_type->element_type); - - if (element_type->kind == TYPE_ATOMIC) { - atomic_type_kind_t akind = element_type->atomic.akind; - switch (expression->kind) { - case EXPR_STRING_LITERAL: - if (akind == ATOMIC_TYPE_CHAR - || akind == ATOMIC_TYPE_SCHAR - || akind == ATOMIC_TYPE_UCHAR) { - return initializer_from_string(array_type, - &expression->string_literal.value); - } - break; - - case EXPR_WIDE_STRING_LITERAL: { - type_t *bare_wchar_type = skip_typeref(type_wchar_t); - if (get_unqualified_type(element_type) == bare_wchar_type) { - return initializer_from_wide_string(array_type, - &expression->string_literal.value); - } - break; + switch (expression->string_literal.encoding) { + case STRING_ENCODING_CHAR: { + if (is_type_atomic(element_type, ATOMIC_TYPE_CHAR) || + is_type_atomic(element_type, ATOMIC_TYPE_SCHAR) || + is_type_atomic(element_type, ATOMIC_TYPE_UCHAR)) { + goto make_string_init; } + break; + } - default: - break; + case STRING_ENCODING_WIDE: { + type_t *bare_wchar_type = skip_typeref(type_wchar_t); + if (get_unqualified_type(element_type) == bare_wchar_type) { +make_string_init:; + initializer_t *const init = allocate_initializer_zero(INITIALIZER_STRING); + init->value.value = expression; + return init; } + break; + } } } @@ -1829,7 +1828,8 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, } } else { expression_t *array_index = designator->array_index; - assert(designator->array_index != NULL); + if (is_constant_expression(array_index) != EXPR_CLASS_CONSTANT) + return true; if (!is_type_array(type)) { if (is_type_valid(type)) { @@ -1973,7 +1973,7 @@ static initializer_t *parse_sub_initializer(type_path_t *path, } else if (token.kind == T_IDENTIFIER && look_ahead(1)->kind == ':') { /* GNU-style designator ("identifier: value") */ designator = allocate_ast_zero(sizeof(designator[0])); - designator->source_position = token.base.source_position; + designator->source_position = *HERE; designator->symbol = token.base.symbol; eat(T_IDENTIFIER); eat(':'); @@ -2056,9 +2056,7 @@ finish_designator: } /* handle { "string" } special case */ - if ((expression->kind == EXPR_STRING_LITERAL - || expression->kind == EXPR_WIDE_STRING_LITERAL) - && outer_type != NULL) { + if (expression->kind == EXPR_STRING_LITERAL && outer_type != NULL) { sub = initializer_from_expression(outer_type, expression); if (sub != NULL) { next_if(','); @@ -2207,13 +2205,11 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) size = max_index + 1; break; - case INITIALIZER_STRING: - size = result->string.string.size; - break; - - case INITIALIZER_WIDE_STRING: - size = result->wide_string.string.size; + case INITIALIZER_STRING: { + string_literal_expression_t const *const str = get_init_string(result); + size = get_string_len(str->encoding, &str->value) + 1; break; + } case INITIALIZER_DESIGNATOR: case INITIALIZER_VALUE: @@ -2267,7 +2263,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) /* the compound has a name, check if we have seen it already */ symbol = token.base.symbol; entity = get_tag(symbol, kind); - next_token(); + eat(T_IDENTIFIER); if (entity != NULL) { if (entity->base.parent_scope != current_scope && @@ -2324,7 +2320,7 @@ static void parse_enum_entries(type_t *const enum_type) if (token.kind == '}') { errorf(HERE, "empty enum not allowed"); - next_token(); + eat('}'); return; } @@ -2366,7 +2362,7 @@ static type_t *parse_enum_specifier(void) case T_IDENTIFIER: symbol = token.base.symbol; entity = get_tag(symbol, ENTITY_ENUM); - next_token(); + eat(T_IDENTIFIER); if (entity != NULL) { if (entity->base.parent_scope != current_scope && @@ -2438,8 +2434,8 @@ static type_t *parse_typeof(void) type_t *type; - expect('('); add_anchor_token(')'); + expect('('); expression_t *expression = NULL; @@ -2504,10 +2500,10 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute) { attribute_property_argument_t *const property = allocate_ast_zero(sizeof(*property)); - expect('('); - add_anchor_token(')'); add_anchor_token(','); + expect('('); + do { add_anchor_token('='); source_position_t pos; @@ -2584,10 +2580,9 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first) { eat(T__declspec); + add_anchor_token(')'); expect('('); if (token.kind != ')') { - add_anchor_token(')'); - attribute_t **anchor = &first; do { while (*anchor != NULL) @@ -2601,9 +2596,8 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first) *anchor = attribute; anchor = &attribute->next; } while (next_if(',')); - - rem_anchor_token(')'); } + rem_anchor_token(')'); expect(')'); return first; } @@ -2632,7 +2626,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) bool saw_error = false; memset(specifiers, 0, sizeof(*specifiers)); - specifiers->source_position = token.base.source_position; + specifiers->source_position = *HERE; while (true) { specifiers->attributes = parse_attributes(specifiers->attributes); @@ -2647,7 +2641,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) specifiers->storage_class = class; \ if (specifiers->thread_local) \ goto check_thread_storage_class; \ - next_token(); \ + eat(token); \ break; MATCH_STORAGE_CLASS(T_typedef, STORAGE_CLASS_TYPEDEF) @@ -2689,7 +2683,7 @@ wrong_thread_storage_class: #define MATCH_TYPE_QUALIFIER(token, qualifier) \ case token: \ qualifiers |= qualifier; \ - next_token(); \ + eat(token); \ break MATCH_TYPE_QUALIFIER(T_const, TYPE_QUALIFIER_CONST); @@ -2709,7 +2703,7 @@ wrong_thread_storage_class: } else { \ type_specifiers |= specifier; \ } \ - next_token(); \ + eat(token); \ break MATCH_SPECIFIER(T__Bool, SPECIFIER_BOOL, "_Bool"); @@ -2732,13 +2726,13 @@ wrong_thread_storage_class: MATCH_SPECIFIER(T_wchar_t, SPECIFIER_WCHAR_T, "wchar_t"); case T_inline: - next_token(); + eat(T_inline); specifiers->is_inline = true; break; #if 0 case T__forceinline: - next_token(); + eat(T__forceinline); specifiers->modifiers |= DM_FORCEINLINE; break; #endif @@ -2751,7 +2745,7 @@ wrong_thread_storage_class: } else { type_specifiers |= SPECIFIER_LONG; } - next_token(); + eat(T_long); break; #define CHECK_DOUBLE_TYPE() \ @@ -2779,7 +2773,7 @@ wrong_thread_storage_class: case T___builtin_va_list: CHECK_DOUBLE_TYPE(); type = duplicate_type(type_valist); - next_token(); + eat(T___builtin_va_list); break; case T_IDENTIFIER: { @@ -2800,7 +2794,7 @@ wrong_thread_storage_class: case '&': case '*': errorf(HERE, "discarding stray %K in declaration specifier", &token); - next_token(); + eat(T_IDENTIFIER); continue; default: @@ -2826,7 +2820,7 @@ wrong_thread_storage_class: type = allocate_type_zero(TYPE_TYPEDEF); type->typedeft.typedefe = &entity->typedefe; - next_token(); + eat(T_IDENTIFIER); saw_error = true; continue; } @@ -2836,7 +2830,7 @@ wrong_thread_storage_class: } } - next_token(); + eat(T_IDENTIFIER); type = typedef_type; break; } @@ -3007,7 +3001,8 @@ warn_about_long_long: } else { errorf(pos, "multiple datatypes in declaration"); } - goto end_error; + specifiers->type = type_error_type; + return; } } @@ -3036,10 +3031,6 @@ warn_about_long_long: if (specifiers->attributes != NULL) type = handle_type_attributes(specifiers->attributes, type); specifiers->type = type; - return; - -end_error: - specifiers->type = type_error_type; } static type_qualifiers_t parse_type_qualifiers(void) @@ -3074,7 +3065,7 @@ static void parse_identifier_list(scope_t *scope) do { entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.base.symbol, HERE); /* a K&R parameter has no type, yet */ - next_token(); + eat(T_IDENTIFIER); if (scope != NULL) append_entity(scope, entity); @@ -3141,8 +3132,8 @@ static bool has_parameters(void) */ static void parse_parameters(function_type_t *type, scope_t *scope) { - eat('('); add_anchor_token(')'); + eat('('); if (token.kind == T_IDENTIFIER && !is_typedef_symbol(token.base.symbol) && @@ -3159,7 +3150,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope) do { switch (token.kind) { case T_DOTDOTDOT: - next_token(); + eat(T_DOTDOTDOT); type->variadic = true; goto parameters_finished; @@ -3301,7 +3292,7 @@ static construct_type_t *parse_array_declarator(void) expression_t *size = NULL; if (token.kind == '*' && look_ahead(1)->kind == ']') { array->is_variable = true; - next_token(); + eat('*'); } else if (token.kind != ']') { size = parse_assignment_expression(); @@ -3401,9 +3392,9 @@ ptr_operator_end: ; errorf(HERE, "no identifier expected in typename"); } else { env->symbol = token.base.symbol; - env->source_position = token.base.source_position; + env->source_position = *HERE; } - next_token(); + eat(T_IDENTIFIER); break; case '(': { @@ -3428,7 +3419,7 @@ ptr_operator_end: ; case '[': case T___attribute__: /* FIXME __attribute__ might also introduce a parameter of a function declarator. */ /* Paranthesized declarator. */ - next_token(); + eat('('); add_anchor_token(')'); inner_types = parse_inner_declarator(env); if (inner_types != NULL) { @@ -4623,8 +4614,8 @@ static bool expression_returns(expression_t const *const expr) case EXPR_REFERENCE: case EXPR_ENUM_CONSTANT: case EXPR_LITERAL_CASES: + case EXPR_LITERAL_CHARACTER: case EXPR_STRING_LITERAL: - case EXPR_WIDE_STRING_LITERAL: case EXPR_COMPOUND_LITERAL: // TODO descend into initialisers case EXPR_LABEL_ADDRESS: case EXPR_CLASSIFY_TYPE: @@ -4709,7 +4700,6 @@ static bool initializer_returns(initializer_t const *const init) } case INITIALIZER_STRING: - case INITIALIZER_WIDE_STRING: case INITIALIZER_DESIGNATOR: // designators have no payload return true; } @@ -5474,8 +5464,7 @@ static expression_t *find_create_select(const source_position_t *pos, symbol_t *iter_symbol = iter->base.symbol; if (iter_symbol == NULL) { type_t *type = iter->declaration.type; - if (type->kind != TYPE_COMPOUND_STRUCT - && type->kind != TYPE_COMPOUND_UNION) + if (!is_type_compound(type)) continue; compound_t *sub_compound = type->compound.compound; @@ -5682,14 +5671,14 @@ struct expression_parser_function_t { static expression_parser_function_t expression_parsers[T_LAST_TOKEN]; -static type_t *get_string_type(void) +static type_t *get_string_type(string_encoding_t const enc) { - return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr; -} - -static type_t *get_wide_string_type(void) -{ - return is_warn_on(WARN_WRITE_STRINGS) ? type_const_wchar_t_ptr : type_wchar_t_ptr; + bool const warn = is_warn_on(WARN_WRITE_STRINGS); + switch (enc) { + case STRING_ENCODING_CHAR: return warn ? type_const_char_ptr : type_char_ptr; + case STRING_ENCODING_WIDE: return warn ? type_const_wchar_t_ptr : type_wchar_t_ptr; + } + panic("invalid string encoding"); } /** @@ -5697,31 +5686,10 @@ static type_t *get_wide_string_type(void) */ static expression_t *parse_string_literal(void) { - source_position_t begin = token.base.source_position; - string_t res = token.string.string; - bool is_wide = (token.kind == T_WIDE_STRING_LITERAL); - - next_token(); - while (token.kind == T_STRING_LITERAL - || token.kind == T_WIDE_STRING_LITERAL) { - warn_string_concat(&token.base.source_position); - res = concat_strings(&res, &token.string.string); - next_token(); - is_wide |= token.kind == T_WIDE_STRING_LITERAL; - } - - expression_t *literal; - if (is_wide) { - literal = allocate_expression_zero(EXPR_WIDE_STRING_LITERAL); - literal->base.type = get_wide_string_type(); - } else { - literal = allocate_expression_zero(EXPR_STRING_LITERAL); - literal->base.type = get_string_type(); - } - literal->base.source_position = begin; - literal->literal.value = res; - - return literal; + expression_t *const expr = allocate_expression_zero(EXPR_STRING_LITERAL); + expr->string_literal.value = concat_string_literals(&expr->string_literal.encoding); + expr->base.type = get_string_type(expr->string_literal.encoding); + return expr; } /** @@ -5734,7 +5702,7 @@ static expression_t *parse_boolean_literal(bool value) literal->literal.value.begin = value ? "true" : "false"; literal->literal.value.size = value ? 4 : 5; - next_token(); + eat(value ? T_true : T_false); return literal; } @@ -5775,8 +5743,7 @@ static void check_integer_suffix(void) } } if (*c != '\0') { - errorf(&token.base.source_position, - "invalid suffix '%S' on integer constant", suffix); + errorf(HERE, "invalid suffix '%S' on integer constant", suffix); } else if (not_traditional) { warn_traditional_suffix(); } @@ -5799,8 +5766,7 @@ static type_t *check_floatingpoint_suffix(void) type = type_long_double; } if (*c != '\0') { - errorf(&token.base.source_position, - "invalid suffix '%S' on floatingpoint constant", suffix); + errorf(HERE, "invalid suffix '%S' on floatingpoint constant", suffix); } else if (not_traditional) { warn_traditional_suffix(); } @@ -5851,39 +5817,33 @@ static expression_t *parse_number_literal(void) */ static expression_t *parse_character_constant(void) { - expression_t *literal = allocate_expression_zero(EXPR_LITERAL_CHARACTER); - literal->base.type = c_mode & _CXX ? type_char : type_int; - literal->literal.value = token.string.string; + expression_t *const literal = allocate_expression_zero(EXPR_LITERAL_CHARACTER); + literal->string_literal.encoding = token.string.encoding; + literal->string_literal.value = token.string.string; + + size_t const size = get_string_len(token.string.encoding, &token.string.string); + switch (token.string.encoding) { + case STRING_ENCODING_CHAR: + literal->base.type = c_mode & _CXX ? type_char : type_int; + if (size > 1) { + if (!GNU_MODE && !(c_mode & _C99)) { + errorf(HERE, "more than 1 character in character constant"); + } else { + literal->base.type = type_int; + warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); + } + } + break; - size_t len = literal->literal.value.size; - if (len > 1) { - if (!GNU_MODE && !(c_mode & _C99)) { - errorf(HERE, "more than 1 character in character constant"); - } else { - literal->base.type = type_int; + case STRING_ENCODING_WIDE: + literal->base.type = type_int; + if (size > 1) { warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); } + break; } - next_token(); - return literal; -} - -/** - * Parse a wide character constant. - */ -static expression_t *parse_wide_character_constant(void) -{ - expression_t *literal = allocate_expression_zero(EXPR_LITERAL_WIDE_CHARACTER); - literal->base.type = type_int; - literal->literal.value = token.string.string; - - size_t len = wstrlen(&literal->literal.value); - if (len > 1) { - warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); - } - - next_token(); + eat(T_CHARACTER_CONSTANT); return literal; } @@ -5972,13 +5932,9 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) } case EXPR_STRING_LITERAL: { - size_t size = expression->string_literal.value.size; - return make_array_type(type_char, size, TYPE_QUALIFIER_NONE); - } - - case EXPR_WIDE_STRING_LITERAL: { - size_t size = wstrlen(&expression->string_literal.value); - return make_array_type(type_wchar_t, size, TYPE_QUALIFIER_NONE); + size_t const size = get_string_len(expression->string_literal.encoding, &expression->string_literal.value) + 1; + type_t *const elem = get_unqualified_type(expression->base.type->pointer.points_to); + return make_array_type(elem, size, TYPE_QUALIFIER_NONE); } case EXPR_COMPOUND_LITERAL: @@ -6071,7 +6027,7 @@ static entity_t *parse_qualified_identifier(void) static expression_t *parse_reference(void) { - source_position_t const pos = token.base.source_position; + source_position_t const pos = *HERE; entity_t *const entity = parse_qualified_identifier(); type_t *orig_type; @@ -6274,68 +6230,21 @@ static expression_t *parse_parenthesized_expression(void) return result; } -static expression_t *parse_function_keyword(void) +static expression_t *parse_function_keyword(funcname_kind_t const kind) { - /* TODO */ - if (current_function == NULL) { - errorf(HERE, "'__func__' used outside of a function"); + errorf(HERE, "'%K' used outside of a function", &token); } expression_t *expression = allocate_expression_zero(EXPR_FUNCNAME); expression->base.type = type_char_ptr; - expression->funcname.kind = FUNCNAME_FUNCTION; + expression->funcname.kind = kind; next_token(); return expression; } -static expression_t *parse_pretty_function_keyword(void) -{ - if (current_function == NULL) { - errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function"); - } - - expression_t *expression = allocate_expression_zero(EXPR_FUNCNAME); - expression->base.type = type_char_ptr; - expression->funcname.kind = FUNCNAME_PRETTY_FUNCTION; - - eat(T___PRETTY_FUNCTION__); - - return expression; -} - -static expression_t *parse_funcsig_keyword(void) -{ - if (current_function == NULL) { - errorf(HERE, "'__FUNCSIG__' used outside of a function"); - } - - expression_t *expression = allocate_expression_zero(EXPR_FUNCNAME); - expression->base.type = type_char_ptr; - expression->funcname.kind = FUNCNAME_FUNCSIG; - - eat(T___FUNCSIG__); - - return expression; -} - -static expression_t *parse_funcdname_keyword(void) -{ - if (current_function == NULL) { - errorf(HERE, "'__FUNCDNAME__' used outside of a function"); - } - - expression_t *expression = allocate_expression_zero(EXPR_FUNCNAME); - expression->base.type = type_char_ptr; - expression->funcname.kind = FUNCNAME_FUNCDNAME; - - eat(T___FUNCDNAME__); - - return expression; -} - static designator_t *parse_designator(void) { designator_t *const result = allocate_ast_zero(sizeof(result[0])); @@ -6386,9 +6295,9 @@ static expression_t *parse_offsetof(void) eat(T___builtin_offsetof); - expect('('); add_anchor_token(')'); add_anchor_token(','); + expect('('); type_t *type = parse_typename(); rem_anchor_token(','); expect(','); @@ -6415,8 +6324,25 @@ static expression_t *parse_offsetof(void) return expression; } +static bool is_last_parameter(expression_t *const param) +{ + if (param->kind == EXPR_REFERENCE) { + entity_t *const entity = param->reference.entity; + if (entity->kind == ENTITY_PARAMETER && + !entity->base.next && + entity->base.parent_scope == ¤t_function->parameters) { + return true; + } + } + + if (!is_type_valid(skip_typeref(param->base.type))) + return true; + + return false; +} + /** - * Parses a _builtin_va_start() expression. + * Parses a __builtin_va_start() expression. */ static expression_t *parse_va_start(void) { @@ -6424,9 +6350,9 @@ static expression_t *parse_va_start(void) eat(T___builtin_va_start); - expect('('); add_anchor_token(')'); add_anchor_token(','); + expect('('); expression->va_starte.ap = parse_assignment_expression(); rem_anchor_token(','); expect(','); @@ -6439,16 +6365,8 @@ static expression_t *parse_va_start(void) errorf(&expression->base.source_position, "'va_start' used outside of function"); } else if (!current_function->base.type->function.variadic) { errorf(&expression->base.source_position, "'va_start' used in non-variadic function"); - } else if (param->kind == EXPR_REFERENCE) { - entity_t *const entity = param->reference.entity; - if (entity->base.parent_scope != ¤t_function->parameters || - entity->base.next != NULL || - entity->kind != ENTITY_PARAMETER) { - errorf(¶m->base.source_position, - "second argument of 'va_start' must be last parameter of the current function"); - } - } else { - expression = create_error_expression(); + } else if (!is_last_parameter(param)) { + errorf(¶m->base.source_position, "second argument of 'va_start' must be last parameter of the current function"); } return expression; @@ -6463,9 +6381,9 @@ static expression_t *parse_va_arg(void) eat(T___builtin_va_arg); - expect('('); add_anchor_token(')'); add_anchor_token(','); + expect('('); call_argument_t ap; ap.expression = parse_assignment_expression(); expression->va_arge.ap = ap.expression; @@ -6489,9 +6407,9 @@ static expression_t *parse_va_copy(void) eat(T___builtin_va_copy); - expect('('); add_anchor_token(')'); add_anchor_token(','); + expect('('); expression_t *dst = parse_assignment_expression(); assign_error_t error = semantic_assign(type_valist, dst); report_assign_error(error, type_valist, dst, "call argument 1", @@ -6520,8 +6438,8 @@ static expression_t *parse_builtin_constant(void) eat(T___builtin_constant_p); - expect('('); add_anchor_token(')'); + expect('('); expression->builtin_constant.value = parse_assignment_expression(); rem_anchor_token(')'); expect(')'); @@ -6539,9 +6457,9 @@ static expression_t *parse_builtin_types_compatible(void) eat(T___builtin_types_compatible_p); - expect('('); add_anchor_token(')'); add_anchor_token(','); + expect('('); expression->builtin_types_compatible.left = parse_typename(); rem_anchor_token(','); expect(','); @@ -6558,36 +6476,22 @@ static expression_t *parse_builtin_types_compatible(void) */ static expression_t *parse_compare_builtin(void) { - expression_t *expression; - + expression_kind_t kind; switch (token.kind) { - case T___builtin_isgreater: - expression = allocate_expression_zero(EXPR_BINARY_ISGREATER); - break; - case T___builtin_isgreaterequal: - expression = allocate_expression_zero(EXPR_BINARY_ISGREATEREQUAL); - break; - case T___builtin_isless: - expression = allocate_expression_zero(EXPR_BINARY_ISLESS); - break; - case T___builtin_islessequal: - expression = allocate_expression_zero(EXPR_BINARY_ISLESSEQUAL); - break; - case T___builtin_islessgreater: - expression = allocate_expression_zero(EXPR_BINARY_ISLESSGREATER); - break; - case T___builtin_isunordered: - expression = allocate_expression_zero(EXPR_BINARY_ISUNORDERED); - break; - default: - internal_errorf(HERE, "invalid compare builtin found"); - } - expression->base.source_position = *HERE; + case T___builtin_isgreater: kind = EXPR_BINARY_ISGREATER; break; + case T___builtin_isgreaterequal: kind = EXPR_BINARY_ISGREATEREQUAL; break; + case T___builtin_isless: kind = EXPR_BINARY_ISLESS; break; + case T___builtin_islessequal: kind = EXPR_BINARY_ISLESSEQUAL; break; + case T___builtin_islessgreater: kind = EXPR_BINARY_ISLESSGREATER; break; + case T___builtin_isunordered: kind = EXPR_BINARY_ISUNORDERED; break; + default: internal_errorf(HERE, "invalid compare builtin found"); + } + expression_t *const expression = allocate_expression_zero(kind); next_token(); - expect('('); add_anchor_token(')'); add_anchor_token(','); + expect('('); expression->binary.left = parse_assignment_expression(); rem_anchor_token(','); expect(','); @@ -6621,8 +6525,8 @@ static expression_t *parse_assume(void) eat(T__assume); - expect('('); add_anchor_token(')'); + expect('('); expression->unary.value = parse_assignment_expression(); rem_anchor_token(')'); expect(')'); @@ -6634,12 +6538,15 @@ static expression_t *parse_assume(void) /** * Return the label for the current symbol or create a new one. */ -static label_t *get_label(void) +static label_t *get_label(char const *const context) { - assert(token.kind == T_IDENTIFIER); assert(current_function != NULL); - entity_t *label = get_entity(token.base.symbol, NAMESPACE_LABEL); + symbol_t *const sym = expect_identifier(context, NULL); + if (!sym) + return NULL; + + entity_t *label = get_entity(sym, NAMESPACE_LABEL); /* If we find a local label, we already created the declaration. */ if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) { if (label->base.parent_scope != current_scope) { @@ -6649,11 +6556,10 @@ static label_t *get_label(void) } else if (label == NULL || label->base.parent_scope != ¤t_function->parameters) { /* There is no matching label in the same function, so create a new one. */ source_position_t const nowhere = { NULL, 0, 0, false }; - label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.base.symbol, &nowhere); + label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym, &nowhere); label_push(label); } - eat(T_IDENTIFIER); return &label->label; } @@ -6662,14 +6568,13 @@ static label_t *get_label(void) */ static expression_t *parse_label_address(void) { - source_position_t source_position = token.base.source_position; + source_position_t const source_position = *HERE; eat(T_ANDAND); - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing label address", T_IDENTIFIER, NULL); + + label_t *const label = get_label("while parsing label address"); + if (!label) return create_error_expression(); - } - label_t *const label = get_label(); label->used = true; label->address_taken = true; @@ -6724,14 +6629,11 @@ static expression_t *parse_primary_expression(void) case T_INTEGER: case T_FLOATINGPOINT: return parse_number_literal(); case T_CHARACTER_CONSTANT: return parse_character_constant(); - case T_WIDE_CHARACTER_CONSTANT: return parse_wide_character_constant(); - case T_STRING_LITERAL: - case T_WIDE_STRING_LITERAL: return parse_string_literal(); - case T___FUNCTION__: - case T___func__: return parse_function_keyword(); - case T___PRETTY_FUNCTION__: return parse_pretty_function_keyword(); - case T___FUNCSIG__: return parse_funcsig_keyword(); - case T___FUNCDNAME__: return parse_funcdname_keyword(); + case T_STRING_LITERAL: return parse_string_literal(); + case T___func__: return parse_function_keyword(FUNCNAME_FUNCTION); + case T___PRETTY_FUNCTION__: return parse_function_keyword(FUNCNAME_PRETTY_FUNCTION); + case T___FUNCSIG__: return parse_function_keyword(FUNCNAME_FUNCSIG); + case T___FUNCDNAME__: return parse_function_keyword(FUNCNAME_FUNCDNAME); case T___builtin_offsetof: return parse_offsetof(); case T___builtin_va_start: return parse_va_start(); case T___builtin_va_arg: return parse_va_arg(); @@ -6851,7 +6753,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind) expression_t *expression; if (token.kind == '(' && is_declaration_specifier(look_ahead(1))) { source_position_t const pos = *HERE; - next_token(); + eat('('); add_anchor_token(')'); orig_type = parse_typename(); rem_anchor_token(')'); @@ -6948,9 +6850,7 @@ static expression_t *parse_select_expression(expression_t *addr) type_left = type; } - if (type_left->kind != TYPE_COMPOUND_STRUCT && - type_left->kind != TYPE_COMPOUND_UNION) { - + if (!is_type_compound(type_left)) { if (is_type_valid(type_left) && !saw_error) { errorf(&pos, "request for member '%Y' in something not a struct or union, but '%T'", @@ -7403,8 +7303,8 @@ static expression_t *parse_builtin_classify_type(void) eat(T___builtin_classify_type); - expect('('); add_anchor_token(')'); + expect('('); expression_t *expression = parse_expression(); rem_anchor_token(')'); expect(')'); @@ -8024,8 +7924,7 @@ static void warn_string_literal_address(expression_t const* expr) expr = expr->unary.value; } - if (expr->kind == EXPR_STRING_LITERAL - || expr->kind == EXPR_WIDE_STRING_LITERAL) { + if (expr->kind == EXPR_STRING_LITERAL) { source_position_t const *const pos = &expr->base.source_position; warningf(WARN_ADDRESS, pos, "comparison with string literal results in unspecified behaviour"); } @@ -8363,11 +8262,9 @@ static bool expression_has_effect(const expression_t *const expr) case EXPR_LITERAL_MS_NOOP: return true; case EXPR_LITERAL_BOOLEAN: case EXPR_LITERAL_CHARACTER: - case EXPR_LITERAL_WIDE_CHARACTER: case EXPR_LITERAL_INTEGER: case EXPR_LITERAL_FLOATINGPOINT: case EXPR_STRING_LITERAL: return false; - case EXPR_WIDE_STRING_LITERAL: return false; case EXPR_CALL: { const call_expression_t *const call = &expr->call; @@ -8585,10 +8482,7 @@ static void register_expression_parser(parse_expression_function parser, { expression_parser_function_t *entry = &expression_parsers[token_kind]; - if (entry->parser != NULL) { - diagnosticf("for token '%k'\n", (token_kind_t)token_kind); - panic("trying to register multiple expression parsers for a token"); - } + assert(!entry->parser); entry->parser = parser; } @@ -8604,11 +8498,7 @@ static void register_infix_parser(parse_expression_infix_function parser, { expression_parser_function_t *entry = &expression_parsers[token_kind]; - if (entry->infix_parser != NULL) { - diagnosticf("for token '%k'\n", (token_kind_t)token_kind); - panic("trying to register multiple infix expression parsers for a " - "token"); - } + assert(!entry->infix_parser); entry->infix_parser = parser; entry->infix_precedence = precedence; } @@ -8694,9 +8584,9 @@ static asm_argument_t *parse_asm_arguments(bool is_out) return NULL; } - argument->constraints = parse_string_literals(); - expect('('); + argument->constraints = parse_string_literals("asm argument"); add_anchor_token(')'); + expect('('); expression_t *expression = parse_expression(); rem_anchor_token(')'); if (is_out) { @@ -8781,7 +8671,7 @@ static asm_clobber_t *parse_asm_clobbers(void) while (token.kind == T_STRING_LITERAL) { asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0])); - clobber->clobber = parse_string_literals(); + clobber->clobber = parse_string_literals(NULL); *anchor = clobber; anchor = &clobber->next; @@ -8802,40 +8692,27 @@ static statement_t *parse_asm_statement(void) asm_statement_t *asm_statement = &statement->asms; eat(T_asm); + add_anchor_token(')'); + add_anchor_token(':'); + add_anchor_token(T_STRING_LITERAL); if (next_if(T_volatile)) asm_statement->is_volatile = true; expect('('); - add_anchor_token(')'); - if (token.kind != T_STRING_LITERAL) { - parse_error_expected("after asm(", T_STRING_LITERAL, NULL); - goto end_of_asm; - } - asm_statement->asm_text = parse_string_literals(); + rem_anchor_token(T_STRING_LITERAL); + asm_statement->asm_text = parse_string_literals("asm statement"); - add_anchor_token(':'); - if (!next_if(':')) { - rem_anchor_token(':'); - goto end_of_asm; - } + if (next_if(':')) + asm_statement->outputs = parse_asm_arguments(true); - asm_statement->outputs = parse_asm_arguments(true); - if (!next_if(':')) { - rem_anchor_token(':'); - goto end_of_asm; - } + if (next_if(':')) + asm_statement->inputs = parse_asm_arguments(false); - asm_statement->inputs = parse_asm_arguments(false); - if (!next_if(':')) { - rem_anchor_token(':'); - goto end_of_asm; - } rem_anchor_token(':'); + if (next_if(':')) + asm_statement->clobbers = parse_asm_clobbers(); - asm_statement->clobbers = parse_asm_clobbers(); - -end_of_asm: rem_anchor_token(')'); expect(')'); expect(';'); @@ -8864,7 +8741,7 @@ static statement_t *parse_label_inner_statement(statement_t const *const label, * statement after a label. label:; is commonly used to have a label * before a closing brace. */ inner_stmt = create_empty_statement(); - next_token(); + eat(';'); break; } /* FALLTHROUGH */ @@ -9034,7 +8911,7 @@ static statement_t *parse_default_statement(void) static statement_t *parse_label_statement(void) { statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL); - label_t *const label = get_label(); + label_t *const label = get_label(NULL /* Cannot fail, token is T_IDENTIFIER. */); statement->label.label = label; PUSH_PARENT(statement); @@ -9082,8 +8959,8 @@ static statement_t *parse_inner_statement(void) */ static expression_t *parse_condition(void) { - expect('('); add_anchor_token(')'); + expect('('); expression_t *const expr = parse_expression(); mark_vars_read(expr, NULL); rem_anchor_token(')'); @@ -9299,8 +9176,8 @@ static statement_t *parse_for(void) PUSH_PARENT(statement); PUSH_SCOPE_STATEMENT(&statement->fors.scope); - expect('('); add_anchor_token(')'); + expect('('); PUSH_EXTENSION(); @@ -9381,8 +9258,9 @@ static statement_t *parse_goto(void) } else { statement = allocate_statement_zero(STATEMENT_GOTO); eat(T_goto); - if (token.kind == T_IDENTIFIER) { - label_t *const label = get_label(); + + label_t *const label = get_label("while parsing goto"); + if (label) { label->used = true; statement->gotos.label = label; @@ -9390,11 +9268,6 @@ static statement_t *parse_goto(void) *goto_anchor = &statement->gotos; goto_anchor = &statement->gotos.next; } else { - if (GNU_MODE) - parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL); - else - parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); - eat_until_anchor(); statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous, &builtin_source_position)->label; } } @@ -9486,22 +9359,6 @@ static bool expression_is_local_variable(const expression_t *expression) return is_local_variable(entity); } -/** - * Check if a given expression represents a local variable and - * return its declaration then, else return NULL. - */ -entity_t *expression_is_variable(const expression_t *expression) -{ - if (expression->base.kind != EXPR_REFERENCE) { - return NULL; - } - entity_t *entity = expression->reference.entity; - if (entity->kind != ENTITY_VARIABLE) - return NULL; - - return entity; -} - static void err_or_warn(source_position_t const *const pos, char const *const msg) { if (c_mode & _CXX || strict_mode) { @@ -9656,29 +9513,31 @@ static statement_t *parse_local_label_declaration(void) entity_t *begin = NULL; entity_t *end = NULL; entity_t **anchor = &begin; + add_anchor_token(';'); + add_anchor_token(','); do { source_position_t pos; symbol_t *const symbol = expect_identifier("while parsing local label declaration", &pos); - if (!symbol) - goto end_error; - - entity_t *entity = get_entity(symbol, NAMESPACE_LABEL); - if (entity != NULL && entity->base.parent_scope == current_scope) { - source_position_t const *const ppos = &entity->base.source_position; - errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos); - } else { - entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol, &pos); - entity->base.parent_scope = current_scope; + if (symbol) { + entity_t *entity = get_entity(symbol, NAMESPACE_LABEL); + if (entity != NULL && entity->base.parent_scope == current_scope) { + source_position_t const *const ppos = &entity->base.source_position; + errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos); + } else { + entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol, &pos); + entity->base.parent_scope = current_scope; - *anchor = entity; - anchor = &entity->base.next; - end = entity; + *anchor = entity; + anchor = &entity->base.next; + end = entity; - environment_push(entity); + environment_push(entity); + } } } while (next_if(',')); + rem_anchor_token(','); + rem_anchor_token(';'); expect(';'); -end_error: statement->declaration.declarations_begin = begin; statement->declaration.declarations_end = end; return statement; @@ -9693,18 +9552,14 @@ static void parse_namespace_definition(void) if (token.kind == T_IDENTIFIER) { symbol = token.base.symbol; - next_token(); - entity = get_entity(symbol, NAMESPACE_NORMAL); - if (entity != NULL - && entity->kind != ENTITY_NAMESPACE - && entity->base.parent_scope == current_scope) { - if (is_entity_valid(entity)) { - error_redefined_as_different_kind(&token.base.source_position, - entity, ENTITY_NAMESPACE); - } + if (entity && entity->kind != ENTITY_NAMESPACE) { entity = NULL; + if (entity->base.parent_scope == current_scope && is_entity_valid(entity)) { + error_redefined_as_different_kind(HERE, entity, ENTITY_NAMESPACE); + } } + eat(T_IDENTIFIER); } if (entity == NULL) { @@ -9870,12 +9725,9 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) add_anchor_token(T_MINUSMINUS); add_anchor_token(T_PLUSPLUS); add_anchor_token(T_STRING_LITERAL); - add_anchor_token(T_WIDE_CHARACTER_CONSTANT); - add_anchor_token(T_WIDE_STRING_LITERAL); add_anchor_token(T__Bool); add_anchor_token(T__Complex); add_anchor_token(T__Imaginary); - add_anchor_token(T___FUNCTION__); add_anchor_token(T___PRETTY_FUNCTION__); add_anchor_token(T___alignof__); add_anchor_token(T___attribute__); @@ -10043,12 +9895,9 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) rem_anchor_token(T___attribute__); rem_anchor_token(T___alignof__); rem_anchor_token(T___PRETTY_FUNCTION__); - rem_anchor_token(T___FUNCTION__); rem_anchor_token(T__Imaginary); rem_anchor_token(T__Complex); rem_anchor_token(T__Bool); - rem_anchor_token(T_WIDE_STRING_LITERAL); - rem_anchor_token(T_WIDE_CHARACTER_CONSTANT); rem_anchor_token(T_STRING_LITERAL); rem_anchor_token(T_PLUSPLUS); rem_anchor_token(T_MINUSMINUS); @@ -10122,7 +9971,7 @@ static void parse_global_asm(void) expect('('); rem_anchor_token(T_STRING_LITERAL); - statement->asms.asm_text = parse_string_literals(); + statement->asms.asm_text = parse_string_literals("global asm"); statement->base.next = unit->global_asm; unit->global_asm = statement; @@ -10137,7 +9986,7 @@ static void parse_linkage_specification(void) eat(T_extern); source_position_t const pos = *HERE; - char const *const linkage = parse_string_literals().begin; + char const *const linkage = parse_string_literals(NULL).begin; linkage_kind_t old_linkage = current_linkage; linkage_kind_t new_linkage; @@ -10194,7 +10043,7 @@ static void parse_external(void) case ';': if (!strict_mode) { warningf(WARN_STRAY_SEMICOLON, HERE, "stray ';' outside of function"); - next_token(); + eat(';'); return; } /* FALLTHROUGH */ @@ -10275,7 +10124,6 @@ void start_parsing(void) { environment_stack = NEW_ARR_F(stack_entry_t, 0); label_stack = NEW_ARR_F(stack_entry_t, 0); - diagnostic_count = 0; error_count = 0; warning_count = 0;