X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=b33c140956598a2e3bab6a434ac20a6e17b6321e;hb=1a01d49a5f4858ede8175221921be0e3719ea2a6;hp=fc156f475649ca929b06dee155e75357b34bf30a;hpb=9795a8c46d189b43d47dca502a9394a8d89c786e;p=cparser diff --git a/parser.c b/parser.c index fc156f4..b33c140 100644 --- a/parser.c +++ b/parser.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -247,16 +248,12 @@ static void semantic_comparison(binary_expression_t *expression); case '~': \ case T_ANDAND: \ case T_CHARACTER_CONSTANT: \ - case T_FLOATINGPOINT: \ - case T_INTEGER: \ + case T_NUMBER: \ 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), @@ -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,12 +481,17 @@ static inline void next_token(void) #endif } -#define eat(token_kind) (assert(token.kind == (token_kind)), next_token()) +static inline void eat(token_kind_t const kind) +{ + assert(token.kind == kind); + (void)kind; + next_token(); +} -static inline bool next_if(token_kind_t const type) +static inline bool next_if(token_kind_t const kind) { - if (token.kind == type) { - eat(type); + if (token.kind == kind) { + eat(kind); return true; } else { return false; @@ -631,33 +630,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 +1036,62 @@ 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(string_encoding_t const enc) { - 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, enc }; +} - eat(T_STRING_LITERAL); +static string_t concat_string_literals(void) +{ + assert(token.kind == T_STRING_LITERAL); - while (token.kind == T_STRING_LITERAL) { - warn_string_concat(HERE); - result = concat_strings(&result, &token.string.string); + string_t result; + if (look_ahead(1)->kind == T_STRING_LITERAL) { + append_string(&token.literal.string); + eat(T_STRING_LITERAL); + warningf(WARN_TRADITIONAL, HERE, "traditional C rejects string constant concatenation"); + string_encoding_t enc = token.literal.string.encoding; + do { + if (token.literal.string.encoding != STRING_ENCODING_CHAR) { + enc = token.literal.string.encoding; + } + append_string(&token.literal.string); + eat(T_STRING_LITERAL); + } while (token.kind == T_STRING_LITERAL); + result = finish_string(enc); + } else { + result = token.literal.string; eat(T_STRING_LITERAL); } 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_CHAR }; + + source_position_t const pos = *HERE; + string_t const res = concat_string_literals(); + + if (res.encoding != 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)); @@ -1456,9 +1490,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: @@ -1512,31 +1546,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 +1554,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.value.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; + } } } @@ -2057,9 +2059,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(','); @@ -2208,13 +2208,10 @@ 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: { + size = get_string_len(&get_init_string(result)->value) + 1; break; + } case INITIALIZER_DESIGNATOR: case INITIALIZER_VALUE: @@ -2468,6 +2465,7 @@ static type_t *parse_typeof(void) } typedef enum specifiers_t { + SPECIFIER_NONE = 0, SPECIFIER_SIGNED = 1 << 0, SPECIFIER_UNSIGNED = 1 << 1, SPECIFIER_LONG = 1 << 2, @@ -3006,7 +3004,8 @@ warn_about_long_long: } else { errorf(pos, "multiple datatypes in declaration"); } - goto end_error; + specifiers->type = type_error_type; + return; } } @@ -3035,10 +3034,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) @@ -4622,8 +4617,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: @@ -4708,7 +4703,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; } @@ -5473,8 +5467,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; @@ -5681,14 +5674,14 @@ struct expression_parser_function_t { static expression_parser_function_t expression_parsers[T_LAST_TOKEN]; -static type_t *get_string_type(void) -{ - return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr; -} - -static type_t *get_wide_string_type(void) +static type_t *get_string_type(string_encoding_t const enc) { - 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"); } /** @@ -5696,31 +5689,10 @@ static type_t *get_wide_string_type(void) */ static expression_t *parse_string_literal(void) { - source_position_t begin = *HERE; - 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(HERE); - 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->base.type = get_string_type(expr->string_literal.value.encoding); + return expr; } /** @@ -5737,110 +5709,204 @@ static expression_t *parse_boolean_literal(bool value) return literal; } -static void warn_traditional_suffix(void) +static void warn_traditional_suffix(char const *const suffix) { - warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%S' suffix", - &token.number.suffix); + warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix); } -static void check_integer_suffix(void) +static void check_integer_suffix(expression_t *const expr, char const *const suffix) { - const string_t *suffix = &token.number.suffix; - if (suffix->size == 0) - return; - - bool not_traditional = false; - const char *c = suffix->begin; - if (*c == 'l' || *c == 'L') { - ++c; - if (*c == *(c-1)) { - not_traditional = true; - ++c; - if (*c == 'u' || *c == 'U') { + unsigned spec = SPECIFIER_NONE; + char const *c = suffix; + for (;;) { + specifiers_t add; + if (*c == 'L' || *c == 'l') { + add = SPECIFIER_LONG; + if (*c == c[1]) { + add |= SPECIFIER_LONG_LONG; ++c; } - } else if (*c == 'u' || *c == 'U') { - not_traditional = true; - ++c; + } else if (*c == 'U' || *c == 'u') { + add = SPECIFIER_UNSIGNED; + } else { + break; } - } else if (*c == 'u' || *c == 'U') { - not_traditional = true; ++c; - if (*c == 'l' || *c == 'L') { - ++c; - if (*c == *(c-1)) { - ++c; - } - } - } - if (*c != '\0') { - errorf(HERE, "invalid suffix '%S' on integer constant", suffix); - } else if (not_traditional) { - warn_traditional_suffix(); + if (spec & add) + goto error; + spec |= add; + } + + if (*c == '\0') { + type_t *type; + switch (spec) { + case SPECIFIER_NONE: type = type_int; break; + case SPECIFIER_LONG: type = type_long; break; + case SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_long_long; break; + case SPECIFIER_UNSIGNED: type = type_unsigned_int; break; + case SPECIFIER_UNSIGNED | SPECIFIER_LONG: type = type_unsigned_long; break; + case SPECIFIER_UNSIGNED | SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_unsigned_long_long; break; + default: panic("inconsistent suffix"); + } + if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG) { + warn_traditional_suffix(suffix); + } + expr->base.type = type; + /* Integer type depends on the size of the number and the size + * representable by the types. The backend/codegeneration has to + * determine that. */ + determine_literal_type(&expr->literal); + } else { +error: + errorf(HERE, "invalid suffix '%s' on integer constant", suffix); } } -static type_t *check_floatingpoint_suffix(void) +static void check_floatingpoint_suffix(expression_t *const expr, char const *const suffix) { - const string_t *suffix = &token.number.suffix; - type_t *type = type_double; - if (suffix->size == 0) - return type; - - bool not_traditional = false; - const char *c = suffix->begin; - if (*c == 'f' || *c == 'F') { - ++c; - type = type_float; - } else if (*c == 'l' || *c == 'L') { - ++c; - type = type_long_double; - } - if (*c != '\0') { - errorf(HERE, "invalid suffix '%S' on floatingpoint constant", suffix); - } else if (not_traditional) { - warn_traditional_suffix(); + type_t *type; + char const *c = suffix; + switch (*c) { + case 'F': + case 'f': type = type_float; ++c; break; + case 'L': + case 'l': type = type_long_double; ++c; break; + default: type = type_double; break; } - return type; + if (*c == '\0') { + expr->base.type = type; + if (suffix[0] != '\0') { + warn_traditional_suffix(suffix); + } + } else { + errorf(HERE, "invalid suffix '%s' on floatingpoint constant", suffix); + } } -/** - * Parse an integer constant. - */ static expression_t *parse_number_literal(void) { - expression_kind_t kind; - type_t *type; + string_t const *const str = &token.literal.string; + char const * i = str->begin; + unsigned digits = 0; + bool is_float = false; - switch (token.kind) { - case T_INTEGER: - kind = EXPR_LITERAL_INTEGER; - check_integer_suffix(); - type = type_int; + /* Parse base prefix. */ + unsigned base; + if (*i == '0') { + switch (*++i) { + case 'B': case 'b': base = 2; ++i; break; + case 'X': case 'x': base = 16; ++i; break; + default: base = 8; digits |= 1U << 0; break; + } + } else { + base = 10; + } + + /* Parse mantissa. */ + for (;; ++i) { + unsigned digit; + switch (*i) { + case '.': + if (is_float) { + errorf(HERE, "multiple decimal points in %K", &token); + i = 0; + goto done; + } + is_float = true; + if (base == 8) + base = 10; + continue; + + case '0': digit = 0; break; + case '1': digit = 1; break; + case '2': digit = 2; break; + case '3': digit = 3; break; + case '4': digit = 4; break; + case '5': digit = 5; break; + case '6': digit = 6; break; + case '7': digit = 7; break; + case '8': digit = 8; break; + case '9': digit = 9; break; + case 'A': case 'a': digit = 10; break; + case 'B': case 'b': digit = 11; break; + case 'C': case 'c': digit = 12; break; + case 'D': case 'd': digit = 13; break; + case 'E': case 'e': digit = 14; break; + case 'F': case 'f': digit = 15; break; + + default: goto done_mantissa; + } + + if (digit >= 10 && base != 16) + goto done_mantissa; + + digits |= 1U << digit; + } +done_mantissa: + + /* Parse exponent. */ + switch (base) { + case 2: + if (is_float) + errorf(HERE, "binary floating %K not allowed", &token); break; - case T_FLOATINGPOINT: - kind = EXPR_LITERAL_FLOATINGPOINT; - type = check_floatingpoint_suffix(); + case 8: + case 10: + if (*i == 'E' || *i == 'e') { + base = 10; + goto parse_exponent; + } + break; + + case 16: + if (*i == 'P' || *i == 'p') { +parse_exponent: + ++i; + is_float = true; + + if (*i == '-' || *i == '+') + ++i; + + if (isdigit(*i)) { + do { + ++i; + } while (isdigit(*i)); + } else { + errorf(HERE, "exponent of %K has no digits", &token); + } + } else if (is_float) { + errorf(HERE, "hexadecimal floating %K requires an exponent", &token); + i = 0; + } break; default: - panic("unexpected token type in parse_number_literal"); + panic("invalid base"); } - expression_t *literal = allocate_expression_zero(kind); - literal->base.type = type; - literal->literal.value = token.number.number; - literal->literal.suffix = token.number.suffix; - next_token(); +done:; + expression_t *const expr = allocate_expression_zero(is_float ? EXPR_LITERAL_FLOATINGPOINT : EXPR_LITERAL_INTEGER); + expr->literal.value = *str; - /* integer type depends on the size of the number and the size - * representable by the types. The backend/codegeneration has to determine - * that - */ - determine_literal_type(&literal->literal); - return literal; + if (i) { + if (digits == 0) { + errorf(HERE, "%K has no digits", &token); + } else if (digits & ~((1U << base) - 1)) { + errorf(HERE, "invalid digit in %K", &token); + } else { + expr->literal.suffix = i; + if (is_float) { + check_floatingpoint_suffix(expr, i); + } else { + check_integer_suffix(expr, i); + } + } + } + + eat(T_NUMBER); + return expr; } /** @@ -5848,42 +5914,35 @@ 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.value = token.literal.string; - 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; + size_t const size = get_string_len(&token.literal.string); + switch (token.literal.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; + + case STRING_ENCODING_WIDE: + literal->base.type = type_int; + if (size > 1) { warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); } + break; } eat(T_CHARACTER_CONSTANT); 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"); - } - - eat(T_WIDE_CHARACTER_CONSTANT); - return literal; -} - static entity_t *create_implicit_function(symbol_t *symbol, source_position_t const *const pos) { type_t *ntype = allocate_type_zero(TYPE_FUNCTION); @@ -5969,13 +6028,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.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: @@ -6667,13 +6722,9 @@ static expression_t *parse_primary_expression(void) switch (token.kind) { case T_false: return parse_boolean_literal(false); case T_true: return parse_boolean_literal(true); - case T_INTEGER: - case T_FLOATINGPOINT: return parse_number_literal(); + case T_NUMBER: 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_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); @@ -6894,9 +6945,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'", @@ -7970,8 +8019,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"); } @@ -8309,11 +8357,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; @@ -8531,10 +8577,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; } @@ -8550,11 +8593,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; } @@ -8640,7 +8679,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out) return NULL; } - argument->constraints = parse_string_literals(); + argument->constraints = parse_string_literals("asm argument"); add_anchor_token(')'); expect('('); expression_t *expression = parse_expression(); @@ -8727,7 +8766,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; @@ -8748,40 +8787,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(';'); @@ -9428,22 +9454,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) { @@ -9804,18 +9814,14 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) add_anchor_token('~'); add_anchor_token(T_CHARACTER_CONSTANT); add_anchor_token(T_COLONCOLON); - add_anchor_token(T_FLOATINGPOINT); add_anchor_token(T_IDENTIFIER); - add_anchor_token(T_INTEGER); add_anchor_token(T_MINUSMINUS); + add_anchor_token(T_NUMBER); 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__); @@ -9983,18 +9989,14 @@ 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_NUMBER); rem_anchor_token(T_MINUSMINUS); - rem_anchor_token(T_INTEGER); rem_anchor_token(T_IDENTIFIER); - rem_anchor_token(T_FLOATINGPOINT); rem_anchor_token(T_COLONCOLON); rem_anchor_token(T_CHARACTER_CONSTANT); rem_anchor_token('~'); @@ -10062,7 +10064,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; @@ -10077,7 +10079,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; @@ -10215,7 +10217,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;